4

I'm working on a multi module maven based project in which one of the modules contains a few annotation processors for the custom annotations used by other modules. When I add a dependency of annotation processor module to any other module, the annotations of that modules are processed by those annotation processors.

But recently I integrated Checker Framework (for type annotations) and then all the custom annotation processors (I mentioned above) stopped working. Any idea on how to get them to work even with Checker Framework is greatly appreciated?


To clear the scenario,

Let's say I have a maven module named module_A. In this module I have a annotation (class level) called "@FoodItem". I need to enforce a rule that any class annotated with "@FoodItem" annotation should implement the interface "Food". So I wrote an annotation processor "FoodItemAnnotationProcessor" in the same module (module_A) which processes such classes and check for the compliance with that rule.

Then let's say I have another module named module_B which has a maven dependency to the module_A. In this module I have a class called "Pizza" which is annotated with "@FoodItem" annotation.

If a build the project (which has module_A and module_B) with the above configuration, the "FoodItemAnnotationProcessor" is executed at compile stage and validates the class "Pizza" for the rule mentioned above.

After that I integrated Checker framework to module_B (as mentioned here). Then checker framework related validations are executed at compile time as expected, but the "FoodItemAnnotationProcessor" ceased to work.

Udith Gunaratna
  • 2,091
  • 1
  • 13
  • 17

1 Answers1

1

To understand the problem you must know how javac finds your annotation processors.

When you don't supply the --processor argument for javac (see doc-javac-options), then the annotation-processor auto-discovery feature (see javac-doc: Annotation processing) is activated. This means, that javac will search for all available annotation-processors in your classpath (or processorpath, if you have specified it).
Jars, which include a META-INF/services/javax.annotation.processing.Processor file, can specify their annotation processor classes and javac will automatically use them.

The "problem" is that the checker-framework has multiple multiple annotation processors for the checks, but you may only want to use some of those: thus the annotation-discovery process cannot be used and you must manually specify all annotation processors to run in your build file.

For a Maven build you can do it like this:checker-framework doc for Maven

<annotationProcessors>
  <!-- Add all the checkers you want to enable here -->
  <annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
</annotationProcessors>

This will explicitly set the --processor argument for javac (see doc-javac-options), which disables the default annotation-discovery process.

So the solution is to manually add all annotation processors that you want to run (in addition to the checker-framework checkers).

E.g. when you want to run the NullnessChecker and Dagger, you must specify both:

<annotationProcessors>
  <!-- Add all the checkers you want to enable here -->
  <annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
  <!-- Add all your other annotation processors here -->
  <annotationProcessor>dagger.internal.codegen.ComponentProcessor</annotationProcessor>
</annotationProcessors>

Hint:
to find out which annotation processors you are currently using, run your build and pass the Non-Standard Option -XprintProcessorInfo to javac.

UPDATE:

The checkers also support some sort of auto-discovery (doc-ref) - Note: I have not used this yet.

2.2.3 Checker auto-discovery

“Auto-discovery” makes the javac compiler always run a checker plugin, even if you do not explicitly pass the -processor command-line option. This can make your command line shorter, and ensures that your code is checked even if you forget the command-line option.

To enable auto-discovery, place a configuration file named META-INF/services/javax.annotation.processing.Processor in your classpath. The file contains the names of the checker plugins to be used, listed one per line. For instance, to run the Nullness Checker and the Interning Checker automatically, the configuration file should contain:

org.checkerframework.checker.nullness.NullnessChecker
org.checkerframework.checker.interning.InterningChecker

TmTron
  • 17,012
  • 10
  • 94
  • 142