From 99ce4b4f46190ce9e4e6c49d988f230a393f35ed Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Mon, 23 May 2016 12:53:19 +0200 Subject: [PATCH] redundant lambda code block: check applicability over replaced lambda --- .../AnonymousCanBeLambdaInspection.java | 4 +- .../RedundantLambdaCodeBlockInspection.java | 42 ++++++------------- .../util/LambdaRefactoringUtil.java | 3 +- .../afterCollapseToExprLambda.java | 23 ++++++++++ .../beforeCollapseToExprLambda.java | 28 +++++++++++++ 5 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCollapseToExprLambda.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeCollapseToExprLambda.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index 4b9ec4c1a6df..743e5d2bd7de 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -284,8 +284,8 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection .giveUniqueNames(project, elementFactory, lambdaExpression, usedLocalNames, variables.toArray(new PsiVariable[variables.size()])); - final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression, - lambdaExpression.getBody()); + final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant( + lambdaExpression.getBody()); if (singleExpr != null) { lambdaExpression.getBody().replace(singleExpr); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/RedundantLambdaCodeBlockInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/RedundantLambdaCodeBlockInspection.java index f253ac0f3e14..a05dd88c4700 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/RedundantLambdaCodeBlockInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/RedundantLambdaCodeBlockInspection.java @@ -20,20 +20,13 @@ import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.intention.HighPriorityAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; -import com.intellij.psi.infos.CandidateInfo; -import com.intellij.psi.infos.MethodCandidateInfo; -import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.List; /** * User: anna @@ -75,7 +68,7 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaBatchLocalInspec super.visitLambdaExpression(expression); if (PsiUtil.isLanguageLevel8OrHigher(expression)) { final PsiElement body = expression.getBody(); - final PsiExpression psiExpression = isCodeBlockRedundant(expression, body); + final PsiExpression psiExpression = isCodeBlockRedundant(body); if (psiExpression != null) { final PsiElement errorElement; final PsiElement parent = psiExpression.getParent(); @@ -92,31 +85,22 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaBatchLocalInspec }; } - public static PsiExpression isCodeBlockRedundant(PsiExpression expression, PsiElement body) { + public static PsiExpression isCodeBlockRedundant(PsiElement body) { if (body instanceof PsiCodeBlock) { PsiExpression psiExpression = LambdaUtil.extractSingleExpressionFromBody(body); if (psiExpression != null && !findCommentsOutsideExpression(body, psiExpression)) { if (LambdaUtil.isExpressionStatementExpression(psiExpression)) { - final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent()); - if (parent instanceof PsiExpressionList) { - final PsiElement gParent = parent.getParent(); - if (gParent instanceof PsiCallExpression) { - final CandidateInfo[] candidates = PsiResolveHelper.SERVICE.getInstance(gParent.getProject()) - .getReferencedMethodCandidates((PsiCallExpression)gParent, false, true); - if (candidates.length > 1) { - final List info = new ArrayList(Arrays.asList(candidates)); - final LanguageLevel level = PsiUtil.getLanguageLevel(parent); - final JavaMethodsConflictResolver conflictResolver = new JavaMethodsConflictResolver((PsiExpressionList)parent, level); - final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList(); - if (argumentList == null) { - return null; - } - final boolean atLeastOneMatchFound = conflictResolver.checkParametersNumber(info, argumentList.getExpressions().length, false); - if (!atLeastOneMatchFound) { - return null; - } - conflictResolver.checkSpecifics(info, MethodCandidateInfo.ApplicabilityLevel.VARARGS, level); - if (info.size() > 1) { + final PsiCall call = LambdaUtil.treeWalkUp(body); + if (call != null && call.resolveMethod() != null) { + final int offsetInTopCall = body.getTextRange().getStartOffset() - call.getTextRange().getStartOffset(); + PsiCall copyCall = LambdaUtil.copyTopLevelCall(call); + if (copyCall == null) return null; + final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(copyCall.findElementAt(offsetInTopCall), PsiCodeBlock.class); + if (codeBlock != null) { + final PsiElement parent = codeBlock.getParent(); + if (parent instanceof PsiLambdaExpression) { + codeBlock.replace(psiExpression); + if (copyCall.resolveMethod() == null || ((PsiLambdaExpression)parent).getFunctionalInterfaceType() == null) { return null; } } diff --git a/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java index 8a208c42023a..b2e4427d9c49 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java @@ -31,7 +31,6 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.RedundantCastUtil; import com.intellij.refactoring.introduceField.ElementToWorkOn; import com.intellij.refactoring.introduceVariable.IntroduceVariableHandler; -import com.intellij.util.Function; import com.intellij.util.text.UniqueNameGenerator; import com.siyeh.ig.psiutils.SideEffectChecker; import org.jetbrains.annotations.NotNull; @@ -230,7 +229,7 @@ public class LambdaRefactoringUtil { public static void simplifyToExpressionLambda(@NotNull final PsiLambdaExpression lambdaExpression) { final PsiElement body = lambdaExpression.getBody(); - final PsiExpression singleExpression = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression, body); + final PsiExpression singleExpression = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(body); if (singleExpression != null) { body.replace(singleExpression); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCollapseToExprLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCollapseToExprLambda.java new file mode 100644 index 000000000000..52d0fceb2979 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCollapseToExprLambda.java @@ -0,0 +1,23 @@ +// "Replace with lambda" "true" +import java.util.Collection; +import java.util.function.Function; + +class Test { + + public static V[] map2Array( T[] array, Class aClass, Function mapper) { + return null; + } + public static V[] map2Array(Collection array, Class aClass, Function mapper) { + return null; + } + + void m(String[] f, int i, FooBar manager){ + + map2Array(f, Integer.class, (NullableFunction) s -> s.length()); + } + + interface NullableFunction extends Function { + + B apply(final A param); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeCollapseToExprLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeCollapseToExprLambda.java new file mode 100644 index 000000000000..f3a759154a83 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeCollapseToExprLambda.java @@ -0,0 +1,28 @@ +// "Replace with lambda" "true" +import java.util.Collection; +import java.util.function.Function; + +class Test { + + public static V[] map2Array( T[] array, Class aClass, Function mapper) { + return null; + } + public static V[] map2Array(Collection array, Class aClass, Function mapper) { + return null; + } + + void m(String[] f, int i, FooBar manager){ + + map2Array(f, Integer.class, new NullableFunction() { + @Override + public Integer apply(String s) { + return s.length(); + } + }); + } + + interface NullableFunction extends Function { + + B apply(final A param); + } +} \ No newline at end of file