diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormals.java b/core/src/main/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormals.java index c75d3fb84c7..9149004fc71 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormals.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormals.java @@ -39,6 +39,7 @@ import com.sun.tools.javac.code.Types; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.TreeScanner; @@ -110,6 +111,12 @@ public Description matchMethod(MethodTree tree, VisitorState state) { } } + // Ignore cases where the type is never used in the method body. Methods that claim to return + // 'any' type are OK if they only return null, or always throw. + if (!CastFinder.find(tree.getBody(), retType)) { + return Description.NO_MATCH; + } + return attemptFix(retType, tree, state); } @@ -261,4 +268,26 @@ public Void visitType(Type type, Void unused) { return null; } } + + private static class CastFinder extends TreeScanner { + + static boolean find(Tree tree, Type retType) { + CastFinder finder = new CastFinder(retType); + ((JCTree) tree).accept(finder); + return finder.found; + } + + Type retType; + boolean found = false; + + private CastFinder(Type retType) { + this.retType = retType; + } + + @Override + public void visitTypeCast(JCTypeCast tree) { + found |= retType.tsym.equals(ASTHelpers.getSymbol(tree.clazz)); + scan(tree.expr); + } + } } diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormalsTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormalsTest.java index 5d400d2ceb7..4fcc8d42f0a 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormalsTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/TypeParameterUnusedInFormalsTest.java @@ -23,7 +23,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - @RunWith(JUnit4.class) public class TypeParameterUnusedInFormalsTest { @@ -157,4 +156,35 @@ public void okNotMyParam() throws Exception { "}") ); } + + @Test + public void okAlwaysThrows() throws Exception { + compilationHelper.assertCompileSucceeds( + compilationHelper.fileManager().forSourceLines("Test.java", + "class Test {", + " T logAndThrow() { throw new RuntimeException(); }", + "}") + ); + } + + @Test + public void okAlwaysReturnsNull() throws Exception { + compilationHelper.assertCompileSucceeds( + compilationHelper.fileManager().forSourceLines("Test.java", + "class Test {", + " T nullFactory() { return null; }", + "}") + ); + } + + @Test + public void badCast() throws Exception { + compilationHelper.assertCompileSucceedsWithMessages( + compilationHelper.fileManager().forSourceLines("Test.java", + "class Test {", + " // BUG: Diagnostic contains:", + " T nullFactory() { return (T) null; }", + "}") + ); + } }