diff --git a/common/src/main/java/com/google/auto/common/SuperficialValidation.java b/common/src/main/java/com/google/auto/common/SuperficialValidation.java index a7b8ebcfa9..92c73734b9 100644 --- a/common/src/main/java/com/google/auto/common/SuperficialValidation.java +++ b/common/src/main/java/com/google/auto/common/SuperficialValidation.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.AnnotationValueVisitor; @@ -63,10 +64,13 @@ public static boolean validateElements(Iterable elements) { } @Override public Boolean visitType(TypeElement e, Void p) { + TypeMirror superclass = e.getSuperclass(); return isValidBaseElement(e) && validateElements(e.getTypeParameters()) && validateTypes(e.getInterfaces()) - && validateType(e.getSuperclass()); + && validateType(superclass) + && validateElements(e.getInterfaces().stream().map(MoreTypes::asElement).collect(Collectors.toList())) + && (superclass.getKind() == TypeKind.NONE || validateElement(MoreTypes.asElement(superclass))); } @Override public Boolean visitVariable(VariableElement e, Void p) { diff --git a/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java b/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java index 15e54fff52..165bc9377d 100644 --- a/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java +++ b/common/src/test/java/com/google/auto/common/SuperficialValidationTest.java @@ -276,6 +276,90 @@ void runAssertions() { .failsToCompile(); } + @Test + public void missingSuperclass() { + JavaFileObject javaFileObject = JavaFileObjects.forSourceLines( + "test.TestClass", + "package test;", + "", + "class TestClass extends Missing {}"); + assertAbout(javaSource()) + .that(javaFileObject) + .processedWith(new AssertingProcessor() { + @Override + void runAssertions() { + TypeElement testClassElement = + processingEnv.getElementUtils().getTypeElement("test.TestClass"); + assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse(); + } + }) + .failsToCompile(); + } + + @Test + public void missingSuperinterface() { + JavaFileObject javaFileObject = JavaFileObjects.forSourceLines( + "test.TestClass", + "package test;", + "", + "class TestClass implements Missing {}"); + assertAbout(javaSource()) + .that(javaFileObject) + .processedWith(new AssertingProcessor() { + @Override + void runAssertions() { + TypeElement testClassElement = + processingEnv.getElementUtils().getTypeElement("test.TestClass"); + assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse(); + } + }) + .failsToCompile(); + } + + @Test + public void missingGrandparentSuperclass() { + JavaFileObject javaFileObject = JavaFileObjects.forSourceLines( + "test.TestClass", + "package test;", + "", + "class Parent extends Missing {}", + "", + "class TestClass extends Parent {}"); + assertAbout(javaSource()) + .that(javaFileObject) + .processedWith(new AssertingProcessor() { + @Override + void runAssertions() { + TypeElement testClassElement = + processingEnv.getElementUtils().getTypeElement("test.TestClass"); + assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse(); + } + }) + .failsToCompile(); + } + + @Test + public void missingGrandparentSuperinterface() { + JavaFileObject javaFileObject = JavaFileObjects.forSourceLines( + "test.TestClass", + "package test;", + "", + "interface Parent extends Missing {}", + "", + "class TestClass implements Parent {}"); + assertAbout(javaSource()) + .that(javaFileObject) + .processedWith(new AssertingProcessor() { + @Override + void runAssertions() { + TypeElement testClassElement = + processingEnv.getElementUtils().getTypeElement("test.TestClass"); + assertThat(SuperficialValidation.validateElement(testClassElement)).isFalse(); + } + }) + .failsToCompile(); + } + private abstract static class AssertingProcessor extends AbstractProcessor { @Override public Set getSupportedAnnotationTypes() {