Skip to content

Commit

Permalink
Merge pull request #19067 Fix multiple annotation processing issues d…
Browse files Browse the repository at this point in the history
…iscovered by Micronaut
  • Loading branch information
bot-gradle committed Nov 25, 2021
2 parents a87fabb + 7a897d3 commit a2e63a5
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 28 deletions.
Expand Up @@ -21,6 +21,7 @@ import org.gradle.integtests.fixtures.CompilationOutputsFixture
import org.gradle.language.fixtures.AnnotationProcessorFixture
import org.gradle.language.fixtures.CompileJavaBuildOperationsFixture
import org.gradle.test.fixtures.file.TestFile
import org.intellij.lang.annotations.Language

abstract class AbstractIncrementalAnnotationProcessingIntegrationTest extends AbstractIntegrationSpec {

Expand Down Expand Up @@ -53,6 +54,9 @@ abstract class AbstractIncrementalAnnotationProcessingIntegrationTest extends Ab
dependencies {
compileOnly project(":annotation")
annotationProcessor project(":processor")
testCompileOnly project(":annotation")
testAnnotationProcessor project(":processor")
}
"""

Expand All @@ -70,7 +74,7 @@ abstract class AbstractIncrementalAnnotationProcessingIntegrationTest extends Ab
processor.writeAnnotationProcessorTo(processorProjectDir)
}

protected final File java(String... classBodies) {
protected final File java(@Language("java") String... classBodies) {
javaInPackage('', classBodies)
}

Expand Down
Expand Up @@ -436,6 +436,23 @@ class AggregatingIncrementalAnnotationProcessingIntegrationTest extends Abstract
succeeds "compileJava"
}
@Issue("https://github.com/micronaut-projects/micronaut-core/issues/6536")
def "does not reprocess if nothing in the current sourceSet changed"() {
given:
withProcessor(new AnnotatedGeneratedClassProcessorFixture())
javaTestSourceFile "@Bean class Test {}"
outputs.snapshot { succeeds "compileTestJava" }
when:
java "class Unrelated {}"
then:
succeeds "compileTestJava"
and:
outputs.recompiledClasses("Unrelated")
}
private boolean serviceRegistryReferences(String... services) {
def registry = file("build/classes/java/main/ServiceRegistryResource.txt").text
services.every() {
Expand Down
Expand Up @@ -61,6 +61,25 @@ class IsolatingIncrementalAnnotationProcessingIntegrationTest extends AbstractIn
outputs.recompiledFiles("A", "AHelper", "AHelperResource.txt")
}

@Issue("https://github.com/micronaut-projects/micronaut-core/issues/6536")
def "remembers generated files across multiple compilations"() {
given:
def a = java "@Helper class A {}"
def b = java "@Helper class B {}"
java "class Unrelated {}"
run "compileJava"
a.text = "@Helper class A { public void foo() {} }"
outputs.snapshot { run "compileJava" }

when:
b.text = " class B { }"
run "compileJava"

then:
outputs.deletedFiles("BHelper", "BHelperResource")
outputs.recompiledFiles("B")
}

def "generated files are recompiled when annotated file is affected by a change"() {
given:
def util = java "class Util {}"
Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.gradle.api.internal.tasks.compile.incremental.compilerapi.CompilerApiData;
import org.gradle.api.internal.tasks.compile.incremental.compilerapi.constants.ConstantToDependentsMapping;
import org.gradle.api.internal.tasks.compile.incremental.compilerapi.constants.ConstantToDependentsMappingMerger;
import org.gradle.api.internal.tasks.compile.incremental.compilerapi.deps.GeneratedResource;
import org.gradle.api.internal.tasks.compile.incremental.deps.ClassSetAnalysisData;
import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessingData;
import org.gradle.api.internal.tasks.compile.incremental.processing.AnnotationProcessingResult;
Expand Down Expand Up @@ -73,40 +74,14 @@ public WorkResult execute(T spec) {
private void storeResult(JavaCompileSpec spec, WorkResult result) {
ClassSetAnalysisData outputSnapshot = classpathSnapshotter.analyzeOutputFolder(spec.getDestinationDir());
ClassSetAnalysisData classpathSnapshot = classpathSnapshotter.getClasspathSnapshot(Iterables.concat(spec.getCompileClasspath(), spec.getModulePath()));
AnnotationProcessingData annotationProcessingData = getAnnotationProcessingResult(spec, result);
AnnotationProcessingData annotationProcessingData = getAnnotationProcessingData(spec, result);
CompilerApiData compilerApiData = getCompilerApiData(spec, result);
ClassSetAnalysisData minimizedClasspathSnapshot = classpathSnapshot.reduceToTypesAffecting(outputSnapshot, compilerApiData);
PreviousCompilationData data = new PreviousCompilationData(outputSnapshot, annotationProcessingData, minimizedClasspathSnapshot, compilerApiData);
File previousCompilationDataFile = Objects.requireNonNull(spec.getCompileOptions().getPreviousCompilationDataFile());
previousCompilationAccess.writePreviousCompilationData(data, previousCompilationDataFile);
}

private AnnotationProcessingData getAnnotationProcessingResult(JavaCompileSpec spec, WorkResult result) {
Set<AnnotationProcessorDeclaration> processors = spec.getEffectiveAnnotationProcessors();
if (processors.isEmpty()) {
return new AnnotationProcessingData();
}
if (result instanceof IncrementalCompilationResult) {
result = ((IncrementalCompilationResult) result).getCompilerResult();
}
if (result instanceof ApiCompilerResult) {
AnnotationProcessingResult processingResult = ((ApiCompilerResult) result).getAnnotationProcessingResult();
return convertProcessingResult(processingResult);
}
return new AnnotationProcessingData(ImmutableMap.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableMap.of(), ImmutableSet.of(), "the chosen compiler did not support incremental annotation processing");
}

private AnnotationProcessingData convertProcessingResult(AnnotationProcessingResult processingResult) {
return new AnnotationProcessingData(
processingResult.getGeneratedTypesWithIsolatedOrigin(),
processingResult.getAggregatedTypes(),
processingResult.getGeneratedAggregatingTypes(),
processingResult.getGeneratedResourcesWithIsolatedOrigin(),
processingResult.getGeneratedAggregatingResources(),
processingResult.getFullRebuildCause()
);
}

private CompilerApiData getCompilerApiData(JavaCompileSpec spec, WorkResult result) {
if (spec.getCompileOptions().supportsCompilerApi()) {
CompilerApiData previousCompilerApiData = null;
Expand Down Expand Up @@ -152,4 +127,62 @@ private Map<String, Set<String>> mergeSourceClassesMappings(Map<String, Set<Stri
return merged;
}

private AnnotationProcessingData getAnnotationProcessingData(JavaCompileSpec spec, WorkResult result) {
Set<AnnotationProcessorDeclaration> processors = spec.getEffectiveAnnotationProcessors();
if (processors.isEmpty()) {
return new AnnotationProcessingData();
}
AnnotationProcessingData previousAnnotationProcessingData = null;
RecompilationSpec recompilationSpec = null;
if (result instanceof IncrementalCompilationResult) {
previousAnnotationProcessingData = ((IncrementalCompilationResult) result).getPreviousCompilationData().getAnnotationProcessingData();
recompilationSpec = ((IncrementalCompilationResult) result).getRecompilationSpec();
result = ((IncrementalCompilationResult) result).getCompilerResult();
}
Set<String> changedClasses = recompilationSpec == null ? Collections.emptySet() : recompilationSpec.getClassesToCompile();

if (result instanceof ApiCompilerResult) {
AnnotationProcessingResult processingResult = ((ApiCompilerResult) result).getAnnotationProcessingResult();
AnnotationProcessingData newAnnotationProcessingData = new AnnotationProcessingData(
processingResult.getGeneratedTypesWithIsolatedOrigin(),
processingResult.getAggregatedTypes(),
processingResult.getGeneratedAggregatingTypes(),
processingResult.getGeneratedResourcesWithIsolatedOrigin(),
processingResult.getGeneratedAggregatingResources(),
processingResult.getFullRebuildCause()
);
if (previousAnnotationProcessingData == null) {
return newAnnotationProcessingData;
}
return mergeAnnotationProcessingData(previousAnnotationProcessingData, newAnnotationProcessingData, changedClasses);
}
return new AnnotationProcessingData(
ImmutableMap.of(),
ImmutableSet.of(),
ImmutableSet.of(),
ImmutableMap.of(),
ImmutableSet.of(),
"the chosen compiler did not support incremental annotation processing"
);

}

private AnnotationProcessingData mergeAnnotationProcessingData(AnnotationProcessingData oldData, AnnotationProcessingData newData, Set<String> changedClasses) {
Map<String, Set<String>> generatedTypesByOrigin = new HashMap<>(oldData.getGeneratedTypesByOrigin());
changedClasses.forEach(generatedTypesByOrigin::remove);
generatedTypesByOrigin.putAll(newData.getGeneratedTypesByOrigin());
Map<String, Set<GeneratedResource>> generatedResourcesByOrigin = new HashMap<>(oldData.getGeneratedResourcesByOrigin());
changedClasses.forEach(generatedResourcesByOrigin::remove);
generatedResourcesByOrigin.putAll(newData.getGeneratedResourcesByOrigin());

return new AnnotationProcessingData(
generatedTypesByOrigin,
newData.getAggregatedTypes(),
newData.getGeneratedTypesDependingOnAllOthers(),
generatedResourcesByOrigin,
newData.getGeneratedResourcesDependingOnAllOthers(),
newData.getFullRebuildCause()
);
}

}
Expand Up @@ -157,6 +157,9 @@ private DependentsSet findDirectDependents(String className) {
* - the originating types of generated classes that need to be recompiled, since they wouldn't exist if the originating type is not reprocessed
*/
public Set<String> getTypesToReprocess(Set<String> compiledClasses) {
if (compiledClasses.isEmpty()) {
return Collections.emptySet();
}
Set<String> typesToReprocess = new HashSet<>(annotationProcessingData.getAggregatedTypes());
for (Map.Entry<String, Set<String>> entry : annotationProcessingData.getGeneratedTypesByOrigin().entrySet()) {
if (entry.getValue().stream().anyMatch(compiledClasses::contains)) {
Expand Down

0 comments on commit a2e63a5

Please sign in to comment.