** ErrorProne ** is a Java static analysis tool made by Google. The big difference from other static analysis tools (such as FindBugs) is that the check NG ** will result in a compilation error **.
Below, quoted from Official Site
It’s common for even the best programmers to make simple mistakes. And sometimes a refactoring which seems safe can leave behind code which will never do what’s intended.
We’re used to getting help from the compiler, but it doesn’t do much beyond static type checking. Using Error Prone to augment the compiler’s type analysis, you can catch more mistakes before they cost you time, or end up as bugs in production. We use Error Prone in Google’s Java build system to eliminate classes of serious bugs from entering our code, and we’ve open-sourced it, so you can too!
It is said that Google also uses this for static analysis. The bug patterns to be checked are described in here.
This time, we built the following verification environment.
IntelliJ IDEA 2019.2.2
5.6.2
jdk11.0.3_7 (Amazon Corretto)
Created IntelliJ Gradle project.
In addition, looking at the official website, it seems that it corresponds to the following.
--Build tools: Bazel, Maven, Gradle, Ant
Note that ErrorProne requires JDK9
or higher.
The following build files are prepared to run ErrorProne.
build.gradle
plugins {
id 'java'
id "net.ltgt.errorprone" version "0.8.1"
}
group 'errorprone-sample2'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
errorprone("com.google.errorprone:error_prone_core:2.+")
}
def defaultEncoding = 'UTF-8'
tasks.withType(AbstractCompile) each { it.options.encoding = defaultEncoding }
compileTestJava {
options.encoding = defaultEncoding
}
//tasks.withType(JavaCompile) {
// options.errorprone {
// disableAllChecks = true //Disable all checks
// enable("CollectionIncompatibleType", "ArrayToString") //Enable the check specified earlier
// }
//}
We will verify the bug pattern check by ErrorProne. CollectionIncompatibleType Incompatible type as argument to Object-accepting Java collections method
public class CollectionIncompatibleTypeSample {
public static void main(String... args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "One");
map.put(2, "Two");
map.get("1"); //Different type from generics
map.remove("2"); //Different type from generics
}
}
src\main\java\CollectionIncompatibleTypeSample.java:10:error: [CollectionIncompatibleType] Argument '"1"' should not be passed to t
his method; its type String is not compatible with its collection's type argument Integer
map.get("1"); //Different type from generics
^
(see https://errorprone.info/bugpattern/CollectionIncompatibleType)
src\main\java\CollectionIncompatibleTypeSample.java:11:error: [CollectionIncompatibleType] Argument '"2"' should not be passed to t
his method; its type String is not compatible with its collection's type argument Integer
map.remove("2"); //Different type from generics
^
(see https://errorprone.info/bugpattern/CollectionIncompatibleType)
In java.util.Map
, the argument type of the above method is ʻObject`, so the above usually does not cause a compile error.
However, since this is an implementation error, ErrorProne will result in a compilation error.
ArrayToString Calling toString on an array does not provide useful information
public class ArrayToStringSample {
public static void main(String... args) {
int[] ary = {1, 2, 3};
System.out.println(ary); // => [I@3ac3fd8b
System.out.println(Arrays.toString(ary)); // => [1, 2, 3]
}
}
System.out.println ()
implicitly calls thetoString ()
method.src\main\java\ArrayToStringSample.java:6:error: [ArrayToString] Calling toString on an array does not provide useful information
System.out.println(ary); // => [I@3ac3fd8b
^
(see https://errorprone.info/bugpattern/ArrayToString)
Did you mean 'System.out.println(Arrays.toString(ary));'?
Using the toString ()
method of an array is often incorrect, so ErrorProne will result in a compilation error.
FormatString Invalid printf-style format string
public class FormatStringSample {
public static void main(String... args) {
String text1 = String.format("arg1: %d. arg2: %s", 1, "a");
System.out.println(text1); // => arg1: 1. arg2: a
String text2 = String.format("arg1: %d. arg2: %s", "2", "b");
System.out.println(text2); // => java.util.IllegalFormatConversionException: d != java.lang.String
}
}
text2
throws ʻIllegalFormatConversionException because the format string of
String.format () `and the argument type are different.
src\main\java\FormatStringSample.java:5:error: [FormatString] illegal format conversion: 'java.lang.String' cannot be formatted usi
ng '%d'
String text2 = String.format("arg1: %d. arg2: %s", "2", "b");
^
(see https://errorprone.info/bugpattern/FormatString)
If the format string and the argument type are different, an exception is thrown at runtime without a compile error, but ErrorProne causes a compile error.
You may want to enable only some checks in the following cases.
--Many check NGs with existing code --Intentionally written code becomes check NG
In that case, only some checks can be enabled by setting as follows.
tasks.withType(JavaCompile) {
options.errorprone {
disableAllChecks = true //Disable all checks
enable("CollectionIncompatibleType", "ArrayToString") //Enable the check specified earlier
}
}
InteliJ will issue a warning for the above part, so I think that there is basically no problem if it corresponds to the IDE warning, but Some people in the world ignore IDE warnings, so if there is a compile error, it will be enforced, so it looks good.
Also, since you can notice the error at the time of compilation, I thought it would be less likely to waste time like sending back a test.
Recommended Posts