|
15 | 15 | */
|
16 | 16 | package com.google.auto.value.processor;
|
17 | 17 |
|
18 |
| -import static com.google.common.truth.Truth.assertAbout; |
| 18 | +import static com.google.common.truth.Truth.assertThat; |
19 | 19 | import static com.google.testing.compile.CompilationSubject.assertThat;
|
20 | 20 | import static com.google.testing.compile.CompilationSubject.compilations;
|
21 | 21 | import static com.google.testing.compile.Compiler.javac;
|
22 |
| -import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; |
23 | 22 | import static java.util.stream.Collectors.joining;
|
24 | 23 |
|
25 | 24 | import com.google.common.collect.ImmutableSet;
|
|
34 | 33 | import java.util.stream.Stream;
|
35 | 34 | import javax.annotation.processing.AbstractProcessor;
|
36 | 35 | import javax.annotation.processing.RoundEnvironment;
|
| 36 | +import javax.annotation.processing.SupportedAnnotationTypes; |
37 | 37 | import javax.lang.model.SourceVersion;
|
38 | 38 | import javax.lang.model.element.Element;
|
39 | 39 | import javax.lang.model.element.TypeElement;
|
| 40 | +import javax.lang.model.element.TypeParameterElement; |
40 | 41 | import javax.lang.model.util.ElementFilter;
|
41 | 42 | import javax.tools.JavaFileObject;
|
42 | 43 | import org.junit.Rule;
|
@@ -352,6 +353,75 @@ public void testNestedParameterizedTypesWithTypeAnnotations() throws Exception {
|
352 | 353 | .hasSourceEquivalentTo(expectedOutput);
|
353 | 354 | }
|
354 | 355 |
|
| 356 | + // Tests that type annotations are correctly copied from the bounds of type parameters in the |
| 357 | + // @AutoValue class to the bounds of the corresponding parameters in the generated class. For |
| 358 | + // example, if we have `@AutoValue abstract class Foo<T extends @NullableType Object>`, then the |
| 359 | + // generated class should be `class AutoValue_Foo<T extends @NullableType Object> extends Foo<T>`. |
| 360 | + // Some buggy versions of javac do not report type annotations correctly in this context. |
| 361 | + // AutoValue can't copy them if it can't see them, so we make a special annotation processor to |
| 362 | + // detect if we are in the presence of this bug and if so we don't fail. |
| 363 | + @Test |
| 364 | + public void testTypeParametersWithAnnotationsOnBounds() { |
| 365 | + @SupportedAnnotationTypes("*") |
| 366 | + class CompilerBugProcessor extends AbstractProcessor { |
| 367 | + boolean checkedAnnotationsOnTypeBounds; |
| 368 | + boolean reportsAnnotationsOnTypeBounds; |
| 369 | + |
| 370 | + @Override |
| 371 | + public SourceVersion getSupportedSourceVersion() { |
| 372 | + return SourceVersion.latestSupported(); |
| 373 | + } |
| 374 | + |
| 375 | + @Override |
| 376 | + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| 377 | + if (roundEnv.processingOver()) { |
| 378 | + TypeElement test = processingEnv.getElementUtils().getTypeElement("com.example.Test"); |
| 379 | + TypeParameterElement t = test.getTypeParameters().get(0); |
| 380 | + this.checkedAnnotationsOnTypeBounds = true; |
| 381 | + this.reportsAnnotationsOnTypeBounds = |
| 382 | + !t.getBounds().get(0).getAnnotationMirrors().isEmpty(); |
| 383 | + } |
| 384 | + return false; |
| 385 | + } |
| 386 | + } |
| 387 | + CompilerBugProcessor compilerBugProcessor = new CompilerBugProcessor(); |
| 388 | + JavaFileObject nullableTypeFileObject = |
| 389 | + JavaFileObjects.forSourceLines( |
| 390 | + "foo.bar.NullableType", |
| 391 | + "package foo.bar;", |
| 392 | + "", |
| 393 | + "import java.lang.annotation.ElementType;", |
| 394 | + "import java.lang.annotation.Target;", |
| 395 | + "", |
| 396 | + "@Target(ElementType.TYPE_USE)", |
| 397 | + "public @interface NullableType {}"); |
| 398 | + JavaFileObject autoValueFileObject = |
| 399 | + JavaFileObjects.forSourceLines( |
| 400 | + "com.example.Test", |
| 401 | + "package com.example;", |
| 402 | + "", |
| 403 | + "import com.google.auto.value.AutoValue;", |
| 404 | + "import foo.bar.NullableType;", |
| 405 | + "", |
| 406 | + "@AutoValue", |
| 407 | + "abstract class Test<T extends @NullableType Object & @NullableType Cloneable> {}"); |
| 408 | + Compilation compilation = |
| 409 | + javac() |
| 410 | + .withProcessors(new AutoValueProcessor(), compilerBugProcessor) |
| 411 | + .withOptions("-Xlint:-processing", "-implicit:none") |
| 412 | + .compile(nullableTypeFileObject, autoValueFileObject); |
| 413 | + assertThat(compilation).succeededWithoutWarnings(); |
| 414 | + assertThat(compilerBugProcessor.checkedAnnotationsOnTypeBounds).isTrue(); |
| 415 | + if (compilerBugProcessor.reportsAnnotationsOnTypeBounds) { |
| 416 | + assertThat(compilation) |
| 417 | + .generatedSourceFile("com.example.AutoValue_Test") |
| 418 | + .contentsAsUtf8String() |
| 419 | + .contains( |
| 420 | + "class AutoValue_Test<T extends @NullableType Object & @NullableType Cloneable>" |
| 421 | + + " extends Test<T> {"); |
| 422 | + } |
| 423 | + } |
| 424 | + |
355 | 425 | // In the following few tests, see AutoValueProcessor.validateMethods for why unrecognized
|
356 | 426 | // abstract methods provoke only a warning rather than an error. Compilation will fail anyway
|
357 | 427 | // because the generated class is not abstract and does not implement the unrecognized methods.
|
@@ -2538,12 +2608,13 @@ public void autoValueBuilderToBuilderWrongTypeParameters() {
|
2538 | 2608 | " Baz<K, V> build();",
|
2539 | 2609 | " }",
|
2540 | 2610 | "}");
|
2541 |
| - assertAbout(javaSource()) |
2542 |
| - .that(javaFileObject) |
2543 |
| - .processedWith(new AutoValueProcessor(), new AutoValueBuilderProcessor()) |
2544 |
| - .failsToCompile() |
2545 |
| - .withErrorContaining("Builder converter method should return foo.bar.Baz.Builder<K, V>") |
2546 |
| - .in(javaFileObject) |
| 2611 | + Compilation compilation = |
| 2612 | + javac() |
| 2613 | + .withProcessors(new AutoValueProcessor(), new AutoValueBuilderProcessor()) |
| 2614 | + .compile(javaFileObject); |
| 2615 | + assertThat(compilation) |
| 2616 | + .hadErrorContaining("Builder converter method should return foo.bar.Baz.Builder<K, V>") |
| 2617 | + .inFile(javaFileObject) |
2547 | 2618 | .onLine(9);
|
2548 | 2619 | }
|
2549 | 2620 |
|
|
0 commit comments