ensure functional type for formal parameters lambda is valid after method reference replacement (IDEA-135053)

This commit is contained in:
Anna Kozlova
2015-01-08 19:47:01 +01:00
parent 3d9f911dc3
commit fcb252d25e
3 changed files with 41 additions and 6 deletions

View File

@@ -420,21 +420,24 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
if (lambdaExpression == null) return;
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
if (functionalInterfaceType == null || !functionalInterfaceType.isValid()) return;
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 PsiExpression psiExpression = factory.createExpressionFromText(methodRefText, lambdaExpression);
final SmartTypePointer typePointer = SmartTypePointerManager.getInstance(project).createSmartTypePointer(functionalInterfaceType);
PsiElement replace = lambdaExpression.replace(psiExpression);
if (((PsiMethodReferenceExpression)replace).getFunctionalInterfaceType() == null) { //ambiguity
final PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(A)a", replace);
cast.getCastType().replace(factory.createTypeElement(functionalInterfaceType));
cast.getOperand().replace(replace);
replace = replace.replace(cast);
functionalInterfaceType = typePointer.getType();
if (functionalInterfaceType != null) {
cast.getCastType().replace(factory.createTypeElement(functionalInterfaceType));
cast.getOperand().replace(replace);
replace = replace.replace(cast);
}
}
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replace);
}

View File

@@ -0,0 +1,16 @@
// "Replace lambda with method reference" "true"
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
class Test {
public Test(String s) {}
public static void define(Supplier<?> moduleConstructor){}
public static void define(Function<?, ?> moduleConstructor){}
public static void define(BiFunction<?, ?, ?> moduleConstructor){}
{
define((Function<String, Object>) Test::new);
}
}

View File

@@ -0,0 +1,16 @@
// "Replace lambda with method reference" "true"
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
class Test {
public Test(String s) {}
public static void define(Supplier<?> moduleConstructor){}
public static void define(Function<?, ?> moduleConstructor){}
public static void define(BiFunction<?, ?, ?> moduleConstructor){}
{
define((String s) -> new Test<caret>(s));
}
}