Skip to content

Commit 8ba4531

Browse files
eamonnmcmanusGoogle Java Core Libraries
authored andcommitted
Make property builders a bit more flexible.
Allow a property of type `List<T>` to be built by a property builder whose `build()` method returns `List<? extends T>`. This can show up in various `@AutoBuilder` scenarios with Kotlin, for example. RELNOTES=A property of type `List<T>` can be built by a property builder whose `build()` method returns `List<? extends T>`. PiperOrigin-RevId: 508665647
1 parent 162ae8f commit 8ba4531

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

value/src/it/functional/src/test/java/com/google/auto/value/AutoValueJava8Test.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.lang.reflect.Method;
4141
import java.lang.reflect.TypeVariable;
4242
import java.util.Arrays;
43+
import java.util.ArrayList;
4344
import java.util.List;
4445
import java.util.Optional;
4546
import java.util.OptionalDouble;
@@ -922,4 +923,45 @@ public void nestedOptionalGetter() {
922923
assertThat(foo.bar()).isNotNull();
923924
assertThat(foo.baz()).isEqualTo(0.0);
924925
}
926+
927+
// Test that we can build a property of type List<? extends Foo> using a property builder whose
928+
// build() method returns List<Foo>. The main motivation for this is Kotlin, where you can
929+
// easily run into this situation with "in" types.
930+
// This is a "Java 8" test because the generated code uses List.of (which is actually Java 9).
931+
// If we really are on Java 8 then the generated code will use `new ListBuilder<T>().build()`
932+
// instead.
933+
@AutoValue
934+
public abstract static class PropertyBuilderWildcard<T> {
935+
public abstract List<? extends T> list();
936+
937+
public static <T>PropertyBuilderWildcard.Builder<T> builder() {
938+
return new AutoValue_AutoValueJava8Test_PropertyBuilderWildcard.Builder<>();
939+
}
940+
941+
@AutoValue.Builder
942+
public interface Builder<T> {
943+
ListBuilder<T> listBuilder();
944+
945+
PropertyBuilderWildcard<T> build();
946+
}
947+
948+
public static class ListBuilder<T> {
949+
private final List<T> list = new ArrayList<>();
950+
951+
public void add(T value) {
952+
list.add(value);
953+
}
954+
955+
public List<T> build() {
956+
return list;
957+
}
958+
}
959+
}
960+
961+
@Test
962+
public void propertyBuilderWildcard() {
963+
PropertyBuilderWildcard.Builder<CharSequence> builder = PropertyBuilderWildcard.builder();
964+
builder.listBuilder().add("foo");
965+
assertThat(builder.build().list()).containsExactly("foo");
966+
}
925967
}

value/src/main/java/com/google/auto/value/processor/PropertyBuilderClassifier.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,9 @@ Optional<PropertyBuilder> makePropertyBuilder(ExecutableElement method, String p
275275

276276
// We've determined that `BarBuilder` has a method `build()` or `buildOrThrow(). But it must
277277
// return `Bar`. And if the type of `bar()` is Bar<String> then `BarBuilder.build()` must return
278-
// Bar<String>.
278+
// something that can be assigned to Bar<String>.
279279
TypeMirror buildType = eclipseHack.methodReturnType(build, barBuilderDeclaredType);
280-
if (!MoreTypes.equivalence().equivalent(barTypeMirror, buildType)) {
280+
if (!typeUtils.isAssignable(buildType, barTypeMirror)) {
281281
errorReporter.reportError(
282282
method,
283283
"[AutoValueBuilderWrongType] Property builder for %s has type %s whose %s() method"

0 commit comments

Comments
 (0)