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 1f21acb4a204..e11a45600ed3 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/LambdaRefactoringUtil.java @@ -20,14 +20,12 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; -import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; -import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; -import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; @@ -87,7 +85,7 @@ public class LambdaRefactoringUtil { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(referenceExpression.getProject()); PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)elementFactory.createExpressionFromText(lambda, referenceExpression); final PsiType functionalInterfaceType = referenceExpression.getFunctionalInterfaceType(); - boolean needToSpecifyFormalTypes = !doNotAddParameterTypes && !isInferredSameTypeAfterConversion(lambdaExpression, referenceExpression, functionalInterfaceType); + boolean needToSpecifyFormalTypes = !doNotAddParameterTypes && !isInferredSameTypeAfterConversion(lambdaExpression, referenceExpression); if (needToSpecifyFormalTypes) { PsiParameterList typedParamList = specifyLambdaParameterTypes(functionalInterfaceType, lambdaExpression); if (typedParamList == null) { @@ -281,30 +279,20 @@ public class LambdaRefactoringUtil { } private static boolean isInferredSameTypeAfterConversion(PsiLambdaExpression lambdaExpression, - PsiMethodReferenceExpression methodReferenceExpression, - PsiType functionalInterfaceType) { - PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodReferenceExpression.getParent()); - if (!(parent instanceof PsiExpressionList)) { + PsiMethodReferenceExpression methodReferenceExpression) { + PsiCall call = LambdaUtil.treeWalkUp(methodReferenceExpression); + if (call == null) { return true; } - PsiElement gParent = parent.getParent(); - if (gParent instanceof PsiCall) { - if (gParent instanceof PsiCallExpression && ((PsiCallExpression)gParent).getTypeArguments().length > 0) { - return true; - } - JavaResolveResult result = ((PsiCall)gParent).resolveMethodGenerics(); - if (result instanceof MethodCandidateInfo) { - PsiMethod method = ((MethodCandidateInfo)result).getElement(); - if (!method.hasTypeParameters()) { - return true; - } - PsiExpression[] args = ((PsiExpressionList)parent).getExpressions(); - int lambdaIdx = LambdaUtil.getLambdaIdx((PsiExpressionList)parent, methodReferenceExpression); - args[lambdaIdx] = lambdaExpression; - final PsiParameter[] methodParams = method.getParameterList().getParameters(); - final PsiSubstitutor substitutor = ((MethodCandidateInfo)result).inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, args, true); - PsiType formalTargetType = substitutor.substitute(PsiTypesUtil.getParameterType(methodParams, lambdaIdx, ((MethodCandidateInfo)result).isVarargs())); - return functionalInterfaceType.equals(FunctionalInterfaceParameterizationUtil.getGroundTargetType(formalTargetType)); + Object marker = new Object(); + PsiTreeUtil.mark(methodReferenceExpression, marker); + PsiCall copyTopLevelCall = LambdaUtil.copyTopLevelCall(call); + if (copyTopLevelCall != null) { + PsiMethodReferenceExpression methodReferenceInCopy = (PsiMethodReferenceExpression)PsiTreeUtil.releaseMark(copyTopLevelCall, marker); + if (methodReferenceInCopy != null) { + PsiType functionalInterfaceType = methodReferenceInCopy.getFunctionalInterfaceType(); + PsiLambdaExpression lambdaCopy = (PsiLambdaExpression)methodReferenceInCopy.replace(lambdaExpression); + return Comparing.equal(functionalInterfaceType, lambdaCopy.getFunctionalInterfaceType()); } } return false; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/methodRefs2lambda/ExplicitTypeRequired.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/methodRefs2lambda/ExplicitTypeRequired.after.java new file mode 100644 index 000000000000..421f483bf1cd --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/methodRefs2lambda/ExplicitTypeRequired.after.java @@ -0,0 +1,11 @@ +import java.util.Comparator; +class MyTest { + void setComparator(Comparator comparator) {} + String getValue() { + return ""; + } + + { + setComparator(Comparator.comparing((MyTest myTest) -> myTest.getValue())); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/methodRefs2lambda/ExplicitTypeRequired.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/methodRefs2lambda/ExplicitTypeRequired.java new file mode 100644 index 000000000000..0758b5c1bfd4 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/methodRefs2lambda/ExplicitTypeRequired.java @@ -0,0 +1,11 @@ +import java.util.Comparator; +class MyTest { + void setComparator(Comparator comparator) {} + String getValue() { + return ""; + } + + { + setComparator(Comparator.comparing(MyTest::getValue)); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/MethodRefCanBeReplacedWithLambdaFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/MethodRefCanBeReplacedWithLambdaFixTest.java index 2d0bcba84147..3466af99c0e4 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/MethodRefCanBeReplacedWithLambdaFixTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/MethodRefCanBeReplacedWithLambdaFixTest.java @@ -143,9 +143,8 @@ public class MethodRefCanBeReplacedWithLambdaFixTest extends IGQuickFixesTestCas doTest(); } - public void testNewArrayMethodReferenceHasNoSideEffects() { - doTest(); - } + public void testNewArrayMethodReferenceHasNoSideEffects() { doTest(); } + public void testExplicitTypeRequired() { doTest(); } public void testEnsureNoConversionIsSuggestedWhenLambdaWithoutCantBeInferredAndFormalParametersAreNotDenotable() { assertQuickfixNotAvailable();