Gradle 5.4 removes the limitation that incremental annotation processors cannot create resources, so these can now be marked as incremental annotation processors.

Comment From: philwebb

@thyming If we make this change do you know what the impact will be for earlier versions of Gradle? I'm not sure we're quite ready to make 5.4 the minimum supported version.

Comment From: thyming

Per @oehme (https://github.com/gradle/gradle/issues/4702#issuecomment-484809622) the fallback behavior is just as it is now.

Comment From: wilkinsona

Thanks for the PR. I am not sure that we can safely mark spring-boot-configuration-processor as incremental. The Gradle documentation says the following:

They must not depend on compiler-specific APIs like com.sun.source.util.Trees. Gradle wraps the processing APIs, so attempts to cast to compiler-specific types will fail. If your processor does this, it cannot be incremental, unless you have some fallback mechanism.

The Trees API is used to determine the default values of a configuration property field for inclusion in the generated metadata. While we use reflection, I expect the wrapping that's done by Gradle to stop this from working.

Have you tried your proposed changes with Gradle 5.4 and verified that the annotation processor works correctly?

Comment From: snicoll

@thyming gentle ping. Can you please get back to us? See https://github.com/spring-projects/spring-boot/pull/16603#issuecomment-486164149

Comment From: thyming

Apologies - this slipped through the cracks. @wilkinsona I did just build the processor locally and your reading was correct - while everything builds without errors and the incremental compilation behavior is correct, it fails to include the default values in the resultant metadata file.

Comment From: wilkinsona

Thanks, @thyming.

Comment From: oehme

Gradle wraps the processing APIs, so attempts to cast to compiler-specific types will fail. If your processor does this, it cannot be incremental, unless you have some fallback mechanism.

A few processors (e.g. Lombok) unwrap the Gradle decorator and we keep the name of the delegate field stable for that reason. If your usage of the Trees API is in line with the incremental processing contract, you could do that as well. I totally understand if that's too much hackery though :)

Accessing default values of a field would only be okay if you do that for the fields of the currently processed class. If the generated code depends on field initializers of other classes (e.g. superclasses), it won't work since field initializers are considered implementation details and don't trigger recompilation of dependent classes.

Comment From: mattdkerr

Is this possible now that Gradle 6.0 offers more options? Would a plugin for Gradle aid in solving this problem?

Comment From: wilkinsona

AFAIK, nothing has changed in Gradle 6 in this area. The 6.0 docs still describes the same limitation as I mentioned above.

Comment From: LifeIsStrange

Wouldn't investigating @oehme idea (doing the same technique as lombok) be a great improvement idea for Spring boot 2.4?

Micronaut 2 has released with incremental annotation processing support! The competition is increasingly eating the deceloppers mindshare because they achieve two pain points objectively better than current spring boot: 1) Catching more errors at compile time. 2) And here: faster startup time.

Resolving this issue would be a great progress towards being competitive regarding 2) Therefore I believe that Pivotal should prioritize it.

Comment From: wilkinsona

We can take another look at this but it won’t make any difference to startup time. Incremental annotation processing only has the potential to reduce compilation time. Once compilation is complete, there’s no difference to startup time as the end result of the compilation is identical, irrespective of whether or not it was done incrementally.

Comment From: philwebb

We're going to take another look at this, but there's slightly more work to do than the changes in this PR. Please follow #22150 for updates.