Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of AutoValue extensions in AutoValueSubclassLeaked #4509

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import static com.google.errorprone.util.ASTHelpers.hasAnnotation;
import static com.google.errorprone.util.ASTHelpers.isSubtype;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
Expand All @@ -39,6 +38,7 @@
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.TypeTag;
import java.util.regex.Pattern;

/** Matches {@code AutoValue_} uses outside the containing file. */
Expand All @@ -58,6 +58,8 @@ public final class AutoValueSubclassLeaked extends BugChecker

private static final Pattern AUTO_VALUE_PREFIX = Pattern.compile("\\$*AutoValue_.*");

private static final String AUTO_VALUE_ANNOTATION = "com.google.auto.value.AutoValue";

@Override
public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) {
ImmutableSet<Type> autoValueClassesFromThisFile = findAutoValueClasses(tree, state);
Expand Down Expand Up @@ -110,9 +112,20 @@ private static ImmutableSet<Type> findAutoValueClasses(
new TreeScanner<Void, Void>() {
@Override
public Void visitClass(ClassTree classTree, Void unused) {
if (hasAnnotation(classTree, AutoValue.class, state)) {
if (hasAnnotation(classTree, AUTO_VALUE_ANNOTATION, state)) {
types.add(getType(classTree));
}
ClassSymbol classSymbol = getSymbol(classTree);
if (AUTO_VALUE_PREFIX.matcher(classSymbol.getSimpleName().toString()).matches()) {
for (Type type = classSymbol.asType();
!type.hasTag(TypeTag.NONE);
type = state.getTypes().supertype(type)) {
if (hasAnnotation(type.asElement(), AUTO_VALUE_ANNOTATION, state)) {
types.add(type);
break;
}
}
}
return super.visitClass(classTree, null);
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,43 @@ public void positiveAutoValueExtension() {
"}")
.doTest();
}

@Test
public void positiveAutoValueExtension_noGeneratedAnnotation() {
CompilationTestHelper.newInstance(AutoValueSubclassLeaked.class, getClass())
.addSourceLines(
"$AutoValue_Test_Foo.java", //
"package test;",
"final class AutoValue_Test_Foo extends $AutoValue_Test_Foo {",
" static final Test.Foo AUTO_VALUE = new AutoValue_Test_Foo();",
"}")
.addSourceLines(
"$AutoValue_Test_Foo.java", //
"package test;",
"import javax.annotation.processing.Generated;",
"@Generated(\"com.google.auto.value.processor.AutoValueProcessor\")",
"class $AutoValue_Test_Foo extends Test.Foo {",
"}")
.addSourceLines(
"Test.java",
"package test;",
"import com.google.auto.value.AutoValue;",
"class Test {",
" static final Test.Foo EXTENSION = new $AutoValue_Test_Foo();",
" static final Test.Foo AUTO_VALUE = new AutoValue_Test_Foo();",
" @AutoValue",
" abstract static class Foo {",
" }",
"}")
.addSourceLines(
"Bar.java",
"package test;",
"class Bar {",
" // BUG: Diagnostic contains:",
" static final Test.Foo EXTENSION = new $AutoValue_Test_Foo();",
" // BUG: Diagnostic contains:",
" static final Test.Foo AUTO_VALUE = new AutoValue_Test_Foo();",
"}")
.doTest();
}
}
Loading