diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java index bd62579397ad..fd8056a9fe12 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java @@ -232,7 +232,7 @@ public class ComparatorCombinatorsInspection extends BaseJavaBatchLocalInspectio PsiParameter[] parameters = lambda.getParameterList().getParameters(); PsiElement body = lambda.getBody(); if (body == null) return; - if (LambdaCanBeMethodReferenceInspection.replaceLambdaWithMethodReference(factory, lambda) == lambda) { + if (LambdaCanBeMethodReferenceInspection.replaceLambdaWithMethodReference(lambda) == lambda) { PsiParameter parameter = parameters[0]; String name = parameter.getName(); SuggestedNameInfo nameCandidate = null; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java index c86d71191de2..17bd630a1528 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java @@ -308,27 +308,18 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp public static void replaceAllLambdasWithMethodReferences(PsiElement root) { Collection lambdas = PsiTreeUtil.findChildrenOfType(root, PsiLambdaExpression.class); if(!lambdas.isEmpty()) { - PsiElementFactory factory = JavaPsiFacade.getElementFactory(root.getProject()); for(PsiLambdaExpression lambda : lambdas) { - replaceLambdaWithMethodReference(factory, lambda); + replaceLambdaWithMethodReference(lambda); } } } - public static PsiExpression replaceLambdaWithMethodReference(PsiElementFactory factory, PsiLambdaExpression lambda) { - PsiType type = lambda.getFunctionalInterfaceType(); - if(type == null) return lambda; - String methodReference = - convertToMethodReference(lambda.getBody(), lambda.getParameterList().getParameters(), type, lambda); - if(methodReference == null) return lambda; - PsiTypeCastExpression replacement = (PsiTypeCastExpression)lambda.replace( - factory.createExpressionFromText("(" + lambda.getFunctionalInterfaceType().getCanonicalText() + ")" + methodReference, lambda)); - if (RedundantCastUtil.isCastRedundant(replacement)) { - final PsiExpression operand = replacement.getOperand(); - LOG.assertTrue(operand != null); - return (PsiExpression)replacement.replace(operand); - } - return replacement; + @NotNull + public static PsiExpression replaceLambdaWithMethodReference(@NotNull PsiLambdaExpression lambda) { + PsiElement body = LambdaUtil.extractSingleExpressionFromBody(lambda.getBody()); + final PsiExpression candidate = new LambdaCanBeMethodReferenceInspection() + .canBeMethodReferenceProblem(body, lambda.getParameterList().getParameters(), lambda.getFunctionalInterfaceType(), lambda); + return tryConvertToMethodReference(lambda, candidate); } private static boolean checkQualifier(PsiElement qualifier) { @@ -599,34 +590,46 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class); if (lambdaExpression == null) return; - PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType(); - if (functionalInterfaceType == null || !functionalInterfaceType.isValid()) return; - final PsiType denotableFunctionalInterfaceType = RefactoringChangeUtil.getTypeByExpression(lambdaExpression); - if (denotableFunctionalInterfaceType == null) return; - - Collection comments = ContainerUtil.map(PsiTreeUtil.findChildrenOfType(lambdaExpression, PsiComment.class), - (comment) -> (PsiComment)comment.copy()); - - final String methodRefText = createMethodReferenceText(element, functionalInterfaceType, - lambdaExpression.getParameterList().getParameters()); - - if (methodRefText != null) { - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - final PsiExpression psiExpression = factory.createExpressionFromText(methodRefText, lambdaExpression); - final SmartTypePointer typePointer = SmartTypePointerManager.getInstance(project).createSmartTypePointer(denotableFunctionalInterfaceType); - PsiElement replace = lambdaExpression.replace(psiExpression); - final PsiType functionalTypeAfterReplacement = GenericsUtil.getVariableTypeByExpressionType(((PsiMethodReferenceExpression)replace).getFunctionalInterfaceType()); - functionalInterfaceType = typePointer.getType(); - if (functionalTypeAfterReplacement == null || functionalInterfaceType != null && !functionalTypeAfterReplacement.equals(functionalInterfaceType)) { //ambiguity - final PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(A)a", replace); - cast.getCastType().replace(factory.createTypeElement(functionalInterfaceType)); - cast.getOperand().replace(replace); - replace = replace.replace(cast); - } - - AnonymousCanBeLambdaInspection.restoreComments(comments, replace); - JavaCodeStyleManager.getInstance(project).shortenClassReferences(replace); - } + tryConvertToMethodReference(lambdaExpression, element); } } + + @NotNull + static PsiExpression tryConvertToMethodReference(@NotNull PsiLambdaExpression lambda, PsiElement body) { + Project project = lambda.getProject(); + PsiType functionalInterfaceType = lambda.getFunctionalInterfaceType(); + if (functionalInterfaceType == null || !functionalInterfaceType.isValid()) return lambda; + final PsiType denotableFunctionalInterfaceType = RefactoringChangeUtil.getTypeByExpression(lambda); + if (denotableFunctionalInterfaceType == null) return lambda; + + Collection comments = ContainerUtil.map(PsiTreeUtil.findChildrenOfType(lambda, PsiComment.class), + (comment) -> (PsiComment)comment.copy()); + + final String methodRefText = createMethodReferenceText(body, functionalInterfaceType, lambda.getParameterList().getParameters()); + + if (methodRefText != null) { + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + final PsiExpression psiExpression = factory.createExpressionFromText(methodRefText, lambda); + final SmartTypePointer typePointer = SmartTypePointerManager.getInstance(project).createSmartTypePointer(denotableFunctionalInterfaceType); + PsiExpression replace = (PsiExpression)lambda.replace(psiExpression); + final PsiType functionalTypeAfterReplacement = GenericsUtil.getVariableTypeByExpressionType(((PsiMethodReferenceExpression)replace).getFunctionalInterfaceType()); + functionalInterfaceType = typePointer.getType(); + if (functionalInterfaceType != null && (functionalTypeAfterReplacement == null || + !functionalTypeAfterReplacement.equals(functionalInterfaceType))) { //ambiguity + final PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(A)a", replace); + PsiTypeElement castType = cast.getCastType(); + LOG.assertTrue(castType != null); + castType.replace(factory.createTypeElement(functionalInterfaceType)); + PsiExpression castOperand = cast.getOperand(); + LOG.assertTrue(castOperand != null); + castOperand.replace(replace); + replace = (PsiExpression)replace.replace(cast); + } + + AnonymousCanBeLambdaInspection.restoreComments(comments, replace); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(replace); + return replace; + } + return lambda; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java index ef974e531b70..710734674046 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java @@ -285,8 +285,7 @@ public class IntroduceParameterDialog extends RefactoringDialog { if (myCbCollapseToLambda.isVisible() && myCbCollapseToLambda.isSelected() && parameterInitializer != null) { PsiExpression lambda = AnonymousCanBeLambdaInspection.replaceAnonymousWithLambda(parameterInitializer, selectedType); if (lambda != null) { - lambda = LambdaCanBeMethodReferenceInspection.replaceLambdaWithMethodReference(JavaPsiFacade.getElementFactory(getProject()), - (PsiLambdaExpression)lambda); + lambda = LambdaCanBeMethodReferenceInspection.replaceLambdaWithMethodReference((PsiLambdaExpression)lambda); processor.setParameterInitializer(lambda); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchExtends.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchExtends.java new file mode 100644 index 000000000000..dc7d98df6e0c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchExtends.java @@ -0,0 +1,10 @@ +// "Replace with anyMatch()" "true" + +import java.util.*; + +public class Main { + public List getList() {return Arrays.asList("a");} + public boolean test() { + return getList().stream().map(CharSequence::toString).anyMatch(s -> !s.isEmpty()); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstField.java index d513498dc463..9d2fedce705b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstField.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstField.java @@ -3,12 +3,11 @@ import java.awt.*; import java.util.List; import java.util.Objects; -import java.util.function.Predicate; public class Main { private Point field = new Point(0, 0); public Point find(List points) { - return points.stream().filter((Predicate) Objects::nonNull).findFirst().orElse(field); + return points.stream().filter(Objects::nonNull).findFirst().orElse(field); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstStaticField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstStaticField.java index 5023572711d0..219566b708f0 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstStaticField.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstStaticField.java @@ -3,12 +3,11 @@ import java.awt.*; import java.util.List; import java.util.Objects; -import java.util.function.Predicate; public class Main { private static Point ZERO = new Point(0, 0); public static Point find(List points) { - return points.stream().filter((Predicate) Objects::nonNull).findFirst().orElse(ZERO); + return points.stream().filter(Objects::nonNull).findFirst().orElse(ZERO); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchExtends.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchExtends.java new file mode 100644 index 000000000000..79edd50a2d68 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchExtends.java @@ -0,0 +1,16 @@ +// "Replace with anyMatch()" "true" + +import java.util.*; + +public class Main { + public List getList() {return Arrays.asList("a");} + public boolean test() { + for(CharSequence cs : getList()) { + String s = cs.toString(); + if(!s.isEmpty()) { + return true; + } + } + return false; + } +}