checkerframework-gradle-plugin
checkerframework-gradle-plugin copied to clipboard
Compile tasks for additional source sets don't include the checker framework dependency
Originally reported here https://github.com/typetools/checker-framework/issues/5787, the problem is that an additional source set which I added did not receive the compileOnly dependencies like the main and test source sets. This leads to this strange error
Caused by: java.lang.NullPointerException: Cannot invoke "java.util.TreeSet.clear()" because "this.messageStore" is null
at org.checkerframework.common.basetype.BaseTypeChecker.typeProcess(BaseTypeChecker.java:537)
at org.checkerframework.javacutil.AbstractTypeProcessor$AttributionTaskListener.finished(AbstractTypeProcessor.java:188)
at jdk.compiler/com.sun.tools.javac.api.ClientCodeWrapper$WrappedTaskListener.finished(ClientCodeWrapper.java:854)
at jdk.compiler/com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:132)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1394)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1351)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:946)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
... 31 more
because the compile task doesn't have the -qual
artifact in the compileOnly
configuration. I understand that this might be a self made problem, but I think that the plugin should try to add the dependencies to all compile tasks.
Thanks for reporting and figuring out the root cause! I would have expected the plugin to handle your use case properly: in some places, we're applying CF options to all tasks derived from AbstractCompile
, but we don't do that when adding dependencies.
The reason we don't is that AbstractCompile
doesn't give us the right APIs to add checker.jar
to the processorPath in a safe way (and, depending on the rest of the project's configuration, we might not want to do so blindly, because of e.g., the need to avoid/continue triggering annotation processor search).
However, your issue is with checker-qual.jar
rather than checker.jar
. So, one solution would be to maintain the current behavior for the checkers themselves (which we definitely don't want to accidentally put onto a classpath where they don't belong, because they're a large dependency), but to blindly add checker-qual
to the classpath of any AbstractCompile
task we come across (using the recommended method in the Gradle docs to add a dependency to all tasks matching a particular type). The downside of this approach is that we might accidentally add checker-qual
to some classpaths where it doesn't belong. That jar is small (it only contains the annotations), so the cost there is relatively low even if we add it somewhere it doesn't belong, but users might not like that behavior.
@kelloggm FWIW, I did run into this issue today, with a very simple setup. In fact, simply applying the plugin with at least one checker and adding one source set triggers the error. MWE
You suggested adding checker-qual
blindly to all AbstractCompile
tasks - in this case, an easier and more conservative approach might be to detect what is happening and make the error message more clear?
@all A workaround is to simply add a compile-only dependency on the offending source set:
sourceSets {
abcd {}
}
dependencies {
abcdCompileOnly 'org.checkerframework:checker-qual:3.42.0'
}