From a5673d06f687e1354f1f069cce36136538cf532c Mon Sep 17 00:00:00 2001 From: Thomas Broyer Date: Tue, 25 Sep 2018 08:25:58 -0700 Subject: [PATCH] Make AutoValue and AutoService support Gradle incremental build. This work was done by Thomas Broyer. Closes https://github.com/google/auto/pull/657 RELNOTES=Make AutoValue and AutoService support Gradle incremental build. Thanks to Thomas Broyer for this work. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=214442018 --- .../gradle/incremental.annotation.processors | 1 + value/processor/pom.xml | 11 ++++ .../value/extension/AutoValueExtension.java | 56 +++++++++++++++++++ .../memoized/processor/MemoizeExtension.java | 6 ++ .../memoized/processor/MemoizedValidator.java | 3 + .../processor/AutoAnnotationProcessor.java | 3 + .../value/processor/AutoOneOfProcessor.java | 5 +- .../processor/AutoValueBuilderProcessor.java | 3 + .../value/processor/AutoValueProcessor.java | 33 +++++++++-- 9 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 service/src/main/resources/META-INF/gradle/incremental.annotation.processors diff --git a/service/src/main/resources/META-INF/gradle/incremental.annotation.processors b/service/src/main/resources/META-INF/gradle/incremental.annotation.processors new file mode 100644 index 0000000000..dd17374c7f --- /dev/null +++ b/service/src/main/resources/META-INF/gradle/incremental.annotation.processors @@ -0,0 +1 @@ +com.google.auto.service.processor.AutoServiceProcessor,AGGREGATING diff --git a/value/processor/pom.xml b/value/processor/pom.xml index a99276f1df..52040ec2df 100644 --- a/value/processor/pom.xml +++ b/value/processor/pom.xml @@ -56,6 +56,17 @@ escapevelocity 0.9 + + net.ltgt.gradle.incap + incap + 0.1 + + + net.ltgt.gradle.incap + incap-processor + 0.1 + provided + com.google.guava guava diff --git a/value/src/main/java/com/google/auto/value/extension/AutoValueExtension.java b/value/src/main/java/com/google/auto/value/extension/AutoValueExtension.java index 5d2b352a42..2aa7bb7133 100644 --- a/value/src/main/java/com/google/auto/value/extension/AutoValueExtension.java +++ b/value/src/main/java/com/google/auto/value/extension/AutoValueExtension.java @@ -108,6 +108,62 @@ public interface Context { Set abstractMethods(); } + /** + * Indicates to an annotation processor environment supporting incremental annotation processing + * (currently a feature specific to Gradle starting with version 4.8) the incremental type of an + * Extension. + * + *

