aboutsummaryrefslogtreecommitdiff
path: root/value/src/test/java/com/google
diff options
context:
space:
mode:
authorÉamonn McManus <emcmanus@google.com>2020-11-16 10:46:55 -0800
committerGoogle Java Core Libraries <java-core-libraries-team+copybara@google.com>2020-11-16 10:47:30 -0800
commitf2cb2247898dcdcb05d52f1faf9689ecef4c0c41 (patch)
treea614486b8af8a1bb88281887c2f84b98fa6e2f08 /value/src/test/java/com/google
parent97863af8fda6e87250dae9e477f98de62d1ff28b (diff)
downloadauto-f2cb2247898dcdcb05d52f1faf9689ecef4c0c41.tar.gz
The methods returned by `BuilderContext.buildMethod()` and `.toBuilderMethods()` can be inherited.
This change addresses cases like this: ```java interface Parent<BuilderT> { BuilderT toBuilder(); interface Builder<BuilderT, BuiltT> {", BuilderT setThing(String x);", BuiltT build();", } } @AutoValue abstract class Foo implements Parent<Foo.Builder> { @AutoValue.Builder abstract static class Builder implements Parent.Builder<Builder, Foo> {} } ``` Previously, there would be two problems with this. First, inheriting `toBuilder()` like this didn't work at all, because its return type is `BuilderT` and not `Foo.Builder`. Now we correctly interpret the inherited return type in the context of `Foo`. Second, in `BuilderContext.buildMethod()` we were looking for methods returning `Foo`, and again this failed because the inherited `build()` method returns `BuiltT`. The fix in both cases is to use `Types.asMemberOf` to determine the correct return type in context. Fixes https://github.com/google/auto/issues/933. RELNOTES=The methods returned by `BuilderContext.buildMethod()` and `.toBuilderMethods()` can be inherited. PiperOrigin-RevId: 342670816
Diffstat (limited to 'value/src/test/java/com/google')
-rw-r--r--value/src/test/java/com/google/auto/value/processor/ExtensionTest.java72
1 files changed, 72 insertions, 0 deletions
diff --git a/value/src/test/java/com/google/auto/value/processor/ExtensionTest.java b/value/src/test/java/com/google/auto/value/processor/ExtensionTest.java
index ce9eeed0..8f74d5df 100644
--- a/value/src/test/java/com/google/auto/value/processor/ExtensionTest.java
+++ b/value/src/test/java/com/google/auto/value/processor/ExtensionTest.java
@@ -1075,6 +1075,78 @@ public class ExtensionTest {
}
@Test
+ public void builderContextWithInheritance() {
+ JavaFileObject parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Parent",
+ "package foo.bar;",
+ "",
+ "interface Parent<BuilderT> {",
+ " BuilderT toBuilder();",
+ " interface Builder<T, BuilderT, BuiltT> {",
+ " BuilderT setThing(T x);",
+ " BuiltT build();",
+ " }",
+ "}");
+ JavaFileObject autoValueClass = JavaFileObjects.forSourceLines(
+ "foo.bar.Baz",
+ "package foo.bar;",
+ "",
+ "import com.google.auto.value.AutoValue;",
+ "",
+ "@AutoValue",
+ "abstract class Baz<T> implements Parent<Baz.Builder<T>> {",
+ " abstract T thing();",
+ " static <T> Builder<T> builder() {",
+ " return new AutoValue_Baz.Builder<>();",
+ " }",
+ "",
+ " @AutoValue.Builder",
+ " abstract static class Builder<T> implements Parent.Builder<T, Builder<T>, Baz<T>> {",
+ " }",
+ "}");
+ ContextChecker checker =
+ context -> {
+ assertThat(context.builder()).isPresent();
+ BuilderContext builderContext = context.builder().get();
+
+ assertThat(builderContext.builderType().getQualifiedName().toString())
+ .isEqualTo("foo.bar.Baz.Builder");
+
+ Set<ExecutableElement> builderMethods = builderContext.builderMethods();
+ assertThat(builderMethods).hasSize(1);
+ ExecutableElement builderMethod = Iterables.getOnlyElement(builderMethods);
+ assertThat(builderMethod.getSimpleName().toString()).isEqualTo("builder");
+
+ Set<ExecutableElement> toBuilderMethods = builderContext.toBuilderMethods();
+ assertThat(toBuilderMethods).hasSize(1);
+ ExecutableElement toBuilderMethod = Iterables.getOnlyElement(toBuilderMethods);
+ assertThat(toBuilderMethod.getSimpleName().toString()).isEqualTo("toBuilder");
+
+ Optional<ExecutableElement> buildMethod = builderContext.buildMethod();
+ assertThat(buildMethod).isPresent();
+ assertThat(buildMethod.get().getSimpleName().toString()).isEqualTo("build");
+ assertThat(buildMethod.get().getParameters()).isEmpty();
+ assertThat(buildMethod.get().getReturnType().toString()).isEqualTo("BuiltT");
+
+ ExecutableElement autoBuildMethod = builderContext.autoBuildMethod();
+ assertThat(autoBuildMethod).isEqualTo(buildMethod.get());
+
+ Map<String, Set<ExecutableElement>> setters = builderContext.setters();
+ assertThat(setters.keySet()).containsExactly("thing");
+ Set<ExecutableElement> thingSetters = setters.get("thing");
+ assertThat(thingSetters).hasSize(1);
+ ExecutableElement thingSetter = Iterables.getOnlyElement(thingSetters);
+ assertThat(thingSetter.getSimpleName().toString()).isEqualTo("setThing");
+ };
+ ContextCheckingExtension extension = new ContextCheckingExtension(checker);
+ Compilation compilation =
+ javac()
+ .withProcessors(new AutoValueProcessor(ImmutableList.of(extension)))
+ .compile(autoValueClass, parent);
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
public void oddBuilderContext() {
JavaFileObject autoValueClass = JavaFileObjects.forSourceLines(
"foo.bar.Baz",