diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java b/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java index 6bdc0b254a3..13f2d782e85 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java @@ -44,6 +44,7 @@ import com.sun.source.tree.VariableTree; import com.sun.source.util.TreePathScanner; import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; import java.util.Objects; @@ -99,6 +100,18 @@ public Description matchVariable(VariableTree tree, VisitorState state) { if (type == null || !state.getTypes().isFunctionalInterface(type)) { return NO_MATCH; } + MethodSymbol methodSymbol = getSymbol(implementation); + if (methodSymbol == null) { + return NO_MATCH; + } + Symbol descriptorSymbol = state.getTypes().findDescriptorSymbol(type.tsym); + if (!methodSymbol.getSimpleName().contentEquals(descriptorSymbol.getSimpleName())) { + return NO_MATCH; + } + if (!methodSymbol.overrides( + descriptorSymbol, methodSymbol.owner.enclClass(), state.getTypes(), false)) { + return NO_MATCH; + } if (state.isAndroidCompatible()) { return NO_MATCH; } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClassTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClassTest.java index e9b89c93886..fe371e8e389 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClassTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClassTest.java @@ -91,4 +91,29 @@ public void variable_static() { "}") .doTest(); } + + @Test + public void abstractClass() { + testHelper + .addInputLines( + "Test.java", + "import java.util.function.Function;", + "class Test {", + " static abstract class Impl implements Function {", + " public String apply(String input) {", + " return input;", + " }", + " public abstract void f(String input);", + " }", + " private final Function camelCase = new Impl() {", + " public void f(String input) {}", + " };", + " void g() {", + " Function f = camelCase;", + " System.err.println(camelCase.apply(\"world\"));", + " }", + "}") + .expectUnchanged() + .doTest(); + } }