The constants for this enum are ordered by increasing performance (but also constraints). + * + * @see Gradle + * documentation of its incremental annotation processing + */ + public enum IncrementalExtensionType { + /** + * The incrementality of this extension is unknown, or it is neither aggregating nor isolating. + */ + UNKNOWN, + + /** + * This extension is aggregating, meaning that it may generate outputs based on several + * annotated input classes and it respects the constraints imposed on aggregating processors. + * It is unusual for AutoValue extensions to be aggregating. + * + * @see Gradle + * definition of aggregating processors + */ + AGGREGATING, + + /** + * This extension is isolating, meaning roughly that its output depends on the + * {@code @AutoValue} class and its dependencies, but not on other {@code @AutoValue} classes + * that might be compiled at the same time. The constraints that an isolating extension must + * respect are the same as those that Gradle imposes on an isolating annotation processor. + * + * @see Gradle + * definition of isolating processors + */ + ISOLATING + } + + /** + * Determines the incremental type of this Extension. + * + *

The {@link ProcessingEnvironment} can be used, among other things, to obtain the processor + * options, using {@link ProcessingEnvironment#getOptions()}. + * + *

The actual incremental type of the AutoValue processor as a whole will be the loosest + * incremental types of the Extensions present in the annotation processor path. The default + * returned value is {@link IncrementalExtensionType#UNKNOWN}, which will disable incremental + * annotation processing entirely. + */ + public IncrementalExtensionType incrementalType(ProcessingEnvironment processingEnvironment) { + return IncrementalExtensionType.UNKNOWN; + } + /** * Determines whether this Extension applies to the given context. * diff --git a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java index c14ac6a1d1..ad52f69741 100644 --- a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java +++ b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java @@ -55,6 +55,7 @@ import java.util.Map; import java.util.Optional; import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ExecutableElement; @@ -76,6 +77,11 @@ public final class MemoizeExtension extends AutoValueExtension { private static final AnnotationSpec SUPPRESS_WARNINGS = AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "Immutable").build(); + @Override + public IncrementalExtensionType incrementalType(ProcessingEnvironment processingEnvironment) { + return IncrementalExtensionType.ISOLATING; + } + @Override public boolean applicable(Context context) { return !memoizedMethods(context).isEmpty(); diff --git a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizedValidator.java b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizedValidator.java index 0ba4e11d78..3ee78223a4 100644 --- a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizedValidator.java +++ b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizedValidator.java @@ -33,12 +33,15 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType; /** * An annotation {@link Processor} that reports errors for {@link Memoized @Memoized} methods that * are not inside {@code AutoValue}-annotated classes. */ @AutoService(Processor.class) +@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.ISOLATING) @SupportedAnnotationTypes(MEMOIZED_NAME) public final class MemoizedValidator extends AbstractProcessor { @Override diff --git a/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java index ba7f806cdc..76de3e90a1 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java @@ -58,6 +58,8 @@ import javax.lang.model.util.Types; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType; /** * Javac annotation processor (compiler plugin) to generate annotation implementations. User code @@ -66,6 +68,7 @@ * @author emcmanus@google.com (Éamonn McManus) */ @AutoService(Processor.class) +@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.ISOLATING) @SupportedAnnotationTypes(AUTO_ANNOTATION_NAME) public class AutoAnnotationProcessor extends AbstractProcessor { public AutoAnnotationProcessor() {} diff --git a/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java index 8c52938f94..6a9118d39a 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java @@ -36,7 +36,6 @@ import java.util.Set; import javax.annotation.processing.Processor; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedOptions; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; @@ -46,6 +45,8 @@ import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType; /** * Javac annotation processor (compiler plugin) for {@linkplain com.google.auto.value.AutoOneOf @@ -56,7 +57,7 @@ */ @AutoService(Processor.class) @SupportedAnnotationTypes(AUTO_ONE_OF_NAME) -@SupportedOptions("com.google.auto.value.OmitIdentifiers") +@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.ISOLATING) public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { public AutoOneOfProcessor() { super(AUTO_ONE_OF_NAME); diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueBuilderProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoValueBuilderProcessor.java index bf89160e0d..6e27191ddd 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueBuilderProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueBuilderProcessor.java @@ -30,6 +30,8 @@ import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType; /** * Annotation processor that checks that the type that {@code AutoValue.Builder} is applied to is @@ -39,6 +41,7 @@ * @author Éamonn McManus */ @AutoService(Processor.class) +@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.ISOLATING) @SupportedAnnotationTypes(AUTO_VALUE_BUILDER_NAME) public class AutoValueBuilderProcessor extends AbstractProcessor { @Override diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java index 816bdabd90..594645b3e0 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java @@ -33,6 +33,7 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Optional; @@ -43,7 +44,6 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedOptions; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; @@ -51,6 +51,8 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType; /** * Javac annotation processor (compiler plugin) for value types; user code never references this @@ -61,8 +63,10 @@ */ @AutoService(Processor.class) @SupportedAnnotationTypes(AUTO_VALUE_NAME) -@SupportedOptions("com.google.auto.value.OmitIdentifiers") +@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.DYNAMIC) public class AutoValueProcessor extends AutoValueOrOneOfProcessor { + private static final String OMIT_IDENTIFIERS_OPTION = "com.google.auto.value.OmitIdentifiers"; + public AutoValueProcessor() { this(AutoValueProcessor.class.getClassLoader()); } @@ -112,6 +116,28 @@ public synchronized void init(ProcessingEnvironment processingEnv) { } } + @Override + public Set getSupportedOptions() { + AutoValueExtension.IncrementalExtensionType incrementalType = + extensions.stream() + .map(e -> e.incrementalType(processingEnv)) + .min(Comparator.naturalOrder()) + .orElse(AutoValueExtension.IncrementalExtensionType.ISOLATING); + switch (incrementalType) { + case ISOLATING: + return ImmutableSet.of( + OMIT_IDENTIFIERS_OPTION, + IncrementalAnnotationProcessorType.ISOLATING.getProcessorOption()); + case AGGREGATING: + return ImmutableSet.of( + OMIT_IDENTIFIERS_OPTION, + IncrementalAnnotationProcessorType.AGGREGATING.getProcessorOption()); + case UNKNOWN: + return ImmutableSet.of(OMIT_IDENTIFIERS_OPTION); + } + throw new AssertionError(incrementalType); + } + private static String generatedSubclassName(TypeElement type, int depth) { return generatedClassName(type, Strings.repeat("$", depth) + "AutoValue_"); } @@ -201,8 +227,7 @@ void processType(TypeElement type) { AutoValueTemplateVars vars = new AutoValueTemplateVars(); vars.finalSubclass = TypeSimplifier.simpleNameOf(finalSubclass); vars.types = processingEnv.getTypeUtils(); - vars.identifiers = - !processingEnv.getOptions().containsKey("com.google.auto.value.OmitIdentifiers"); + vars.identifiers = !processingEnv.getOptions().containsKey(OMIT_IDENTIFIERS_OPTION); defineSharedVarsForType(type, methods, vars); defineVarsForType(type, vars, toBuilderMethods, propertyMethods, builder);