LambdaCanBeMethodCallInspection: support Pattern.negate() case

IDEA-197892 Explicitly negated Predicate::test can be simplified with Predicate::negate
This commit is contained in:
Tagir Valeev
2018-09-19 16:00:07 +07:00
parent 2e7763c2ea
commit 596a850fa3
7 changed files with 84 additions and 6 deletions

View File

@@ -0,0 +1,11 @@
// "Replace lambda expression with 'Pattern.negate()'" "true"
import java.util.function.Predicate;
public class Main {
void foo(Predicate<? super String> p) {}
void bar(Predicate<? super String> p1) {
foo(p1.negate());
}
}

View File

@@ -0,0 +1,9 @@
// "Replace lambda expression with 'Pattern.negate()'" "true"
import java.util.function.Predicate;
public class Main {
Predicate<? super String> test(Predicate<Object> predicate) {
return predicate.negate();
}
}

View File

@@ -0,0 +1,11 @@
// "Replace lambda expression with 'Pattern.negate()'" "true"
import java.util.function.Predicate;
public class Main {
void foo(Predicate<? super String> p) {}
void bar(Predicate<? super String> p1) {
foo(t -> !<caret>p1.test(t));
}
}

View File

@@ -0,0 +1,9 @@
// "Replace lambda expression with 'Pattern.negate()'" "true"
import java.util.function.Predicate;
public class Main {
Predicate<? super String> test(Predicate<Object> predicate) {
return p -> !<caret>predicate.test(p);
}
}

View File

@@ -0,0 +1,9 @@
// "Replace lambda expression with 'Pattern.negate()'" "false"
import java.util.function.Predicate;
public class Main {
Predicate<Predicate<Object>> test() {
return p -> !<caret>p.test(p);
}
}

View File

@@ -0,0 +1,9 @@
// "Replace lambda expression with 'Pattern.negate()'" "false"
import java.util.function.Predicate;
public class Main {
Predicate<String> test(Predicate<Object> predicate) {
return p -> !<caret>predicate.test(p);
}
}

View File

@@ -6,15 +6,18 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiPrecedenceUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.intellij.util.ObjectUtils;
import com.siyeh.ig.callMatcher.CallMatcher;
import com.siyeh.ig.psiutils.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class LambdaCanBeMethodCallInspection extends AbstractBaseJavaLocalInspectionTool {
private static final CallMatcher PREDICATE_TEST = CallMatcher.instanceCall(
CommonClassNames.JAVA_UTIL_FUNCTION_PREDICATE, "test").parameterTypes("T");
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
@@ -38,7 +41,7 @@ public class LambdaCanBeMethodCallInspection extends AbstractBaseJavaLocalInspec
if (parameters.length == 1) {
PsiParameter parameter = parameters[0];
if (ExpressionUtils.isReferenceTo(expression, parameter)) {
processFunctionIdentity(lambda, (PsiClassType)type);
handleFunctionIdentity(lambda, (PsiClassType)type);
}
if (expression instanceof PsiMethodCallExpression) {
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
@@ -48,10 +51,27 @@ public class LambdaCanBeMethodCallInspection extends AbstractBaseJavaLocalInspec
handlePatternAsPredicate(lambda, parameter, call);
}
}
handlePatternNegate(lambda, parameter, expression);
}
}
private void processFunctionIdentity(PsiLambdaExpression lambda, PsiClassType type) {
private void handlePatternNegate(PsiLambdaExpression lambda, PsiParameter parameter, PsiExpression expression) {
if (!BoolUtils.isNegation(expression)) return;
PsiMethodCallExpression negated = ObjectUtils.tryCast(BoolUtils.getNegated(expression), PsiMethodCallExpression.class);
if (!PREDICATE_TEST.test(negated)) return;
if (!ExpressionUtils.isReferenceTo(negated.getArgumentList().getExpressions()[0], parameter)) return;
PsiExpression qualifier = negated.getMethodExpression().getQualifierExpression();
if (!ExpressionUtils.isSafelyRecomputableExpression(qualifier) || ExpressionUtils.isReferenceTo(qualifier, parameter)) return;
PsiType lambdaType = ExpectedTypeUtils.findExpectedType(lambda, false);
if (lambdaType == null || qualifier.getType() == null || !lambdaType.isAssignableFrom(qualifier.getType())) return;
registerProblem(lambda, "Pattern.negate()",
ParenthesesUtils.getText(qualifier, PsiPrecedenceUtil.METHOD_CALL_PRECEDENCE) + ".negate()");
}
private void handleFunctionIdentity(PsiLambdaExpression lambda, PsiClassType type) {
PsiClass aClass = type.resolve();
if (aClass == null || !CommonClassNames.JAVA_UTIL_FUNCTION_FUNCTION.equals(aClass.getQualifiedName())) return;
PsiType[] typeParameters = type.getParameters();