From 8e7515a5a796a236a798c299e5338910a4524f3b Mon Sep 17 00:00:00 2001 From: emcmanus Date: Fri, 8 May 2020 12:49:48 -0700 Subject: [PATCH] Have SerializableAutoValueExtension declare that it is "isolating". Since it is a built-in extension, and since AutoValue itself only describes itself as isolating if all extensions are, this omission meant that the presence of AutoValue disabled incremental builds in Gradle. Add a test to ensure that we don't forget this with future extensions. Fixes https://github.com/google/auto/issues/844. RELNOTES=AutoValue is once again "isolating" for Gradle incremental compilation. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=310610697 --- .../SerializableAutoValueExtension.java | 7 +- .../value/processor/AutoValueProcessor.java | 25 ++-- .../processor/IncrementalExtensionTest.java | 108 ++++++++++++++++++ 3 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 value/src/test/java/com/google/auto/value/processor/IncrementalExtensionTest.java diff --git a/value/src/main/java/com/google/auto/value/extension/serializable/processor/SerializableAutoValueExtension.java b/value/src/main/java/com/google/auto/value/extension/serializable/processor/SerializableAutoValueExtension.java index 89118712db..d3265d0291 100644 --- a/value/src/main/java/com/google/auto/value/extension/serializable/processor/SerializableAutoValueExtension.java +++ b/value/src/main/java/com/google/auto/value/extension/serializable/processor/SerializableAutoValueExtension.java @@ -24,7 +24,6 @@ import com.google.auto.common.MoreTypes; import com.google.auto.service.AutoService; import com.google.auto.value.extension.AutoValueExtension; -import com.google.auto.value.extension.AutoValueExtension.Context; import com.google.auto.value.extension.serializable.serializer.SerializerFactoryLoader; import com.google.auto.value.extension.serializable.serializer.interfaces.Serializer; import com.google.auto.value.extension.serializable.serializer.interfaces.SerializerFactory; @@ -45,6 +44,7 @@ import java.util.List; import java.util.Optional; import java.util.function.Function; +import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; @@ -68,6 +68,11 @@ public boolean applicable(Context context) { return hasSerializableInterface(context) && hasSerializableAutoValueAnnotation(context); } + @Override + public IncrementalExtensionType incrementalType(ProcessingEnvironment processingEnvironment) { + return IncrementalExtensionType.ISOLATING; + } + @Override public String generateClass( Context context, String className, String classToExtend, boolean isFinal) { 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 6342d8029e..a469d566f9 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 @@ -88,7 +88,7 @@ public AutoValueProcessor() { @VisibleForTesting public AutoValueProcessor(Iterable extensions) { super(AUTO_VALUE_NAME); - this.extensions = ImmutableList.copyOf(extensions); + this.extensions = ImmutableList.copyOf(extensions); this.loaderForExtensions = null; } @@ -98,25 +98,30 @@ public AutoValueProcessor(Iterable extensions) { private ImmutableList extensions; private final ClassLoader loaderForExtensions; + @VisibleForTesting + static ImmutableList extensionsFromLoader(ClassLoader loader) { + return ImmutableList.copyOf( + Iterables.filter( + SimpleServiceLoader.load(AutoValueExtension.class, loader), + ext -> !ext.getClass().getName().equals(OLD_MEMOIZE_EXTENSION))); + } + @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); if (extensions == null) { try { - extensions = ImmutableList.copyOf( - Iterables.filter( - SimpleServiceLoader.load(AutoValueExtension.class, loaderForExtensions), - ext -> !ext.getClass().getName().equals(OLD_MEMOIZE_EXTENSION))); - } catch (Throwable t) { + extensions = extensionsFromLoader(loaderForExtensions); + } catch (RuntimeException | Error e) { StringBuilder warning = new StringBuilder(); warning.append( - "An exception occurred while looking for AutoValue extensions. " - + "No extensions will function."); - if (t instanceof ServiceConfigurationError) { + "An exception occurred while looking for AutoValue extensions." + + " No extensions will function."); + if (e instanceof ServiceConfigurationError) { warning.append(" This may be due to a corrupt jar file in the compiler's classpath."); } - warning.append("\n").append(Throwables.getStackTraceAsString(t)); + warning.append("\n").append(Throwables.getStackTraceAsString(e)); errorReporter().reportWarning(warning.toString(), null); extensions = ImmutableList.of(); } diff --git a/value/src/test/java/com/google/auto/value/processor/IncrementalExtensionTest.java b/value/src/test/java/com/google/auto/value/processor/IncrementalExtensionTest.java new file mode 100644 index 0000000000..27cb09367e --- /dev/null +++ b/value/src/test/java/com/google/auto/value/processor/IncrementalExtensionTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.auto.value.processor; + +import static com.google.common.truth.Correspondence.transforming; +import static com.google.common.truth.Truth.assertThat; + +import com.google.auto.value.extension.AutoValueExtension; +import com.google.auto.value.extension.AutoValueExtension.IncrementalExtensionType; +import com.google.auto.value.extension.memoized.processor.MemoizeExtension; +import com.google.auto.value.extension.serializable.processor.SerializableAutoValueExtension; +import com.google.common.collect.ImmutableList; +import javax.annotation.processing.ProcessingEnvironment; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests of Gradle incrementality in the presence of extensions. See + * + * incremental annotation processing in the Gradle user guide. + */ +@RunWith(JUnit4.class) +public class IncrementalExtensionTest { + @Test + public void builtInExtensionsAreIsolating() { + ImmutableList builtInExtensions = + AutoValueProcessor.extensionsFromLoader(AutoValueProcessor.class.getClassLoader()); + // These are the current built-in extensions. We will update this test if we add more. + // The (Object) cast is because otherwise the inferred type is Class, and we can't match + // that with the class literals here. Even if we cast them to Class it will be a + // different . + assertThat(builtInExtensions) + .comparingElementsUsing(transforming(e -> (Object) e.getClass(), "is class")) + .containsExactly(MemoizeExtension.class, SerializableAutoValueExtension.class); + + AutoValueProcessor processor = new AutoValueProcessor(builtInExtensions); + assertThat(processor.getSupportedOptions()) + .contains(IncrementalAnnotationProcessorType.ISOLATING.getProcessorOption()); + } + + @Test + public void customExtensionsAreNotIsolatingByDefault() { + AutoValueExtension nonIsolatingExtension = new NonIsolatingExtension(); + assertThat(nonIsolatingExtension.incrementalType((ProcessingEnvironment) null)) + .isEqualTo(IncrementalExtensionType.UNKNOWN); + ImmutableList extensions = ImmutableList.builder() + .addAll(AutoValueProcessor.extensionsFromLoader(AutoValueProcessor.class.getClassLoader())) + .add(nonIsolatingExtension) + .build(); + + AutoValueProcessor processor = new AutoValueProcessor(extensions); + assertThat(processor.getSupportedOptions()) + .doesNotContain(IncrementalAnnotationProcessorType.ISOLATING.getProcessorOption()); + } + + @Test + public void customExtensionsCanBeIsolating() { + AutoValueExtension isolatingExtension = new IsolatingExtension(); + assertThat(isolatingExtension.incrementalType((ProcessingEnvironment) null)) + .isEqualTo(IncrementalExtensionType.ISOLATING); + ImmutableList extensions = ImmutableList.builder() + .addAll(AutoValueProcessor.extensionsFromLoader(AutoValueProcessor.class.getClassLoader())) + .add(isolatingExtension) + .build(); + + AutoValueProcessor processor = new AutoValueProcessor(extensions); + assertThat(processor.getSupportedOptions()) + .contains(IncrementalAnnotationProcessorType.ISOLATING.getProcessorOption()); + } + + // Extensions are "UNKNOWN" by default. + private static class NonIsolatingExtension extends AutoValueExtension { + @Override + public String generateClass( + Context context, String className, String classToExtend, boolean isFinal) { + return null; + } + } + + // Extensions are "ISOLATING" if they say they are. + private static class IsolatingExtension extends AutoValueExtension { + @Override + public IncrementalExtensionType incrementalType(ProcessingEnvironment processingEnvironment) { + return IncrementalExtensionType.ISOLATING; + } + + @Override + public String generateClass( + Context context, String className, String classToExtend, boolean isFinal) { + return null; + } + } +}