diff options
author | emcmanus <emcmanus@google.com> | 2020-06-08 09:34:01 -0700 |
---|---|---|
committer | Chris Povirk <beigetangerine@gmail.com> | 2020-06-09 08:37:32 -0400 |
commit | b22f969d63d7dc6f2163092637c2ba4c763f00bc (patch) | |
tree | 0a708fe8a87a89f9236af71facefe06cdb0d16cb | |
parent | b9ba06a327d08a741ed70f1573540e063fb6c69c (diff) | |
download | auto-b22f969d63d7dc6f2163092637c2ba4c763f00bc.tar.gz |
Copy annotations from `@AutoValue.Builder` to the generated `Builder` subclass.
This happens only if `@AutoValue.CopyAnnotations` is present on the `@AutoValue.Builder` class, using the same logic as for copying annotations from the main `@AutoValue` class.
RELNOTES=Optionally copy annotations from the `@AutoValue.Builder` class to the generated subclass.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=315291023
8 files changed, 88 insertions, 16 deletions
diff --git a/value/src/it/functional/src/test/java/com/google/auto/value/AutoValueTest.java b/value/src/it/functional/src/test/java/com/google/auto/value/AutoValueTest.java index 3a024ab1..346bc53a 100644 --- a/value/src/it/functional/src/test/java/com/google/auto/value/AutoValueTest.java +++ b/value/src/it/functional/src/test/java/com/google/auto/value/AutoValueTest.java @@ -1056,6 +1056,11 @@ public class AutoValueTest { String value(); } + @AutoAnnotation + private static MyAnnotation myAnnotation(String value) { + return new AutoAnnotation_AutoValueTest_myAnnotation(value); + } + @AutoValue abstract static class PrimitiveArrays { @SuppressWarnings("mutable") @@ -3365,4 +3370,51 @@ public class AutoValueTest { .getGenericParameterTypes()[0]; assertThat(generatedBuilderParamType).isEqualTo(originalReturnType); } + + @AutoValue + abstract static class BuilderAnnotationsNotCopied { + abstract String foo(); + + static Builder builder() { + return new AutoValue_AutoValueTest_BuilderAnnotationsNotCopied.Builder(); + } + + @AutoValue.Builder + @MyAnnotation("thing") + abstract static class Builder { + abstract Builder setFoo(String x); + abstract BuilderAnnotationsNotCopied build(); + } + } + + @Test + public void builderAnnotationsNotCopiedByDefault() { + BuilderAnnotationsNotCopied.Builder builder = BuilderAnnotationsNotCopied.builder(); + assertThat(builder.getClass().getAnnotations()).isEmpty(); + assertThat(builder.setFoo("foo").build().foo()).isEqualTo("foo"); + } + + @AutoValue + abstract static class BuilderAnnotationsCopied { + abstract String foo(); + + static Builder builder() { + return new AutoValue_AutoValueTest_BuilderAnnotationsCopied.Builder(); + } + + @AutoValue.Builder + @AutoValue.CopyAnnotations + @MyAnnotation("thing") + abstract static class Builder { + abstract Builder setFoo(String x); + abstract BuilderAnnotationsCopied build(); + } + } + + @Test + public void builderAnnotationsCopiedIfRequested() { + BuilderAnnotationsCopied.Builder builder = BuilderAnnotationsCopied.builder(); + assertThat(builder.getClass().getAnnotations()).asList().containsExactly(myAnnotation("thing")); + assertThat(builder.setFoo("foo").build().foo()).isEqualTo("foo"); + } } diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java index 494577a5..6e708ba0 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java @@ -873,7 +873,7 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { return className.startsWith(AUTO_VALUE_PACKAGE_NAME) && !className.contains("Test"); } - private ImmutableList<String> copiedClassAnnotations(TypeElement type) { + ImmutableList<String> copiedClassAnnotations(TypeElement type) { // Only copy annotations from a class if it has @AutoValue.CopyAnnotations. if (hasAnnotationMirror(type, COPY_ANNOTATIONS_NAME)) { Set<String> excludedAnnotations = diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfTemplateVars.java b/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfTemplateVars.java index 9ad7d043..9fdbea4f 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfTemplateVars.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfTemplateVars.java @@ -56,9 +56,10 @@ abstract class AutoValueOrOneOfTemplateVars extends TemplateVars { String simpleClassName; /** - * The full spelling of any annotation to add to this class, or an empty list if there are none. A - * non-empty value might look something like {@code - * "@com.google.common.annotations.GwtCompatible(serializable = true)"}. + * The full spelling of any annotations to add to this class, or an empty list if there are none. + * A non-empty value might look something like {@code + * "@`com.google.common.annotations.GwtCompatible`(serializable = true)"}. The {@code ``} marks + * are explained in {@link TypeEncoder}. */ ImmutableList<String> annotations; 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 a469d566..cbdc7734 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 @@ -423,7 +423,7 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { AutoValueTemplateVars vars, ImmutableSet<ExecutableElement> toBuilderMethods, ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsAndTypes, - Optional<BuilderSpec.Builder> builder) { + Optional<BuilderSpec.Builder> maybeBuilder) { ImmutableSet<ExecutableElement> propertyMethods = propertyMethodsAndTypes.keySet(); // We can't use ImmutableList.toImmutableList() for obscure Google-internal reasons. vars.toBuilderMethods = @@ -436,11 +436,13 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { propertySet(propertyMethodsAndTypes, annotatedPropertyFields, annotatedPropertyMethods); vars.serialVersionUID = getSerialVersionUID(type); // Check for @AutoValue.Builder and add appropriate variables if it is present. - if (builder.isPresent()) { - ImmutableBiMap<ExecutableElement, String> methodToPropertyName = - propertyNameToMethodMap(propertyMethods).inverse(); - builder.get().defineVars(vars, methodToPropertyName); - } + maybeBuilder.ifPresent( + builder -> { + ImmutableBiMap<ExecutableElement, String> methodToPropertyName = + propertyNameToMethodMap(propertyMethods).inverse(); + builder.defineVars(vars, methodToPropertyName); + vars.builderAnnotations = copiedClassAnnotations(builder.builderType()); + }); } @Override diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueTemplateVars.java b/value/src/main/java/com/google/auto/value/processor/AutoValueTemplateVars.java index 8aec3248..8f855bd0 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueTemplateVars.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueTemplateVars.java @@ -36,7 +36,7 @@ class AutoValueTemplateVars extends AutoValueOrOneOfTemplateVars { * The properties defined by the parent class's abstract methods. The elements of this set are in * the same order as the original abstract method declarations in the AutoValue class. */ - ImmutableSet<AutoValueProcessor.Property> props; + ImmutableSet<AutoValueOrOneOfProcessor.Property> props; /** * Whether to include identifiers in strings in the generated code. If false, exception messages @@ -100,6 +100,14 @@ class AutoValueTemplateVars extends AutoValueOrOneOfTemplateVars { /** True if the builder being implemented is an interface, false if it is an abstract class. */ Boolean builderIsInterface = false; + /** + * The full spelling of any annotations to add to the generated builder subclass, or an empty list + * if there are none. A non-empty value might look something like {@code + * @`java.lang.SuppressWarnings`("Immutable")}. The {@code ``} marks are explained in + * {@link TypeEncoder}. + */ + ImmutableList<String> builderAnnotations = ImmutableList.of(); + /** The builder's build method, often {@code "build"}. */ Optional<SimpleMethod> buildMethod = Optional.empty(); diff --git a/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java b/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java index 32e9e6d4..f218891c 100644 --- a/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java +++ b/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java @@ -447,11 +447,9 @@ class BuilderSpec { if (!sameTypeParameters(autoValueClass, builderTypeElement)) { errorReporter.reportError( - "Type parameters of " - + builderTypeElement - + " must have same names and bounds as " - + "type parameters of " - + autoValueClass, + String.format( + "Type parameters of %s must have same names and bounds as type parameters of %s", + builderTypeElement, autoValueClass), builderTypeElement); return Optional.empty(); } diff --git a/value/src/main/java/com/google/auto/value/processor/autovalue.vm b/value/src/main/java/com/google/auto/value/processor/autovalue.vm index 8fca0e00..80ef79ae 100644 --- a/value/src/main/java/com/google/auto/value/processor/autovalue.vm +++ b/value/src/main/java/com/google/auto/value/processor/autovalue.vm @@ -192,6 +192,13 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #end + ## BUILDER CLASS + + #foreach ($a in $builderAnnotations) + + $a## + #end + static #if ($isFinal) final #end class Builder${builderFormalTypes} ## #if ($builderIsInterface) implements #else extends #end ${builderTypeName}${builderActualTypes} { diff --git a/value/userguide/howto.md b/value/userguide/howto.md index 5f8614c6..6b24a7a1 100644 --- a/value/userguide/howto.md +++ b/value/userguide/howto.md @@ -625,6 +625,10 @@ final class AutoValue_Example extends Example { } ``` +Applying `@AutoValue.CopyAnnotations` to an `@AutoValue.Builder` class like +`Foo.Builder` similarly causes annotations on that class to be copied to the +generated subclass `AutoValue_Foo.Builder`. + ### Copying to the generated method For historical reasons, annotations on methods of an `@AutoValue`-annotated |