diff options
author | Éamonn McManus <emcmanus@google.com> | 2021-10-05 15:34:20 -0700 |
---|---|---|
committer | Google Java Core Libraries <java-libraries-firehose+copybara@google.com> | 2021-10-05 15:34:55 -0700 |
commit | 8ad800edde0e8c743666a5d814e86ecd6c6f39c6 (patch) | |
tree | c888bec7aca6504aed31d89eade23ec7edba68c7 /value/src | |
parent | 206b67396601d99fe87580e7b76d65d3035cc8e3 (diff) | |
download | auto-8ad800edde0e8c743666a5d814e86ecd6c6f39c6.tar.gz |
Ensure the order of copied annotations is deterministic.
Fixes https://github.com/google/auto/issues/1176.
RELNOTES=The order of annotations copied into generated code is now deterministic.
PiperOrigin-RevId: 401086698
Diffstat (limited to 'value/src')
3 files changed, 72 insertions, 7 deletions
diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueishProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoValueishProcessor.java index ea085575..55a94a71 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueishProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueishProcessor.java @@ -501,9 +501,9 @@ abstract class AutoValueishProcessor extends AbstractProcessor { /** Returns the spelling to be used in the generated code for the given list of annotations. */ static ImmutableList<String> annotationStrings(List<? extends AnnotationMirror> annotations) { - // TODO(b/68008628): use ImmutableList.toImmutableList() when that works. return annotations.stream() .map(AnnotationOutput::sourceFormForAnnotation) + .sorted() // ensures deterministic order .collect(toImmutableList()); } @@ -623,8 +623,9 @@ abstract class AutoValueishProcessor extends AbstractProcessor { List<? extends AnnotationMirror> elementAnnotations = element.getAnnotationMirrors(); OptionalInt nullableAnnotationIndex = nullableAnnotationIndex(elementAnnotations); if (nullableAnnotationIndex.isPresent()) { - ImmutableList<String> annotations = annotationStrings(elementAnnotations); - return Optional.of(annotations.get(nullableAnnotationIndex.getAsInt()) + " "); + AnnotationMirror annotation = elementAnnotations.get(nullableAnnotationIndex.getAsInt()); + String annotationString = AnnotationOutput.sourceFormForAnnotation(annotation); + return Optional.of(annotationString + " "); } else { return Optional.empty(); } diff --git a/value/src/test/java/com/google/auto/value/processor/AutoValueCompilationTest.java b/value/src/test/java/com/google/auto/value/processor/AutoValueCompilationTest.java index ab6690fd..9d7f7856 100644 --- a/value/src/test/java/com/google/auto/value/processor/AutoValueCompilationTest.java +++ b/value/src/test/java/com/google/auto/value/processor/AutoValueCompilationTest.java @@ -3052,6 +3052,63 @@ public class AutoValueCompilationTest { } @Test + public void methodAnnotationsCopiedInLexicographicalOrder() { + JavaFileObject bazFileObject = + JavaFileObjects.forSourceLines( + "foo.bar.Baz", + "package foo.bar;", + "", + "import com.google.auto.value.AutoValue;", + "import com.package1.Annotation1;", + "import com.package2.Annotation0;", + "", + "@AutoValue", + "public abstract class Baz extends Parent {", + " @Annotation0", + " @Annotation1", + " @Override", + " public abstract String foo();", + "}"); + JavaFileObject parentFileObject = + JavaFileObjects.forSourceLines( + "foo.bar.Parent", + "package foo.bar;", + "", + "public abstract class Parent {", + " public abstract String foo();", + "}"); + JavaFileObject annotation1FileObject = + JavaFileObjects.forSourceLines( + "com.package1.Annotation1", + "package com.package1;", + "", + "import java.lang.annotation.ElementType;", + "import java.lang.annotation.Target;", + "", + "@Target({ElementType.FIELD, ElementType.METHOD})", + "public @interface Annotation1 {}"); + JavaFileObject annotation0FileObject = + JavaFileObjects.forSourceLines( + "com.package2.Annotation0", + "package com.package2;", + "", + "public @interface Annotation0 {}"); + Compilation compilation = + javac() + .withProcessors(new AutoValueProcessor()) + .withOptions("-Xlint:-processing", "-implicit:none") + .compile(bazFileObject, parentFileObject, annotation1FileObject, annotation0FileObject); + assertThat(compilation).succeededWithoutWarnings(); + assertThat(compilation) + .generatedSourceFile("foo.bar.AutoValue_Baz") + .contentsAsUtf8String() + .containsMatch( + "(?s:@Annotation1\\s+@Annotation0\\s+@Override\\s+public String foo\\(\\))"); + // @Annotation1 precedes @Annotation 0 because + // @com.package2.Annotation1 precedes @com.package1.Annotation0 + } + + @Test public void nonVisibleProtectedAnnotationFromOtherPackage() { JavaFileObject bazFileObject = JavaFileObjects.forSourceLines( diff --git a/value/src/test/java/com/google/auto/value/processor/PropertyAnnotationsTest.java b/value/src/test/java/com/google/auto/value/processor/PropertyAnnotationsTest.java index 48d8cd6e..1d7e89f5 100644 --- a/value/src/test/java/com/google/auto/value/processor/PropertyAnnotationsTest.java +++ b/value/src/test/java/com/google/auto/value/processor/PropertyAnnotationsTest.java @@ -510,11 +510,14 @@ public class PropertyAnnotationsTest { "@PropertyAnnotationsTest.InheritedAnnotation") .build(); + // Annotations are in lexicographical order of FQN: + // @com.google.auto.value.processor.PropertyAnnotationsTest.InheritedAnnotation precedes + // @java.lang.Deprecated JavaFileObject outputFile = new OutputFileBuilder() .setImports(imports) - .addMethodAnnotations("@Deprecated", "@PropertyAnnotationsTest.InheritedAnnotation") - .addFieldAnnotations("@Deprecated", "@PropertyAnnotationsTest.InheritedAnnotation") + .addMethodAnnotations("@PropertyAnnotationsTest.InheritedAnnotation", "@Deprecated") + .addFieldAnnotations("@PropertyAnnotationsTest.InheritedAnnotation", "@Deprecated") .build(); Compilation compilation = @@ -548,12 +551,16 @@ public class PropertyAnnotationsTest { .addInnerTypes("@Target(ElementType.METHOD) @interface MethodsOnly {}") .build(); + // Annotations are in lexicographical order of FQN: + // @com.google.auto.value.processor.PropertyAnnotationsTest.InheritedAnnotation precedes + // @foo.bar.Baz.MethodsOnly precedes + // @java.lang.Deprecated JavaFileObject outputFile = new OutputFileBuilder() .setImports(getImports(PropertyAnnotationsTest.class)) - .addFieldAnnotations("@Deprecated", "@PropertyAnnotationsTest.InheritedAnnotation") + .addFieldAnnotations("@PropertyAnnotationsTest.InheritedAnnotation", "@Deprecated") .addMethodAnnotations( - "@Deprecated", "@PropertyAnnotationsTest.InheritedAnnotation", "@Baz.MethodsOnly") + "@PropertyAnnotationsTest.InheritedAnnotation", "@Baz.MethodsOnly", "@Deprecated") .build(); Compilation compilation = |