Adding Error Prone checker Java 8 Gradle project
Error Prone is a Java code checker developed by Google. In comparison to other code checkers like PMD and FindBugs, it excels at identifying more concise, hard-to-notice bugs. It is actively developed and has a wide list of rules.
Initially, I thought that adding this checker to an existing legacy project would be a trivial task. However, surprisingly, just adding a Gradle plugin didn't work. Therefore, I integrated it directly into the Gradle build file. In this article, I'll show you how to add Error Prone to your Java 8 project. For a quick summary, refer to the TLDR section.
Project Structure
Our project is a monolith code base with more than 100 sub-projects and almost 500K lines of code, all written in Java 8. The code is built using Java 8 JVM and Gradle 7.4.1.
Gradle Plugin
The recommended way of using Error Prone plugin with Gradle project didn't work for me. So I had to integrate it directly into our Gradle build file. Thankfully, just by reading the plugin code and referring to other examples on GitHub made task task much easier for me.
The Goal
My goal was to integrate Error Prone at the project level that my team was responsible for, instead of adding it to the root build file. This approach had a few advantages:
- We wouldn't need to fix all compilation errors, but only those generated in our projects.
- If something went wrong, only our module would fail and it wouldn't affect anything else.
- If our endeavor with Error Prone went well, we could introduce this checker higher in the project structure.
Enabling Error-Prone in Gradle
For every module, Gradle creates a task called compileJava
, which is used for compiling source code. Error Prone provides a Java compiler that can be used as a replacement for the default Javac to execute the compileJava
task. To achieve this, we use the fork option of Gradle, which initiates a new child process for the Java compilation task:
compileJava {
options.fork = true
...
}
If you're using any annotation processors like Lombok, you'll need to include them in the options as well:
options.annotationProcessorPath += configurations.checkerFrameworkCheckerJar
To use the Error Prone compiler, you'll need to set it as the bootclasspath
option in compilerArgs
:
options.compilerArgs = ["-Xbootclasspath/p:${configurations.errorProneJavac.asPath}".toString(),
'-XDcompilePolicy=simple',
'-Xplugin:ErrorProne']
and jvmArgs
:
options.forkOptions.with {
jvmArgs = ["-Xbootclasspath/p:${configurations.errorProneJavac.asPath}".toString()]
}
One gotcha to be aware of is the version of the Error Prone jar to use. In my case, due to using Java 8, I had to stick to version 2.10.
Most Popular Error-Prone Bugs I Found
Here are the most common Error-Prone bugs I found:
- Incorrect number of arguments for the
String.format
method. Since I'm dealing with legacy code, I suspect mistakes were made a long time ago. Nowadays IntelliJ IDEA will notify about missing arguments. - Unused return value. In most cases, it's harmless leftover code, but sometimes you may forget to reuse the results, for example, of the
str.substring
returned value. - The winner! Incorrect conversion of an array into a string. Never use
.toString()
, always useArrays.toString()
.
TLDR Version
To quickly integrate Error Prone into the Java compile task, add the following snippet: Add the following snipped to Java compile task:
afterEvaluate {
compileJava {
options.fork = true
options.annotationProcessorPath += configurations.checkerFrameworkCheckerJar
options.compilerArgs = ["-Xbootclasspath/p:${configurations.errorProneJavac.asPath}".toString(),
'-XDcompilePolicy=simple',
'-Xplugin:ErrorProne']
options.forkOptions.with {
jvmArgs = ["-Xbootclasspath/p:${configurations.errorProneJavac.asPath}".toString()]
}
}
}
Use these specific versions:
errorProneJavac group: 'com.google.errorprone', name: 'javac', version: '9+181-r4173-1'
checkerFrameworkCheckerJar(
'com.google.errorprone:error_prone_core:2.10.0',
'org.checkerframework:dataflow-errorprone:3.15.0'
)
Happy coding!
Discuss on Twitter