mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 05:21:29 +07:00
anonymous -> lambda: deep unique names (IDEA-154751)
This commit is contained in:
@@ -25,7 +25,6 @@ import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -37,10 +36,9 @@ import com.intellij.psi.controlFlow.ControlFlowUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import com.intellij.util.text.UniqueNameGenerator;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -239,12 +237,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
|
||||
final PsiMethod method;
|
||||
if (ignoreEqualsMethod) {
|
||||
final List<PsiMethod> methods = ContainerUtil.filter(anonymousClass.getMethods(), new Condition<PsiMethod>() {
|
||||
@Override
|
||||
public boolean value(PsiMethod method) {
|
||||
return !"equals".equals(method.getName());
|
||||
}
|
||||
});
|
||||
final List<PsiMethod> methods = ContainerUtil.filter(anonymousClass.getMethods(), method1 -> !"equals".equals(method1.getName()));
|
||||
method = methods.get(0);
|
||||
} else {
|
||||
method = anonymousClass.getMethods()[0];
|
||||
@@ -257,22 +250,9 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
final ForbiddenRefsChecker checker = new ForbiddenRefsChecker(method, anonymousClass);
|
||||
body.accept(checker);
|
||||
|
||||
final PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(body.getProject());
|
||||
final Set<PsiVariable> conflictingLocals = checker.getLocals();
|
||||
for (Iterator<PsiVariable> iterator = conflictingLocals.iterator(); iterator.hasNext(); ) {
|
||||
PsiVariable local = iterator.next();
|
||||
final String localName = local.getName();
|
||||
if (localName == null || helper.resolveReferencedVariable(localName, anonymousClass) == null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
final Project project = element.getProject();
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
ReplaceWithLambdaFix
|
||||
.giveUniqueNames(project, elementFactory, body, conflictingLocals.toArray(new PsiVariable[conflictingLocals.size()]));
|
||||
|
||||
final String withoutTypesDeclared = ReplaceWithLambdaFix.composeLambdaText(method);
|
||||
|
||||
PsiLambdaExpression lambdaExpression =
|
||||
@@ -281,12 +261,18 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
PsiElement lambdaBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaBody != null);
|
||||
lambdaBody.replace(body);
|
||||
|
||||
ReplaceWithLambdaFix
|
||||
.giveUniqueNames(project, elementFactory, lambdaExpression, lambdaExpression.getParameterList().getParameters());
|
||||
|
||||
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
|
||||
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
|
||||
|
||||
final Set<PsiVariable> variables = new HashSet<>();
|
||||
final Set<String> usedLocalNames = new HashSet<>();
|
||||
|
||||
collectLocalVariablesDefinedInsideLambda(lambdaExpression, variables, usedLocalNames);
|
||||
|
||||
ReplaceWithLambdaFix
|
||||
.giveUniqueNames(project, elementFactory, lambdaExpression,
|
||||
usedLocalNames, variables.toArray(new PsiVariable[variables.size()]));
|
||||
|
||||
final PsiExpression singleExpr = RedundantLambdaCodeBlockInspection.isCodeBlockRedundant(lambdaExpression,
|
||||
lambdaExpression.getBody());
|
||||
if (singleExpr != null) {
|
||||
@@ -320,6 +306,37 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void collectLocalVariablesDefinedInsideLambda(PsiLambdaExpression lambdaExpression,
|
||||
final Set<PsiVariable> variables,
|
||||
Set<String> namesOfVariablesInTheBlock) {
|
||||
PsiElement block = PsiUtil.getTopLevelEnclosingCodeBlock(lambdaExpression, null);
|
||||
if (block == null) {
|
||||
block = lambdaExpression;
|
||||
}
|
||||
|
||||
block.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitVariable(PsiVariable variable) {
|
||||
super.visitVariable(variable);
|
||||
if (!(variable instanceof PsiField)) {
|
||||
variables.add(variable);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(lambdaExpression.getProject());
|
||||
for (Iterator<PsiVariable> iterator = variables.iterator(); iterator.hasNext(); ) {
|
||||
PsiVariable local = iterator.next();
|
||||
final String localName = local.getName();
|
||||
if (localName == null ||
|
||||
helper.resolveReferencedVariable(localName, lambdaExpression) == null ||
|
||||
!PsiTreeUtil.isAncestor(lambdaExpression, local, false)) {
|
||||
iterator.remove();
|
||||
namesOfVariablesInTheBlock.add(localName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReplaceWithLambdaFix implements LocalQuickFix, HighPriorityAction {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -344,17 +361,19 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
private static void giveUniqueNames(Project project,
|
||||
final PsiElementFactory elementFactory,
|
||||
PsiElement body,
|
||||
PsiVariable[] parameters) {
|
||||
Set<String> usedLocalNames, 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, parameter.getParent(), false);
|
||||
String uniqueVariableName = UniqueNameGenerator.generateUniqueName(codeStyleManager.suggestUniqueVariableName(parameterName, parameter.getParent(), false), usedLocalNames);
|
||||
if (!Comparing.equal(parameterName, uniqueVariableName)) {
|
||||
names.put(parameter, uniqueVariableName);
|
||||
}
|
||||
}
|
||||
|
||||
if (names.isEmpty()) return;
|
||||
|
||||
final LinkedHashMap<PsiElement, PsiElement> replacements = new LinkedHashMap<PsiElement, PsiElement>();
|
||||
body.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
@@ -390,13 +409,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
if (parameters.length != 1) {
|
||||
buf.append("(");
|
||||
}
|
||||
buf.append(StringUtil.join(parameters,
|
||||
new Function<PsiParameter, String>() {
|
||||
@Override
|
||||
public String fun(PsiParameter parameter) {
|
||||
return composeParameter(parameter);
|
||||
}
|
||||
}, ","));
|
||||
buf.append(StringUtil.join(parameters, ReplaceWithLambdaFix::composeParameter, ","));
|
||||
if (parameters.length != 1) {
|
||||
buf.append(")");
|
||||
}
|
||||
@@ -437,7 +450,6 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
|
||||
private static class ForbiddenRefsChecker extends JavaRecursiveElementWalkingVisitor {
|
||||
private boolean myBodyContainsForbiddenRefs;
|
||||
private final Set<PsiVariable> myLocals = ContainerUtilRt.newHashSet(5);
|
||||
|
||||
private final PsiMethod myMethod;
|
||||
private final PsiAnonymousClass myAnonymClass;
|
||||
@@ -492,9 +504,6 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
if (myBodyContainsForbiddenRefs) return;
|
||||
|
||||
super.visitVariable(variable);
|
||||
if (!(variable instanceof PsiField)) {
|
||||
myLocals.add(variable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -582,9 +591,5 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
public boolean hasForbiddenRefs() {
|
||||
return myBodyContainsForbiddenRefs;
|
||||
}
|
||||
|
||||
public Set<PsiVariable> getLocals() {
|
||||
return myLocals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with lambda" "true"
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class A {
|
||||
void anonymousToLambda(String s) {
|
||||
String s12 = "";
|
||||
Consumer<String> consumer = s13 -> {
|
||||
String s1 = "";
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// "Replace with lambda" "true"
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class A {
|
||||
void anonymousToLambda(String s) {
|
||||
String s12 = "";
|
||||
Consumer<String> consumer = new Consu<caret>mer<String>() {
|
||||
@Override
|
||||
public void accept(final String s) {
|
||||
String s1 = "";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user