From acddd00a367ab0587b0d3ef5651edd4eb82a38ec Mon Sep 17 00:00:00 2001 From: Giovanni Zotta Date: Sat, 18 Feb 2023 21:17:22 +0100 Subject: [PATCH] Refactor `IsLambdaExpressionOrMethodReference` with a delegate --- .../IsLambdaExpressionOrMethodReference.java | 22 +++-- ...LambdaExpressionOrMethodReferenceTest.java | 87 +++++++++++++++++++ 2 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 refaster-support/src/test/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReferenceTest.java diff --git a/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReference.java b/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReference.java index bf11aa74c02..4a7c5f9585e 100644 --- a/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReference.java +++ b/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReference.java @@ -1,29 +1,39 @@ package tech.picnic.errorprone.refaster.matchers; +import static com.google.errorprone.matchers.Matchers.anyOf; +import static com.sun.source.tree.MemberReferenceTree.ReferenceMode.INVOKE; + import com.google.errorprone.VisitorState; import com.google.errorprone.matchers.Matcher; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.LambdaExpressionTree; import com.sun.source.tree.MemberReferenceTree; +import com.sun.source.tree.Tree; /** A matcher of lambda expressions or method references. */ public final class IsLambdaExpressionOrMethodReference implements Matcher { private static final long serialVersionUID = 1L; + private static final Matcher DELEGATE = + anyOf(isLambdaExpression(), isMethodReference()); + /** Instantiates a new {@link IsLambdaExpressionOrMethodReference} instance. */ public IsLambdaExpressionOrMethodReference() {} @Override public boolean matches(ExpressionTree tree, VisitorState state) { - return isLambdaExpression(tree) || isMethodReference(tree); + return DELEGATE.matches(tree, state); } - private static boolean isLambdaExpression(ExpressionTree tree) { - return tree instanceof LambdaExpressionTree; + /** Returns a matcher that matches lambda expressions. */ + public static Matcher isLambdaExpression() { + return (tree, state) -> tree instanceof LambdaExpressionTree; } - private static boolean isMethodReference(ExpressionTree tree) { - return tree instanceof MemberReferenceTree - && ((MemberReferenceTree) tree).getMode() == MemberReferenceTree.ReferenceMode.INVOKE; + /** Returns a matcher that matches method references. */ + public static Matcher isMethodReference() { + return (tree, state) -> + tree instanceof MemberReferenceTree + && ((MemberReferenceTree) tree).getMode().equals(INVOKE); } } diff --git a/refaster-support/src/test/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReferenceTest.java b/refaster-support/src/test/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReferenceTest.java new file mode 100644 index 00000000000..9d9e18097d6 --- /dev/null +++ b/refaster-support/src/test/java/tech/picnic/errorprone/refaster/matchers/IsLambdaExpressionOrMethodReferenceTest.java @@ -0,0 +1,87 @@ +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.Disabled; +import org.junit.jupiter.api.Test; + +final class IsLambdaExpressionOrMethodReferenceTest { + + @Disabled + @Test + void matches() { + CompilationTestHelper.newInstance(MatcherTestChecker.class, getClass()) + .addSourceLines( + "A.java", + "import java.util.function.Function;", + "import java.util.stream.Stream;", + "", + "class A {", + " Integer negative1() {", + " Function parseIntFunction = (String s) -> Integer.parseInt(s);", + " return Stream.of(\"1\").map(parseIntFunction).reduce(0, Integer::sum);", + " }", + "", + " Integer negative2() {", + " Function stringLengthMethodReference = String::length;", + " return Stream.of(\"1\").map(stringLengthMethodReference).reduce(0, Integer::sum);", + " }", + "", + " Double negative3() {", + " Function parseDoubleFunction = new Function() {", + " @Override", + " public Double apply(String s) {", + " return Double.parseDouble(s);", + " }", + " };", + " return Stream.of(\"1\").map(parseDoubleFunction).reduce(0.0, Double::sum);", + " }", + "", + " Long negative4() {", + " class ParseLongFunction implements Function {", + " @Override", + " public Long apply(String s) {", + " return Long.parseLong(s);", + " }", + " }", + " return Stream.of(\"1\").map(new ParseLongFunction()).reduce(0L, Long::sum);", + " }", + "", + " Integer positive1() {", + " // BUG: Diagnostic contains:", + " return Stream.of(1).map(i -> i * 2).reduce(0, Integer::sum);", + " }", + "", + " Long positive2() {", + " // BUG: Diagnostic contains:", + " return Stream.of(1)", + " .map(", + " i -> {", + " return i * 2L;", + " })", + " .reduce(0L, Long::sum);", + " }", + "", + " Double positive3() {", + " // BUG: Diagnostic contains:", + " return Stream.of(\"1\").map(Double::parseDouble).reduce(0.0, Double::sum);", + " }", + "}") + .doTest(); + } + + /** A {@link BugChecker} that simply delegates to {@link IsLambdaExpressionOrMethodReference}. */ + @BugPattern( + summary = "Flags expressions matched by `IsLambdaExpressionOrMethodReference`", + severity = ERROR) + public static final class MatcherTestChecker extends AbstractMatcherTestChecker { + private static final long serialVersionUID = 1L; + + public MatcherTestChecker() { + super(new IsLambdaExpressionOrMethodReference()); + } + } +}