diff --git a/check_api/src/main/java/com/google/errorprone/util/ASTHelpers.java b/check_api/src/main/java/com/google/errorprone/util/ASTHelpers.java index 9ee352f0a6b..dc4cee23df9 100644 --- a/check_api/src/main/java/com/google/errorprone/util/ASTHelpers.java +++ b/check_api/src/main/java/com/google/errorprone/util/ASTHelpers.java @@ -1274,11 +1274,12 @@ public static ImmutableSet getGeneratedBy(VisitorState state) { return getGeneratedBy(getSymbol(outerClass), state); } + /** * Returns the values of the given symbol's {@code javax.annotation.Generated} or {@code * javax.annotation.processing.Generated} annotation, if present. */ - public static ImmutableSet getGeneratedBy(ClassSymbol symbol, VisitorState state) { + public static ImmutableSet getGeneratedBy(Symbol symbol, VisitorState state) { checkNotNull(symbol); Optional c = Stream.of("javax.annotation.Generated", "javax.annotation.processing.Generated") diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/ExtendsAutoValue.java b/core/src/main/java/com/google/errorprone/bugpatterns/ExtendsAutoValue.java index 4894cbf376e..2632232c822 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/ExtendsAutoValue.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/ExtendsAutoValue.java @@ -16,6 +16,8 @@ package com.google.errorprone.bugpatterns; +import static com.google.common.collect.Streams.stream; + import com.google.common.collect.ImmutableSet; import com.google.errorprone.BugPattern; import com.google.errorprone.BugPattern.SeverityLevel; @@ -26,6 +28,7 @@ import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.ClassTree; import com.sun.tools.javac.util.Name; +import java.util.Objects; /** Makes sure that you are not extending a class that has @AutoValue as an annotation. */ @BugPattern( @@ -43,24 +46,29 @@ public final class ExtendsAutoValue extends BugChecker implements ClassTreeMatch @Override public Description matchClass(ClassTree tree, VisitorState state) { - - if (!ASTHelpers.getGeneratedBy(ASTHelpers.getSymbol(tree), state).isEmpty()) { - // Skip generated code. Yes, I know we can do this via a flag but we should always ignore - // generated code, so to be sure, manually check it. - return Description.NO_MATCH; - } - if (tree.getExtendsClause() == null) { // Doesn't extend anything, can't possibly be a violation. return Description.NO_MATCH; } + if (!ASTHelpers.annotationsAmong( ASTHelpers.getSymbol(tree.getExtendsClause()), AUTOS.get(state), state) .isEmpty()) { // Violation: one of its superclasses extends AutoValue. - return buildDescription(tree).build(); + if (!isInGeneratedCode(state)) { + return buildDescription(tree).build(); + } } return Description.NO_MATCH; } + + private static boolean isInGeneratedCode(VisitorState state) { + // Skip generated code. Yes, I know we can do this via a flag but we should always ignore + // generated code, so to be sure, manually check it. + return stream(state.getPath()) + .map(ASTHelpers::getSymbol) + .filter(Objects::nonNull) + .anyMatch(sym -> !ASTHelpers.getGeneratedBy(sym, state).isEmpty()); + } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ExtendsAutoValueTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ExtendsAutoValueTest.java index 7a569aa7d12..ff7c15894fb 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ExtendsAutoValueTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ExtendsAutoValueTest.java @@ -150,4 +150,37 @@ public void extendsAutoValue_badButSuppressed() { "public class TestClass extends AutoClass {}") .doTest(); } + + @Test + public void extendsAutoValue_innerClassExtends() { + helper + .addSourceLines( + "TestClass.java", + "import com.google.auto.value.AutoValue;", + "@AutoValue class AutoClass {}", + "", + "public class TestClass {", + " // BUG: Diagnostic contains: ExtendsAutoValue", + " public class Extends extends AutoClass {}", + "}") + .doTest(); + } + + @Test + public void extendsAutoValue_innerClassExtends_generated() { + helper + .addSourceLines( + "TestClass.java", + "import com.google.auto.value.AutoValue;", + (RuntimeVersion.isAtLeast9() + ? "import javax.annotation.processing.Generated;" + : "import javax.annotation.Generated;"), + "@AutoValue class AutoClass {}", + "", + "@Generated(\"generator\")", + "public class TestClass {", + " public class Extends extends AutoClass {}", + "}") + .doTest(); + } }