mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 05:10:22 +07:00
anonym to lambda: rename conflicting locals (IDEA-120221)
This commit is contained in:
@@ -38,10 +38,7 @@ import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -93,11 +90,6 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
final ForbiddenRefsChecker checker = new ForbiddenRefsChecker(methods[0], aClass);
|
||||
body.accept(checker);
|
||||
if (!checker.hasForbiddenRefs()) {
|
||||
PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(body.getProject());
|
||||
for (PsiLocalVariable local : checker.getLocals()) {
|
||||
final String localName = local.getName();
|
||||
if (localName != null && helper.resolveReferencedVariable(localName, aClass) != null) return;
|
||||
}
|
||||
final PsiElement lBrace = aClass.getLBrace();
|
||||
LOG.assertTrue(lBrace != null);
|
||||
final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent());
|
||||
@@ -131,6 +123,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (element instanceof PsiNewExpression) {
|
||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
|
||||
|
||||
LOG.assertTrue(anonymousClass != null);
|
||||
ChangeContextUtil.encodeContextInfo(anonymousClass, true);
|
||||
final PsiElement lambdaContext = anonymousClass.getParent().getParent();
|
||||
@@ -139,14 +132,32 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
final PsiMethod method = anonymousClass.getMethods()[0];
|
||||
LOG.assertTrue(method != null);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
LOG.assertTrue(body != null);
|
||||
|
||||
final ForbiddenRefsChecker checker = new ForbiddenRefsChecker(method, anonymousClass);
|
||||
body.accept(checker);
|
||||
|
||||
PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(body.getProject());
|
||||
final Set<PsiLocalVariable> conflictingLocals = checker.getLocals();
|
||||
for (Iterator<PsiLocalVariable> iterator = conflictingLocals.iterator(); iterator.hasNext(); ) {
|
||||
PsiLocalVariable local = iterator.next();
|
||||
final String localName = local.getName();
|
||||
if (localName == null || helper.resolveReferencedVariable(localName, anonymousClass) == null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
giveUniqueNames(project, lambdaContext, elementFactory, body, conflictingLocals.toArray(new PsiVariable[conflictingLocals.size()]));
|
||||
|
||||
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);
|
||||
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
LOG.assertTrue(body != null);
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
PsiElement copy = body.copy();
|
||||
if (statements.length == 1 && statements[0] instanceof PsiReturnStatement) {
|
||||
@@ -160,42 +171,7 @@ 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));
|
||||
}
|
||||
giveUniqueNames(project, lambdaContext, elementFactory, lambdaExpression, lambdaExpression.getParameterList().getParameters());
|
||||
|
||||
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
|
||||
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
|
||||
@@ -243,6 +219,49 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
}
|
||||
}
|
||||
|
||||
private static void giveUniqueNames(Project project,
|
||||
PsiElement lambdaContext,
|
||||
final PsiElementFactory elementFactory,
|
||||
PsiElement body,
|
||||
PsiVariable[] parameters) {
|
||||
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
|
||||
final Map<PsiVariable, String> names = new HashMap<PsiVariable, String>();
|
||||
for (PsiVariable parameter : parameters) {
|
||||
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>();
|
||||
body.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitVariable(PsiVariable variable) {
|
||||
final String newName = names.get(variable);
|
||||
if (newName != null) {
|
||||
replacements.put(variable.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));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInferred(PsiLambdaExpression lambdaExpression, PsiType interfaceType) {
|
||||
return interfaceType == null || !LambdaUtil.isLambdaFullyInferred(lambdaExpression, interfaceType) || !LambdaUtil.isFunctionalType(interfaceType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Replace with lambda" "true"
|
||||
class X1 {
|
||||
Runnable m() {
|
||||
String s;
|
||||
return () -> {
|
||||
String s1;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with lambda" "true"
|
||||
class X1 {
|
||||
Runnable m() {
|
||||
String s;
|
||||
return new Run<caret>nable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String s;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user