Skip to content

Commit

Permalink
Retain type-use annotations such as @Nullable in generated builder …
Browse files Browse the repository at this point in the history
…setters.

This handles a further case using the logic introduced by #1704.

RELNOTES=Type-use annotations such as `@Nullable` are now better preserved in generated builder setter method parameters. Previously they could be lost in some circumstances, for example with `@Nullable T`.
PiperOrigin-RevId: 699982315
  • Loading branch information
eamonnmcmanus authored and Google Java Core Libraries committed Nov 25, 2024
1 parent 68df67d commit 19a71a7
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,8 @@ private void classifyMethodOneArg(ExecutableElement method) {
+ " is not appropriate", autoWhat());
}
// We allow the return type to be a supertype (other than Object), to support step builders.
TypeMirror parameterType =
Iterables.getOnlyElement(methodSignature.parameterTypes()).getType();
AnnotatedTypeMirror parameterType =
Iterables.getOnlyElement(methodSignature.parameterTypes());
propertyNameToSetters.put(
propertyName, new PropertySetter(method, parameterType, function.get()));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,25 +462,27 @@ public static class PropertySetter {
private final String nullableAnnotation;
private final Copier copier;

PropertySetter(ExecutableElement setter, TypeMirror parameterType, Copier copier) {
PropertySetter(ExecutableElement setter, AnnotatedTypeMirror parameterType, Copier copier) {
this.setter = setter;
this.copier = copier;
this.access = SimpleMethod.access(setter);
this.name = setter.getSimpleName().toString();
primitiveParameter = parameterType.getKind().isPrimitive();
this.parameterTypeString = parameterTypeString(setter, parameterType);
VariableElement parameterElement = Iterables.getOnlyElement(setter.getParameters());
Optional<String> maybeNullable = nullableAnnotationFor(parameterElement, parameterType);
Optional<String> maybeNullable =
nullableAnnotationFor(parameterElement, parameterType.getType());
this.nullableAnnotation = maybeNullable.orElse("");
}

ExecutableElement getSetter() {
return setter;
}

private static String parameterTypeString(ExecutableElement setter, TypeMirror parameterType) {
private static String parameterTypeString(
ExecutableElement setter, AnnotatedTypeMirror parameterType) {
if (setter.isVarArgs()) {
TypeMirror componentType = MoreTypes.asArray(parameterType).getComponentType();
TypeMirror componentType = MoreTypes.asArray(parameterType.getType()).getComponentType();
// This is a bit ugly. It's OK to annotate just the component type, because if it is
// say `@Nullable String` then we will end up with `@Nullable String...`. Unlike the
// normal array case, we can't have the situation where the array itself is annotated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,40 @@ public void simpleRecord() {
.hasSourceEquivalentTo(EXPECTED_SIMPLE_OUTPUT);
}

@Test
public void recordWithNullableTypeVariableComponents() {
double version = Double.parseDouble(JAVA_SPECIFICATION_VERSION.value());
assume().that(version).isAtLeast(16.0);
JavaFileObject javaFileObject =
JavaFileObjects.forSourceLines(
"foo.bar.Baz",
"package foo.bar;",
"",
"import com.google.auto.value.AutoBuilder;",
"import org.checkerframework.checker.nullness.qual.Nullable;",
"",
"public record Baz<T>(int anInt, @Nullable T aT) {",
" public static Builder builder() {",
" return new AutoBuilder_Baz_Builder();",
" }",
"",
" @AutoBuilder",
" public interface Builder<T> {",
" Builder setAnInt(int x);",
" Builder setAT(@Nullable T x);",
" Baz<T> build();",
" }",
"}");
Compilation compilation =
javac()
.withProcessors(new AutoBuilderProcessor())
.compile(javaFileObject);
assertThat(compilation)
.generatedSourceFile("foo.bar.AutoBuilder_Baz_Builder")
.contentsAsUtf8String()
.contains("public Baz.Builder<T> setAT(@Nullable T aT) {");
}

@Test
public void recordWithNullableNestedComponentType() {
double version = Double.parseDouble(JAVA_SPECIFICATION_VERSION.value());
Expand Down

0 comments on commit 19a71a7

Please sign in to comment.