Mark Proctor
Mark Proctor

Reputation: 711

IntelliJ incremental Maven builds with annotations and APT

Gradle supports incremental annotation processing now, but I don't believe that helps those with Maven projects in IntelliJ. When I google on this I find a few references to IntelliJ and incremental annotation processing, but nothing describing how it works, its limitations etc. Is there any public information on this? https://github.com/JetBrains/intellij-community/tree/master/java/java-tests/testData/compileServer/incremental/annotations

I've found posts like this: https://intellij-support.jetbrains.com/hc/en-us/community/posts/7085229549586-JPS-incremental-annotation-processing-is-disabled

And the property "jps.track.ap.dependencies".

So this makes me believe IntelliJ is trying to do something that in some situations might be incremental...

I've done extensive searching and cannot find anything, I'm hoping someone might be aware of a resource they can point to, or maybe have some internal Knowledge on this they can relate.

Upvotes: 2

Views: 267

Answers (3)

Eugene Nesterenko
Eugene Nesterenko

Reputation: 1

Thanks a lot for posting source code, I had the same problem with lombok annotation and Intelj and was able to fix it by setting -Djps.track.ap.dependencies=true There are a lot of sources that instruct to set this flag to false and it is not working

Upvotes: 0

romanv-jb
romanv-jb

Reputation: 711

For Maven-based Projects IDEA, by default, delegates the the build process to its' native Build System, see Delegate IDE build/run actions to Maven option.

IDEA's Build System does support Incremental Annotation Processing. There are no limitations per se, as it only depends on how well the AP adheres to AP-writing best practices.

Specifically, that depends on how well AP reports on so-called "origins" when it returns the result of its' work to IDEA/Javac. "Origin" indicates which object(s) data returned by AP relates to. Based off this "origin" data IDEA determines which objects within the Project have been updated and therefore have to be recompiled, removed, etc. Unfortunately, some APs do not provide this data or do not provide enough of it and in such cases you are likely to get inconsistent compilation results.

Upvotes: 1

Thomas Broyer
Thomas Broyer

Reputation: 64551

Because IntelliJ IDEA is (partly) open source, we can poke at the source code.

That system property leads to https://github.com/JetBrains/intellij-community/blob/6a50833d3cbdfc342e8fe16d954938b9f465fb2e/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java#L48, and from there we can find

      final APIWrappers.ProcessingContext procContext;
      final DiagnosticOutputConsumer diagnosticListener;
      if (TRACK_AP_GENERATED_DEPENDENCIES && isAnnotationProcessingEnabled) {
        procContext = new APIWrappers.ProcessingContext(fileManager);
        // use real processor class names and not names of processor wrappers
        diagnosticListener = APIWrappers.newDiagnosticListenerWrapper(procContext, diagnosticConsumer);
      }
      else {
        procContext = null;
        diagnosticListener = diagnosticConsumer;
      }

      // …

      // note: `task` is a javax.tools.JavaCompiler.CompilationTask
      if (TRACK_AP_GENERATED_DEPENDENCIES && isAnnotationProcessingEnabled) {
        final Iterable<Processor> processors = lookupAnnotationProcessors(procContext, getAnnotationProcessorNames(_options));
        if (processors != null) {
          task.setProcessors(processors);
        }
      }

This then (through the APIWrappers wrapper classes) will eventually call https://github.com/JetBrains/intellij-community/blob/6a50833d3cbdfc342e8fe16d954938b9f465fb2e/jps/jps-builders-6/src/org/jetbrains/jps/javac/JpsJavacFileManager.java#L665, which is then used to implement javax.tools.JavaFileManager's getFileForOutput and getJavaFileForOutput.

I didn't look further but it looks like they're using a similar approach to Gradle's incremental annotation processing: tracing the "originating elements" for each generated file, so they can determine which other files/classes need to be reprocessed whenever a source file is being compiled after change.

Upvotes: 2

Related Questions