lambda: convert anonymous to lambda in invalid context with cast; add cast when functional interface type won't be found otherwise (IDEA-90863)

This commit is contained in:
Anna Kozlova
2012-09-03 17:39:49 +04:00
parent 04d0779cfb
commit d71e11473a
5 changed files with 60 additions and 5 deletions

View File

@@ -26,6 +26,7 @@ import com.intellij.psi.*;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.RedundantCastUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -68,7 +69,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaLocalInspectionTool
@Override
public void visitAnonymousClass(PsiAnonymousClass aClass) {
super.visitAnonymousClass(aClass);
if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)&& LambdaUtil.isValidLambdaContext(aClass.getParent().getParent())) {
if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) {
final PsiClassType baseClassType = aClass.getBaseClassType();
final String functionalInterfaceErrorMessage = LambdaUtil.checkInterfaceFunctional(baseClassType);
if (functionalInterfaceErrorMessage == null) {
@@ -103,21 +104,38 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaLocalInspectionTool
final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(element, PsiAnonymousClass.class);
LOG.assertTrue(anonymousClass != null);
boolean validContext = LambdaUtil.isValidLambdaContext(anonymousClass.getParent().getParent());
final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText();
final PsiMethod method = anonymousClass.getMethods()[0];
LOG.assertTrue(method != null);
final String lambdaWithTypesDeclared = composeLambdaText(method, true);
final String withoutTypesDeclared = composeLambdaText(method, false);
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiLambdaExpression lambdaExpression =
(PsiLambdaExpression)JavaPsiFacade.getElementFactory(project).createExpressionFromText(composeLambdaText(method, false), anonymousClass);
(PsiLambdaExpression)elementFactory.createExpressionFromText(withoutTypesDeclared, anonymousClass);
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
if (!validContext) {
lambdaExpression.replace(elementFactory.createExpressionFromText("((" + canonicalText + ")" + withoutTypesDeclared + ")", lambdaExpression));
return;
}
PsiType interfaceType = lambdaExpression.getFunctionalInterfaceType();
if (interfaceType == null || !LambdaUtil.isLambdaFullyInferred(lambdaExpression, interfaceType)) {
lambdaExpression.replace(JavaPsiFacade.getElementFactory(project).createExpressionFromText(lambdaWithTypesDeclared, lambdaExpression));
if (isInferenced(lambdaExpression, interfaceType)) {
lambdaExpression = (PsiLambdaExpression)lambdaExpression.replace(elementFactory.createExpressionFromText(lambdaWithTypesDeclared, lambdaExpression));
interfaceType = lambdaExpression.getFunctionalInterfaceType();
if (isInferenced(lambdaExpression, interfaceType)) {
lambdaExpression.replace(elementFactory.createExpressionFromText("(" + canonicalText + ")" + withoutTypesDeclared, lambdaExpression));
}
}
}
}
private static boolean isInferenced(PsiLambdaExpression lambdaExpression, PsiType interfaceType) {
return interfaceType == null || !LambdaUtil.isLambdaFullyInferred(lambdaExpression, interfaceType) || LambdaUtil.checkInterfaceFunctional(interfaceType) != null;
}
private static String composeLambdaText(PsiMethod method, final boolean appendType) {
final StringBuilder buf = new StringBuilder();
if (appendType) {

View File

@@ -0,0 +1,8 @@
// "Replace with lambda" "true"
class Test {
{
((Runnable) () -> {
//To change body of implemented methods use File | Settings | File Templates.
}).getClass();;
}
}

View File

@@ -0,0 +1,12 @@
// "Replace with lambda" "true"
class Test {
interface I {
}
interface Bar extends I {
int compare(String o1, String o2);
}
{
I bar2 = (Bar) (o1, o2) -> 0;
}
}

View File

@@ -1,4 +1,4 @@
// "Replace with lambda" "false"
// "Replace with lambda" "true"
class Test {
{
new Ru<caret>nnable() {

View File

@@ -0,0 +1,17 @@
// "Replace with lambda" "true"
class Test {
interface I {
}
interface Bar extends I {
int compare(String o1, String o2);
}
{
I bar2 = new Ba<caret>r() {
@Override
public int compare(String o1, String o2) {
return 0;
}
};
}
}