aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremcmanus <emcmanus@google.com>2020-06-08 09:34:01 -0700
committerChris Povirk <beigetangerine@gmail.com>2020-06-09 08:37:32 -0400
commitb22f969d63d7dc6f2163092637c2ba4c763f00bc (patch)
tree0a708fe8a87a89f9236af71facefe06cdb0d16cb
parentb9ba06a327d08a741ed70f1573540e063fb6c69c (diff)
downloadauto-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
-rw-r--r--value/src/it/functional/src/test/java/com/google/auto/value/AutoValueTest.java52
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java2
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfTemplateVars.java7
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java14
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoValueTemplateVars.java10
-rw-r--r--value/src/main/java/com/google/auto/value/processor/BuilderSpec.java8
-rw-r--r--value/src/main/java/com/google/auto/value/processor/autovalue.vm7
-rw-r--r--value/userguide/howto.md4
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