From 4506804f1cc40e565eaf79e42c7ef3e6a23f0890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89amonn=20McManus?= Date: Thu, 24 Aug 2023 08:42:24 -0700 Subject: [PATCH] Apply `@Nullable` to fields in the generated class where appropriate. We already did this if it was a `TYPE_USE` `@Nullable` or if the corresponding property method was annotated with `@CopyAnnotations`. Now we do it in every other case as well. RELNOTES=If an AutoValue property method is `@Nullable`, the corresponding field in the generated class will be too. This was already the case for `TYPE_USE` `@Nullable` or if the method had `@CopyAnnotations`, but now `@Nullable` will be copied in other cases too. PiperOrigin-RevId: 559765107 --- .../processor/AutoValueishProcessor.java | 23 +++++++++++++++---- .../processor/AutoValueCompilationTest.java | 1 + 2 files changed, 19 insertions(+), 5 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 b7bee4297c..82d31bf8c7 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 @@ -17,6 +17,7 @@ import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; import static com.google.auto.common.GeneratedAnnotations.generatedAnnotation; +import static com.google.auto.common.MoreElements.asType; import static com.google.auto.common.MoreElements.getPackage; import static com.google.auto.common.MoreElements.isAnnotationPresent; import static com.google.auto.common.MoreStreams.toImmutableList; @@ -1215,8 +1216,24 @@ final ImmutableListMultimap propertyFieldAn private ImmutableList propertyFieldAnnotations( TypeElement type, ExecutableElement method) { + // We need to exclude type annotations from the ones being output on the method, since + // they will be output as part of the field's type. + Set returnTypeAnnotations = + getReturnTypeAnnotations(method, this::annotationAppliesToFields); if (!hasAnnotationMirror(method, COPY_ANNOTATIONS_NAME)) { - return ImmutableList.of(); + // If there's no @CopyAnnotations, we will still copy a @Nullable annotation, if (1) it is not + // a TYPE_USE annotation (those appear as part of the type in the generated code) and (2) it + // applies to fields. All known non-TYPE_USE @Nullable annotations do apply to fields, but we + // check just in case. + return method.getAnnotationMirrors().stream() + .filter( + a -> { + TypeElement annotationType = asType(a.getAnnotationType().asElement()); + return isNullable(a) + && !returnTypeAnnotations.contains(annotationType.getQualifiedName().toString()) + && annotationAppliesToFields(annotationType); + }) + .collect(toImmutableList()); } ImmutableSet excludedAnnotations = ImmutableSet.builder() @@ -1224,10 +1241,6 @@ private ImmutableList propertyFieldAnnotations( .add(Override.class.getCanonicalName()) .build(); - // We need to exclude type annotations from the ones being output on the method, since - // they will be output as part of the field's type. - Set returnTypeAnnotations = - getReturnTypeAnnotations(method, this::annotationAppliesToFields); Set nonFieldAnnotations = method.getAnnotationMirrors().stream() .map(a -> a.getAnnotationType().asElement()) 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 e9fdcbfd6e..d30198cfa9 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 @@ -1163,6 +1163,7 @@ public void correctBuilder() { "final class AutoValue_Baz extends Baz {", " private final int anInt;", " private final byte[] aByteArray;", + " @Nullable", " private final int[] aNullableIntArray;", " private final List aList;", " private final ImmutableMap anImmutableMap;",