diff --git a/build.gradle b/build.gradle index 6ddc7f2..cbd8ae8 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ dependencies { implementation("com.github.codeclimate:codeclimate-ss-analyzer-wrapper:beta-SNAPSHOT") // Plugins - implementation("org.sonarsource.java:sonar-java-plugin:6.15.1.26025") + implementation("org.sonarsource.java:sonar-java-plugin:7.2.0.26923") testImplementation("org.assertj:assertj-core:2.8.0") testImplementation("org.skyscreamer:jsonassert:1.5.0") diff --git a/src/test/resources/sanity_check_expected_issues.json b/src/test/resources/sanity_check_expected_issues.json index ffc582f..7150985 100644 --- a/src/test/resources/sanity_check_expected_issues.json +++ b/src/test/resources/sanity_check_expected_issues.json @@ -5,7 +5,7 @@ "severity": "major", "description": "Provide the parametrized type for this generic.", "content": { - "body": "
Generic types shouldn't be used raw (without type parameters) in variable declarations or return values. Doing so bypasses generic type checking,\nand defers the catch of unsafe code to runtime.
\n\nList myList; // Noncompliant\nSet mySet; // Noncompliant\n\n
\nList<String> myList;\nSet<? extends Number> mySet;\n" + "body": "
Generic types shouldn’t be used raw (without type parameters) in variable declarations or return values. Doing so bypasses generic type checking,\nand defers the catch of unsafe code to runtime.
\n\nList myList; // Noncompliant\nSet mySet; // Noncompliant\n\n
\nList<String> myList;\nSet<? extends Number> mySet;\n" }, "location": { "path": "main/java/Library.java", @@ -24,7 +24,7 @@ "severity": "major", "description": "Provide the parametrized type for this generic.", "content": { - "body": "
Generic types shouldn't be used raw (without type parameters) in variable declarations or return values. Doing so bypasses generic type checking,\nand defers the catch of unsafe code to runtime.
\n\nList myList; // Noncompliant\nSet mySet; // Noncompliant\n\n
\nList<String> myList;\nSet<? extends Number> mySet;\n" + "body": "
Generic types shouldn’t be used raw (without type parameters) in variable declarations or return values. Doing so bypasses generic type checking,\nand defers the catch of unsafe code to runtime.
\n\nList myList; // Noncompliant\nSet mySet; // Noncompliant\n\n
\nList<String> myList;\nSet<? extends Number> mySet;\n" }, "location": { "path": "main/java/Library.java", @@ -37,25 +37,6 @@ "Clarity" ] }, - { - "type": "issue", - "check_name": "java:S1220", - "severity": "minor", - "description": "Move this file to a named package.", - "content": { - "body": "
According to the Java Language Specification:
\n\n\nUnnamed packages are provided by the Java platform principally for convenience when developing small or temporary applications or when just\n beginning development.
\n
To enforce this best practice, classes located in default package can no longer be accessed from named ones since Java 1.4.
\n\npublic class MyClass { /* ... */ }\n\n
\npackage org.example;\n\npublic class MyClass{ /* ... */ }\n" - }, - "location": { - "path": "main/java/Library.java", - "lines": { - "begin": 1, - "end": 1 - } - }, - "categories": [ - "Style" - ] - }, { "type": "issue", "check_name": "java:S1134", @@ -100,7 +81,7 @@ "severity": "major", "description": "Replace this use of System.out or System.err by a logger.", "content": { - "body": "
When logging a message there are several important requirements which must be fulfilled:
\nIf a program directly writes to the standard outputs, there is absolutely no way to comply with those requirements. That's why defining and using a\ndedicated logger is highly recommended.
\n\nSystem.out.println(\"My Message\"); // Noncompliant\n\n
\nlogger.log(\"My Message\");\n\n
When logging a message there are several important requirements which must be fulfilled:
\nIf a program directly writes to the standard outputs, there is absolutely no way to comply with those requirements. That’s why defining and using a\ndedicated logger is highly recommended.
\n\nSystem.out.println(\"My Message\"); // Noncompliant\n\n
\nlogger.log(\"My Message\");\n\n
A dead store happens when a local variable is assigned a value that is not read by any subsequent instruction. Calculating or retrieving a value\nonly to then overwrite it or throw it away, could indicate a serious error in the code. Even if it’s not an error, it is at best a waste of resources.\nTherefore all calculated values should be used.
\n\ni = a + b; // Noncompliant; calculation result not used before value is overwritten\ni = compute();\n\n
\ni = a + b;\ni += compute();\n\n
This rule ignores initializations to -1, 0, 1, null
, true
, false
and \"\"
.
The instanceof
construction is a preferred way to check whether a variable can be cast to some type statically because a compile-time\nerror will occur in case of incompatible types. The method isInstance() from java.lang.Class
\nworks differently and does type check at runtime only, incompatible types will therefore not be detected early in the developement, potentially\nresulting in dead code. The isInstance()
method should only be used in dynamic cases when the instanceof
operator can't be\nused.
This rule raises an issue when isInstance()
is used and could be replaced with an instanceof
check.
\nint f(Object o) {\n if (String.class.isInstance(o)) { // Noncompliant\n return 42;\n }\n return 0;\n}\n\nint f(Number n) {\n if (String.class.isInstance(n)) { // Noncompliant\n return 42;\n }\n return 0;\n}\n\n\n
\nint f(Object o) {\n if (o instanceof String) { // Compliant\n return 42;\n }\n return 0;\n}\n\nint f(Number n) {\n if (n instanceof String) { // Compile-time error\n return 42;\n }\n return 0;\n}\n\nboolean fun(Object o, String c) throws ClassNotFoundException\n{\n return Class.forName(c).isInstance(o); // Compliant, can't use instanceof operator here\n}\n" + "body": "
The instanceof
construction is a preferred way to check whether a variable can be cast to some type statically because a compile-time\nerror will occur in case of incompatible types. The method isInstance() from java.lang.Class
\nworks differently and does type check at runtime only, incompatible types will therefore not be detected early in the developement, potentially\nresulting in dead code. The isInstance()
method should only be used in dynamic cases when the instanceof
operator can’t be\nused.
This rule raises an issue when isInstance()
is used and could be replaced with an instanceof
check.
\nint f(Object o) {\n if (String.class.isInstance(o)) { // Noncompliant\n return 42;\n }\n return 0;\n}\n\nint f(Number n) {\n if (String.class.isInstance(n)) { // Noncompliant\n return 42;\n }\n return 0;\n}\n\n
\nint f(Object o) {\n if (o instanceof String) { // Compliant\n return 42;\n }\n return 0;\n}\n\nint f(Number n) {\n if (n instanceof String) { // Compile-time error\n return 42;\n }\n return 0;\n}\n\nboolean fun(Object o, String c) throws ClassNotFoundException\n{\n return Class.forName(c).isInstance(o); // Compliant, can't use instanceof operator here\n}\n" }, "location": { "path": "main/java/Library.java", @@ -157,7 +138,7 @@ "severity": "minor", "description": "Use simple literal for a single-line string.", "content": { - "body": "
If a string fits on a single line, without concatenation and escaped newlines, you should probably continue to use a string literal.
\n\nString question = \"\"\"\n What's the point, really?\"\"\";\n\n
\nString question = \"What's the point, really?\";\n\n
If a string fits on a single line, without concatenation and escaped newlines, you should probably continue to use a string literal.
\n\nString question = \"\"\"\n What's the point, really?\"\"\";\n\n
\nString question = \"What's the point, really?\";\n\n
The use of escape sequences is mostly unnecessary in text blocks.
\n\\n
can be replaced by simply introducing the newline, \\\"\\\"\\\"
it is sufficient to escape only the first qoute.
\nString textBlock = \"\"\"\n \\\"\\\"\\\" this \\nis\n text block!\n !!!!\n \"\"\";\n\n
\nString textBlock = \"\"\"\n \\\"\"\" this\n is\n text block!\n !!!!\n \"\"\";\n\n
The use of escape sequences is mostly unnecessary in text blocks.
\n\\n
can be replaced by simply introducing the newline, \\\"\\\"\\\"
it is sufficient to escape only the first qoute.
\nString textBlock = \"\"\"\n \\\"\\\"\\\" this \\nis\n text block!\n !!!!\n \"\"\";\n\n
\nString textBlock = \"\"\"\n \\\"\"\" this\n is\n text block!\n !!!!\n \"\"\";\n\n
If a local variable is declared but not used, it is dead code and should be removed. Doing so will improve maintainability because developers will\nnot wonder what the variable is used for.
\n\npublic int numberOfMinutes(int hours) {\n int seconds = 0; // seconds is never used\n return hours * 60;\n}\n\n
\npublic int numberOfMinutes(int hours) {\n return hours * 60;\n}\n" }, "location": { "path": "main/java/Library.java", @@ -207,5 +188,24 @@ "categories": [ "Clarity" ] + }, + { + "type": "issue", + "check_name": "java:S1220", + "severity": "minor", + "description": "Move this file to a named package.", + "content": { + "body": "
According to the Java Language Specification:
\n\n\nUnnamed packages are provided by the Java platform principally for convenience when developing small or temporary applications or when just\n beginning development.
\n
To enforce this best practice, classes located in default package can no longer be accessed from named ones since Java 1.4.
\n\npublic class MyClass { /* ... */ }\n\n
\npackage org.example;\n\npublic class MyClass{ /* ... */ }\n" + }, + "location": { + "path": "main/java/Library.java", + "lines": { + "begin": 1, + "end": 1 + } + }, + "categories": [ + "Style" + ] } ]