mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
StreamToLoopInspection: get rid of placeholder; instead pass a predicate to suggestUniqueVariableName to be able to reuse existing names
This commit is contained in:
+52
-47
@@ -319,46 +319,50 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
PsiStatement statement = PsiTreeUtil.getParentOfType(terminalCall, PsiStatement.class);
|
||||
LOG.assertTrue(statement != null);
|
||||
CommentTracker ct = new CommentTracker();
|
||||
PsiExpression temporaryStreamPlaceholder =
|
||||
(PsiExpression)ct.replace(terminalCall, "((" + resultType.getCanonicalText() + ")$streamReplacement$)");
|
||||
try {
|
||||
StreamToLoopReplacementContext context =
|
||||
new StreamToLoopReplacementContext(statement, operations, temporaryStreamPlaceholder, ct);
|
||||
new StreamToLoopReplacementContext(statement, operations, terminalCall, ct);
|
||||
registerVariables(operations, context);
|
||||
String replacement = "";
|
||||
for (OperationRecord or : StreamEx.ofReversed(operations)) {
|
||||
replacement = or.myOperation.wrap(or.myInVar, or.myOutVar, replacement, context);
|
||||
}
|
||||
ct.insertCommentsBefore(statement);
|
||||
PsiElement firstAdded = null;
|
||||
for (PsiStatement addedStatement : ((PsiBlockStatement)factory.createStatementFromText("{" + replacement + "}", statement))
|
||||
.getCodeBlock().getStatements()) {
|
||||
addStatement(project, statement, addedStatement);
|
||||
PsiElement res = addStatement(project, statement, addedStatement);
|
||||
if (firstAdded == null) {
|
||||
firstAdded = res;
|
||||
}
|
||||
}
|
||||
PsiElement result = context.makeFinalReplacement();
|
||||
if(result != null) {
|
||||
normalize(project, result);
|
||||
result = normalize(project, result);
|
||||
if (firstAdded == null) {
|
||||
firstAdded = result;
|
||||
}
|
||||
}
|
||||
if (firstAdded != null) {
|
||||
ct.insertCommentsBefore(firstAdded);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
String text = terminalCall.getText();
|
||||
if(temporaryStreamPlaceholder.isPhysical()) {
|
||||
// Just in case if something went wrong: at least try to restore the original stream code
|
||||
temporaryStreamPlaceholder.replace(factory.createExpressionFromText(text, temporaryStreamPlaceholder));
|
||||
}
|
||||
LOG.error(LogMessageEx.createEvent("Error converting Stream to loop", ExceptionUtil.getThrowableText(ex),
|
||||
new Attachment("Stream_code.txt", text)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void addStatement(@NotNull Project project, PsiStatement statement, PsiStatement context) {
|
||||
private static PsiElement addStatement(@NotNull Project project, PsiStatement statement, PsiStatement context) {
|
||||
PsiElement element = statement.getParent().addBefore(context, statement);
|
||||
normalize(project, element);
|
||||
return normalize(project, element);
|
||||
}
|
||||
|
||||
private static void normalize(@NotNull Project project, PsiElement element) {
|
||||
private static PsiElement normalize(@NotNull Project project, PsiElement element) {
|
||||
element = JavaCodeStyleManager.getInstance(project).shortenClassReferences(element);
|
||||
PsiDiamondTypeUtil.removeRedundantTypeArguments(element);
|
||||
RedundantCastUtil.getRedundantCastsInside(element).forEach(RedundantCastUtil::removeCast);
|
||||
return element;
|
||||
}
|
||||
|
||||
private static StreamEx<OperationRecord> allOperations(List<OperationRecord> operations) {
|
||||
@@ -399,19 +403,19 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
private final List<String> myBeforeSteps = new ArrayList<>();
|
||||
private final List<String> myAfterSteps = new ArrayList<>();
|
||||
private final CommentTracker myCommentTracker;
|
||||
private PsiElement myPlaceholder;
|
||||
private PsiElement myStreamExpression;
|
||||
private final PsiElementFactory myFactory;
|
||||
private String myLabel;
|
||||
private String myFinisher;
|
||||
|
||||
StreamToLoopReplacementContext(PsiStatement statement,
|
||||
List<OperationRecord> records,
|
||||
@NotNull PsiExpression placeholder,
|
||||
@NotNull PsiExpression streamExpression,
|
||||
CommentTracker ct) {
|
||||
myStatement = statement;
|
||||
myFactory = JavaPsiFacade.getElementFactory(myStatement.getProject());
|
||||
myHasNestedLoops = records.stream().anyMatch(or -> or.myOperation instanceof FlatMapOperation);
|
||||
myPlaceholder = placeholder;
|
||||
myStreamExpression = streamExpression;
|
||||
mySuffix = myHasNestedLoops ? "Outer" : "";
|
||||
myCommentTracker = ct;
|
||||
myUsedNames = new HashSet<>();
|
||||
@@ -422,7 +426,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
StreamToLoopReplacementContext(StreamToLoopReplacementContext parentContext, List<OperationRecord> records) {
|
||||
myUsedNames = parentContext.myUsedNames;
|
||||
myUsedLabels = parentContext.myUsedLabels;
|
||||
myPlaceholder = null;
|
||||
myStreamExpression = parentContext.myStreamExpression;
|
||||
myStatement = parentContext.myStatement;
|
||||
myFactory = parentContext.myFactory;
|
||||
myCommentTracker = parentContext.myCommentTracker;
|
||||
@@ -480,7 +484,8 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
private boolean isUsed(String varName) {
|
||||
return myUsedNames.contains(varName) || JavaLexer.isKeyword(varName, LanguageLevel.HIGHEST) ||
|
||||
!varName.equals(JavaCodeStyleManager.getInstance(myStatement.getProject()).suggestUniqueVariableName(varName, myStatement, true));
|
||||
!varName.equals(JavaCodeStyleManager.getInstance(myStatement.getProject())
|
||||
.suggestUniqueVariableName(varName, myStatement, v -> PsiTreeUtil.isAncestor(myStreamExpression, v, true)));
|
||||
}
|
||||
|
||||
public String declare(String desiredName, String type, String initializer) {
|
||||
@@ -511,13 +516,13 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
public String declareResult(String desiredName, String type, String initializer, @NotNull ResultKind kind) {
|
||||
if (kind != ResultKind.UNKNOWN && myPlaceholder.getParent() instanceof PsiVariable) {
|
||||
PsiVariable var = (PsiVariable)myPlaceholder.getParent();
|
||||
if (kind != ResultKind.UNKNOWN && myStreamExpression.getParent() instanceof PsiVariable) {
|
||||
PsiVariable var = (PsiVariable)myStreamExpression.getParent();
|
||||
if(var.getType().equalsToText(type) && var.getParent() instanceof PsiDeclarationStatement
|
||||
&& (kind == ResultKind.FINAL || canUseAsNonFinal(var))) {
|
||||
PsiDeclarationStatement declaration = (PsiDeclarationStatement)var.getParent();
|
||||
if(declaration.getDeclaredElements().length == 1) {
|
||||
myPlaceholder = declaration;
|
||||
myStreamExpression = declaration;
|
||||
PsiVariable copy = (PsiVariable)var.copy();
|
||||
if (kind == ResultKind.NON_FINAL) {
|
||||
PsiModifierList modifierList = copy.getModifierList();
|
||||
@@ -553,18 +558,18 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
public PsiElement makeFinalReplacement() {
|
||||
LOG.assertTrue(myPlaceholder != null);
|
||||
if (myFinisher == null || myPlaceholder instanceof PsiStatement) {
|
||||
myPlaceholder.delete();
|
||||
LOG.assertTrue(myStreamExpression != null);
|
||||
if (myFinisher == null || myStreamExpression instanceof PsiStatement) {
|
||||
myCommentTracker.delete(myStreamExpression);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
PsiExpression expression = myFactory.createExpressionFromText(myFinisher, myPlaceholder);
|
||||
PsiElement parent = myPlaceholder.getParent();
|
||||
PsiExpression expression = myFactory.createExpressionFromText(myFinisher, myStreamExpression);
|
||||
PsiElement parent = myStreamExpression.getParent();
|
||||
if (parent instanceof PsiExpression && ParenthesesUtils.areParenthesesNeeded(expression, (PsiExpression)parent, false)) {
|
||||
expression = myFactory.createExpressionFromText("("+myFinisher+")", myPlaceholder);
|
||||
expression = myFactory.createExpressionFromText("("+myFinisher+")", myStreamExpression);
|
||||
}
|
||||
return myPlaceholder.replace(expression);
|
||||
return myCommentTracker.replace(myStreamExpression, expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,7 +585,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
public String assignAndBreak(ConditionalExpression conditionalExpression) {
|
||||
PsiStatement statement = PsiTreeUtil.getParentOfType(myPlaceholder, PsiStatement.class);
|
||||
PsiStatement statement = PsiTreeUtil.getParentOfType(myStreamExpression, PsiStatement.class);
|
||||
boolean inReturn = statement instanceof PsiReturnStatement;
|
||||
if(conditionalExpression instanceof ConditionalExpression.Optional) {
|
||||
conditionalExpression = tryUnwrapOptional((ConditionalExpression.Optional)conditionalExpression, inReturn);
|
||||
@@ -591,38 +596,38 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
if (inReturn) {
|
||||
setFinisher(conditionalExpression.getFalseBranch());
|
||||
Object mark = new Object();
|
||||
PsiTreeUtil.mark(myPlaceholder, mark);
|
||||
PsiTreeUtil.mark(myStreamExpression, mark);
|
||||
PsiElement returnCopy = statement.copy();
|
||||
PsiElement placeHolderCopy = PsiTreeUtil.releaseMark(returnCopy, mark);
|
||||
LOG.assertTrue(placeHolderCopy != null);
|
||||
PsiElement replacement = placeHolderCopy.replace(createExpression(conditionalExpression.getTrueBranch()));
|
||||
return (placeHolderCopy == returnCopy ? replacement : returnCopy).getText();
|
||||
}
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(myPlaceholder.getParent());
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(myStreamExpression.getParent());
|
||||
if(parent instanceof PsiIfStatement && conditionalExpression instanceof ConditionalExpression.Boolean &&
|
||||
!((ConditionalExpression.Boolean)conditionalExpression).isInverted()) {
|
||||
PsiIfStatement ifStatement = (PsiIfStatement)parent;
|
||||
if(ifStatement.getElseBranch() == null) {
|
||||
PsiStatement thenStatement = ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
|
||||
if(thenStatement instanceof PsiReturnStatement || thenStatement instanceof PsiThrowStatement) {
|
||||
myPlaceholder = parent;
|
||||
myStreamExpression = parent;
|
||||
return thenStatement.getText();
|
||||
}
|
||||
if(thenStatement instanceof PsiExpressionStatement) {
|
||||
myPlaceholder = parent;
|
||||
myStreamExpression = parent;
|
||||
return thenStatement.getText() + "\n" + getBreakStatement();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(conditionalExpression instanceof ConditionalExpression.Optional && myPlaceholder instanceof PsiExpression) {
|
||||
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier((PsiExpression)myPlaceholder);
|
||||
if(conditionalExpression instanceof ConditionalExpression.Optional && myStreamExpression instanceof PsiExpression) {
|
||||
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier((PsiExpression)myStreamExpression);
|
||||
if(call != null && call.getParent() instanceof PsiExpressionStatement) {
|
||||
PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
if(args.length == 1 && "ifPresent".equals(call.getMethodExpression().getReferenceName())) {
|
||||
FunctionHelper fn = FunctionHelper.create(args[0], 1);
|
||||
if(fn != null) {
|
||||
fn.transform(this, ((ConditionalExpression.Optional)conditionalExpression).unwrap("").getTrueBranch());
|
||||
myPlaceholder = call.getParent();
|
||||
myStreamExpression = call.getParent();
|
||||
return fn.getStatementText() + getBreakStatement();
|
||||
}
|
||||
}
|
||||
@@ -635,19 +640,19 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
private ConditionalExpression tryUnwrapBoolean(ConditionalExpression.Boolean condition, boolean unwrapLazilyEvaluated) {
|
||||
if (myPlaceholder instanceof PsiExpression) {
|
||||
PsiExpression negation = BoolUtils.findNegation((PsiExpression)myPlaceholder);
|
||||
if (myStreamExpression instanceof PsiExpression) {
|
||||
PsiExpression negation = BoolUtils.findNegation((PsiExpression)myStreamExpression);
|
||||
if (negation != null) {
|
||||
myPlaceholder = negation;
|
||||
myStreamExpression = negation;
|
||||
condition = condition.negate();
|
||||
}
|
||||
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(myPlaceholder.getParent());
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(myStreamExpression.getParent());
|
||||
ConditionalExpression candidate = null;
|
||||
if (parent instanceof PsiPolyadicExpression) {
|
||||
PsiPolyadicExpression expression = (PsiPolyadicExpression)parent;
|
||||
PsiExpression[] operands = expression.getOperands();
|
||||
if (operands.length > 1 && PsiTreeUtil.isAncestor(operands[0], myPlaceholder, false)) {
|
||||
if (operands.length > 1 && PsiTreeUtil.isAncestor(operands[0], myStreamExpression, false)) {
|
||||
IElementType type = expression.getOperationTokenType();
|
||||
if (type.equals(JavaTokenType.ANDAND)) {
|
||||
candidate = condition
|
||||
@@ -659,7 +664,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
} else if (parent instanceof PsiConditionalExpression) {
|
||||
PsiConditionalExpression ternary = (PsiConditionalExpression)parent;
|
||||
if (PsiTreeUtil.isAncestor(ternary.getCondition(), myPlaceholder, false)) {
|
||||
if (PsiTreeUtil.isAncestor(ternary.getCondition(), myStreamExpression, false)) {
|
||||
PsiType type = ternary.getType();
|
||||
PsiExpression thenExpression = ternary.getThenExpression();
|
||||
PsiExpression elseExpression = ternary.getElseExpression();
|
||||
@@ -670,7 +675,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
if (candidate != null &&
|
||||
(unwrapLazilyEvaluated || ExpressionUtils.isSimpleExpression(createExpression(candidate.getFalseBranch())))) {
|
||||
myPlaceholder = parent;
|
||||
myStreamExpression = parent;
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
@@ -679,13 +684,13 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
@NotNull
|
||||
private ConditionalExpression tryUnwrapOptional(ConditionalExpression.Optional condition, boolean unwrapLazilyEvaluated) {
|
||||
if (myPlaceholder instanceof PsiExpression) {
|
||||
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier((PsiExpression)myPlaceholder);
|
||||
if (myStreamExpression instanceof PsiExpression) {
|
||||
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier((PsiExpression)myStreamExpression);
|
||||
if (call != null && !(call.getParent() instanceof PsiExpressionStatement)) {
|
||||
String name = call.getMethodExpression().getReferenceName();
|
||||
PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
if (args.length == 0 && "isPresent".equals(name)) {
|
||||
myPlaceholder = call;
|
||||
myStreamExpression = call;
|
||||
return new ConditionalExpression.Boolean(condition.getCondition(), false);
|
||||
}
|
||||
if (args.length == 1) {
|
||||
@@ -701,7 +706,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
}
|
||||
if (absentExpression != null) {
|
||||
myPlaceholder = call;
|
||||
myStreamExpression = call;
|
||||
return condition.unwrap(absentExpression);
|
||||
}
|
||||
}
|
||||
|
||||
+73
-69
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,6 +40,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -677,12 +679,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
|
||||
@NotNull
|
||||
private static String constantValueToConstantName(@NotNull String[] names) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (i > 0) result.append("_");
|
||||
result.append(names[i]);
|
||||
}
|
||||
return result.toString();
|
||||
return Arrays.stream(names).collect(Collectors.joining("_"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -749,13 +746,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
method = (PsiMethod)navElement;
|
||||
}
|
||||
PsiExpression[] expressions = list.getExpressions();
|
||||
int index = -1;
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
if (expressions[i] == expr) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int index = ArrayUtil.indexOf(expressions, expr);
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (index < parameters.length) {
|
||||
String name = parameters[index].getName();
|
||||
@@ -899,62 +890,13 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, boolean lookForward) {
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, false);
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, false, v -> false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, boolean lookForward, boolean allowShadowing) {
|
||||
PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);
|
||||
for (int index = 0; ; index++) {
|
||||
String name = index > 0 ? baseName + index : baseName;
|
||||
if (hasConflictingVariable(place, name, allowShadowing) || lookForward && hasConflictingVariableAfterwards(scope, name)) {
|
||||
continue;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasConflictingVariableAfterwards(@Nullable PsiElement scope, @NotNull final String name) {
|
||||
PsiElement run = scope;
|
||||
while (run != null) {
|
||||
class CancelException extends RuntimeException {
|
||||
}
|
||||
try {
|
||||
run.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitClass(final PsiClass aClass) {}
|
||||
|
||||
@Override public void visitVariable(PsiVariable variable) {
|
||||
if (name.equals(variable.getName())) {
|
||||
throw new CancelException();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (CancelException e) {
|
||||
return true;
|
||||
}
|
||||
run = run.getNextSibling();
|
||||
if (scope instanceof PsiMethod || scope instanceof PsiForeachStatement) {//do not check next member for param name conflict
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasConflictingVariable(@Nullable PsiElement place, @NotNull String name, boolean allowShadowing) {
|
||||
if (place == null) {
|
||||
return false;
|
||||
}
|
||||
PsiResolveHelper helper = JavaPsiFacade.getInstance(place.getProject()).getResolveHelper();
|
||||
PsiVariable existingVariable = helper.resolveAccessibleReferencedVariable(name, place);
|
||||
if (existingVariable == null) return false;
|
||||
|
||||
if (allowShadowing && existingVariable instanceof PsiField && PsiTreeUtil.getNonStrictParentOfType(place, PsiMethod.class) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@NotNull
|
||||
@Override
|
||||
public String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, Predicate<PsiVariable> canBeReused) {
|
||||
return suggestUniqueVariableName(baseName, place, true, false, canBeReused);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -975,7 +917,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
}
|
||||
String unique = suggestUniqueVariableName(name, place, lookForward);
|
||||
if (!unique.equals(name)) {
|
||||
String withShadowing = suggestUniqueVariableName(name, place, lookForward, true);
|
||||
String withShadowing = suggestUniqueVariableName(name, place, lookForward, true, v -> false);
|
||||
if (withShadowing.equals(name)) {
|
||||
uniqueNames.add(name);
|
||||
}
|
||||
@@ -991,6 +933,68 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String suggestUniqueVariableName(@NotNull String baseName,
|
||||
PsiElement place,
|
||||
boolean lookForward,
|
||||
boolean allowShadowing,
|
||||
Predicate<PsiVariable> canBeReused) {
|
||||
PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);
|
||||
for (int index = 0; ; index++) {
|
||||
String name = index > 0 ? baseName + index : baseName;
|
||||
if (hasConflictingVariable(place, name, allowShadowing) ||
|
||||
lookForward && hasConflictingVariableAfterwards(scope, name, canBeReused)) {
|
||||
continue;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasConflictingVariable(@Nullable PsiElement place, @NotNull String name, boolean allowShadowing) {
|
||||
if (place == null) {
|
||||
return false;
|
||||
}
|
||||
PsiResolveHelper helper = JavaPsiFacade.getInstance(place.getProject()).getResolveHelper();
|
||||
PsiVariable existingVariable = helper.resolveAccessibleReferencedVariable(name, place);
|
||||
if (existingVariable == null) return false;
|
||||
|
||||
if (allowShadowing && existingVariable instanceof PsiField && PsiTreeUtil.getNonStrictParentOfType(place, PsiMethod.class) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean hasConflictingVariableAfterwards(@Nullable PsiElement scope,
|
||||
@NotNull final String name,
|
||||
@NotNull Predicate<PsiVariable> canBeReused) {
|
||||
PsiElement run = scope;
|
||||
while (run != null) {
|
||||
class CancelException extends RuntimeException {
|
||||
}
|
||||
try {
|
||||
run.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitClass(final PsiClass aClass) {}
|
||||
|
||||
@Override public void visitVariable(PsiVariable variable) {
|
||||
if (name.equals(variable.getName()) && !canBeReused.test(variable)) {
|
||||
throw new CancelException();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (CancelException e) {
|
||||
return true;
|
||||
}
|
||||
run = run.getNextSibling();
|
||||
if (scope instanceof PsiMethod || scope instanceof PsiForeachStatement) {//do not check next member for param name conflict
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void sortVariableNameSuggestions(@NotNull String[] names,
|
||||
@NotNull final VariableKind variableKind,
|
||||
@Nullable final String propertyName,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -203,6 +204,18 @@ public abstract class JavaCodeStyleManager {
|
||||
return suggestUniqueVariableName(baseNameInfo, place, false, lookForward);
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests a unique name for the variable used at the specified location looking forward with possible filtering.
|
||||
*
|
||||
* @param baseName the base name info for the variable.
|
||||
* @param place the location where the variable will be used.
|
||||
* @param canBeReused a predicate which returns true for variables which names still could be reused (e.g. a variable will be deleted
|
||||
* during the ongoing refactoring)
|
||||
* @return the generated unique name
|
||||
*/
|
||||
@NotNull
|
||||
public abstract String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, Predicate<PsiVariable> canBeReused);
|
||||
|
||||
/**
|
||||
* Suggests a unique name for the variable used at the specified location.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
@Override
|
||||
@@ -63,6 +64,7 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement shortenClassReferences(@NotNull PsiElement element) throws IncorrectOperationException {
|
||||
return element;
|
||||
@@ -106,6 +108,14 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public String suggestUniqueVariableName(@NotNull @NonNls String baseName, PsiElement place, boolean lookForward) {
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, v -> false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String suggestUniqueVariableName(@NotNull @NonNls String baseName,
|
||||
PsiElement place,
|
||||
boolean lookForward,
|
||||
Predicate<PsiVariable> canBeReused) {
|
||||
int index = 0;
|
||||
PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);
|
||||
NextName:
|
||||
@@ -129,7 +139,7 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
}
|
||||
|
||||
@Override public void visitVariable(PsiVariable variable) {
|
||||
if (name1.equals(variable.getName())) {
|
||||
if (name1.equals(variable.getName()) && !canBeReused.test(variable)) {
|
||||
throw new CancelException();
|
||||
}
|
||||
}
|
||||
@@ -150,6 +160,12 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, Predicate<PsiVariable> canBeReused) {
|
||||
return suggestUniqueVariableName(baseName, place, true, canBeReused);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo,
|
||||
|
||||
Reference in New Issue
Block a user