mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
method ref -> lambda: check functional interface type after replacement
IDEA-184178
This commit is contained in:
@@ -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;
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.util.Comparator;
|
||||
class MyTest {
|
||||
void setComparator(Comparator<?> comparator) {}
|
||||
String getValue() {
|
||||
return "";
|
||||
}
|
||||
|
||||
{
|
||||
setComparator(Comparator.comparing((MyTest myTest) -> myTest.getValue()));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.util.Comparator;
|
||||
class MyTest {
|
||||
void setComparator(Comparator<?> comparator) {}
|
||||
String getValue() {
|
||||
return "";
|
||||
}
|
||||
|
||||
{
|
||||
setComparator(Comparator.comparing(MyTest::<caret>getValue));
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user