resolve names conflicts inside lambda body (IDEA-120096)

This commit is contained in:
Anna Kozlova
2014-01-30 19:49:44 +04:00
parent 876784bc24
commit e0fbc6320e
5 changed files with 94 additions and 12 deletions

View File

@@ -17,10 +17,10 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -29,9 +29,12 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
@@ -180,8 +183,8 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
final PsiMethod method = anonymousClass.getMethods()[0];
LOG.assertTrue(method != null);
final String lambdaWithTypesDeclared = composeLambdaText(method, lambdaContext, true);
final String withoutTypesDeclared = composeLambdaText(method, lambdaContext, false);
final String lambdaWithTypesDeclared = composeLambdaText(method, true);
final String withoutTypesDeclared = composeLambdaText(method, false);
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiLambdaExpression lambdaExpression =
(PsiLambdaExpression)elementFactory.createExpressionFromText(withoutTypesDeclared, anonymousClass);
@@ -201,6 +204,43 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
LOG.assertTrue(lambdaBody != null);
lambdaBody.replace(copy);
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final Map<PsiParameter, String> names = new HashMap<PsiParameter, String>();
for (PsiParameter parameter : lambdaExpression.getParameterList().getParameters()) {
String parameterName = parameter.getName();
final String uniqueVariableName = codeStyleManager.suggestUniqueVariableName(parameterName, lambdaContext, false);
if (!Comparing.equal(parameterName, uniqueVariableName)) {
names.put(parameter, uniqueVariableName);
}
}
final LinkedHashMap<PsiElement, PsiElement> replacements = new LinkedHashMap<PsiElement, PsiElement>();
lambdaExpression.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitParameter(PsiParameter parameter) {
final String newName = names.get(parameter);
if (newName != null) {
replacements.put(parameter.getNameIdentifier(), elementFactory.createIdentifier(newName));
}
}
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement resolve = expression.resolve();
if (resolve instanceof PsiParameter) {
final String newName = names.get(resolve);
if (newName != null) {
replacements.put(expression, elementFactory.createExpressionFromText(newName, expression));
}
}
}
});
for (PsiElement psiElement : replacements.keySet()) {
psiElement.replace(replacements.get(psiElement));
}
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
ChangeContextUtil.decodeContextInfo(lambdaExpression, null, null);
@@ -253,18 +293,17 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
interfaceType) != null;
}
private static String composeLambdaText(PsiMethod method, final PsiElement lambdaContext, final boolean appendType) {
private static String composeLambdaText(PsiMethod method, final boolean appendType) {
final StringBuilder buf = new StringBuilder();
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 1 || appendType) {
buf.append("(");
}
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(lambdaContext.getProject());
buf.append(StringUtil.join(parameters,
new Function<PsiParameter, String>() {
@Override
public String fun(PsiParameter parameter) {
return composeParameter(parameter, appendType, codeStyleManager, lambdaContext);
return composeParameter(parameter, appendType);
}
}, ","));
if (parameters.length != 1 || appendType) {
@@ -275,9 +314,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
}
private static String composeParameter(PsiParameter parameter,
boolean appendType,
JavaCodeStyleManager codeStyleManager,
PsiElement lambdaContext) {
boolean appendType) {
final String parameterType;
if (appendType) {
final PsiTypeElement typeElement = parameter.getTypeElement();
@@ -290,7 +327,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
if (parameterName == null) {
parameterName = "";
}
return parameterType + codeStyleManager.suggestUniqueVariableName(parameterName, lambdaContext, true);
return parameterType + parameterName;
}
}
}

View File

@@ -2,6 +2,6 @@
class Test {
{
String o = "";
Comparable<String> c = o1 -> 0;
Comparable<String> c = o1 -> o1.length();
}
}

View File

@@ -0,0 +1,21 @@
// "Replace with lambda" "true"
public class MyNameConflict {
{
int x = 0;
Comparable<E> c = x1 -> {
switch (x1) {
case EE:
break;
}
return x1.hashCode();
};
}
static enum E {
EE;
}
}

View File

@@ -5,7 +5,7 @@ class Test {
Comparable<String> c = new Compa<caret>rable<String>() {
@Override
public int compareTo(String o) {
return 0;
return o.length();
}
};
}

View File

@@ -0,0 +1,24 @@
// "Replace with lambda" "true"
public class MyNameConflict {
{
int x = 0;
Comparable<E> c = new Compara<caret>ble<E>() {
@Override
public int compareTo(E x) {
switch (x) {
case EE:
break;
}
return x.hashCode();
}
};
}
static enum E {
EE;
}
}