mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Compare commits
1 Commits
v0.19.1
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1ca5b2505 |
@@ -0,0 +1,42 @@
|
||||
package tech.picnic.errorprone.refaster.matchers;
|
||||
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.kindIs;
|
||||
import static com.google.errorprone.matchers.Matchers.parentNode;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.LambdaExpressionTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
/**
|
||||
* A matcher of expressions of which the result (if any) is unused, for use with Refaster's
|
||||
* {@code @Matches} annotation.
|
||||
*/
|
||||
// XXX: Review whether other parts of Error Prone's `AbstractReturnValueIgnored` should be ported to
|
||||
// this class.
|
||||
public final class ReturnValueUnused implements Matcher<ExpressionTree> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> DELEGATE =
|
||||
parentNode(
|
||||
anyOf(
|
||||
ReturnValueUnused::isVoidReturningLambdaExpression,
|
||||
kindIs(Tree.Kind.EXPRESSION_STATEMENT)));
|
||||
|
||||
/** Instantiates a new {@link ReturnValueUnused} instance. */
|
||||
public ReturnValueUnused() {}
|
||||
|
||||
@Override
|
||||
public boolean matches(ExpressionTree tree, VisitorState state) {
|
||||
return DELEGATE.matches(tree, state);
|
||||
}
|
||||
|
||||
private static boolean isVoidReturningLambdaExpression(Tree tree, VisitorState state) {
|
||||
return tree instanceof LambdaExpressionTree
|
||||
&& state.getTypes().findDescriptorType(ASTHelpers.getType(tree)).getReturnType().getKind()
|
||||
== TypeKind.VOID;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ abstract class AbstractMatcherTestChecker extends BugChecker implements Compilat
|
||||
TreePath path = new TreePath(getCurrentPath(), tree);
|
||||
ExpressionTree expressionTree = (ExpressionTree) tree;
|
||||
if (!isMethodSelect(expressionTree, path)
|
||||
&& state.getSourceForNode(expressionTree) != null
|
||||
&& delegate.matches(expressionTree, state.withPath(path))) {
|
||||
state.reportMatch(describeMatch(tree));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package tech.picnic.errorprone.refaster.matchers;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ReturnValueUnusedTest {
|
||||
@Test
|
||||
void matches() {
|
||||
CompilationTestHelper.newInstance(MatcherTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.function.Consumer;",
|
||||
"",
|
||||
"class A {",
|
||||
" String negative1() {",
|
||||
" return toString();",
|
||||
" }",
|
||||
"",
|
||||
" void negative2() {",
|
||||
" String s = toString();",
|
||||
" }",
|
||||
"",
|
||||
" String negative3() {",
|
||||
" return toString().toString();",
|
||||
" }",
|
||||
"",
|
||||
// XXX: The `valueOf` result is ignored, but `String::valueOf` itself isn't. Review.
|
||||
" Object negative4() {",
|
||||
" return sink(String::valueOf);",
|
||||
" }",
|
||||
"",
|
||||
" void positive1() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" toString();",
|
||||
" }",
|
||||
"",
|
||||
" void positive2() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" toString().toString();",
|
||||
" }",
|
||||
"",
|
||||
" void positive3() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new Object();",
|
||||
" }",
|
||||
"",
|
||||
" Object positive4() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" return sink(v -> toString());",
|
||||
" }",
|
||||
"",
|
||||
" Object positive5() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" return sink(v -> new Object());",
|
||||
" }",
|
||||
"",
|
||||
" private <T, S> S sink(Consumer<T> consumer) {",
|
||||
" return null;",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
/** A {@link BugChecker} that simply delegates to {@link ReturnValueUnused}. */
|
||||
@BugPattern(summary = "Flags expressions matched by `ReturnValueUnused`", severity = ERROR)
|
||||
@SuppressWarnings({"RedundantModifier", "serial"})
|
||||
public static final class MatcherTestChecker extends AbstractMatcherTestChecker {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// XXX: This is a false positive reported by Checkstyle. See
|
||||
// https://github.com/checkstyle/checkstyle/issues/10161#issuecomment-1242732120.
|
||||
@SuppressWarnings("RedundantModifier")
|
||||
public MatcherTestChecker() {
|
||||
super(new ReturnValueUnused());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user