mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJ-CR-137428 [java-completion] IDEA-355252 Don't suggest deconstruction with incorrect name
- extend VariableNameGenerator GitOrigin-RevId: b6c1455ff9e01ae898219410cba45a5c5c669703
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d4059839e2
commit
aec277cf21
@@ -5,6 +5,8 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.UniqueNameGenerator;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -17,10 +19,13 @@ import java.util.*;
|
||||
* It's recommended to have at least one {@link #byName(String...)} call with at least one non-null candidate as the last resort.
|
||||
*/
|
||||
public final class VariableNameGenerator {
|
||||
private final static int MAX_ITERATIONS = 10;
|
||||
|
||||
private final @NotNull JavaCodeStyleManager myManager;
|
||||
private final @NotNull PsiElement myContext;
|
||||
private final @NotNull VariableKind myKind;
|
||||
private final @NonNls Set<String> candidates = new LinkedHashSet<>();
|
||||
private final @NonNls Set<String> skipNames = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Constructs a new generator
|
||||
@@ -91,6 +96,16 @@ public final class VariableNameGenerator {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param names which generator tries not to use
|
||||
* Because of performance reason, there is no guarantee that some of these names will not be reused
|
||||
* @return this generator
|
||||
*/
|
||||
public VariableNameGenerator skipNames(List<String> names) {
|
||||
skipNames.addAll(names);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and returns the unique name
|
||||
* @param lookForward whether further conflicting declarations should be considered
|
||||
@@ -102,12 +117,29 @@ public final class VariableNameGenerator {
|
||||
@NonNls final Set<String> candidates = this.candidates.isEmpty() ? Collections.singleton("v") : this.candidates;
|
||||
for (String candidate : candidates) {
|
||||
String name = myManager.suggestUniqueVariableName(candidate, myContext, lookForward);
|
||||
if (name.equals(candidate)) return name;
|
||||
if (name.equals(candidate)){
|
||||
suffixed = name;
|
||||
break;
|
||||
}
|
||||
if (suffixed == null) {
|
||||
suffixed = name;
|
||||
}
|
||||
}
|
||||
return suffixed;
|
||||
return generateWithSkipped(lookForward, suffixed);
|
||||
}
|
||||
|
||||
private String generateWithSkipped(boolean lookForward, String originalName) {
|
||||
if (!skipNames.contains(originalName)) return originalName;
|
||||
String newName = originalName;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
i++;
|
||||
if (i > MAX_ITERATIONS) break;
|
||||
newName = UniqueNameGenerator.generateUniqueNameOneBased(newName, name -> !skipNames.contains(name));
|
||||
newName = myManager.suggestUniqueVariableName(newName, myContext, lookForward);
|
||||
if (!skipNames.contains(newName)) return newName;
|
||||
}
|
||||
return newName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -126,6 +158,7 @@ public final class VariableNameGenerator {
|
||||
else suffixed.add(name);
|
||||
}
|
||||
result.addAll(suffixed);
|
||||
return result;
|
||||
|
||||
return ContainerUtil.map(result, name -> generateWithSkipped(lookForward, name));
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.source.JavaVarTypeUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -17,6 +18,7 @@ import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.VariableNameGenerator;
|
||||
import one.util.streamex.EntryStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -169,7 +171,12 @@ public final class JavaPatternCompletionUtil {
|
||||
PsiDeconstructionPattern deconstructionPattern = PsiTreeUtil.getParentOfType(context, PsiDeconstructionPattern.class);
|
||||
List<String> names = new ArrayList<>();
|
||||
for (PsiRecordComponent component : record.getRecordComponents()) {
|
||||
names.add(manager.suggestUniqueVariableName(component.getName(), context, true, v -> false, name -> !names.contains(name)));
|
||||
String name = new VariableNameGenerator(context, VariableKind.LOCAL_VARIABLE)
|
||||
.byName(component.getName())
|
||||
.skipNames(names)
|
||||
.generateAll(true)
|
||||
.get(0);
|
||||
names.add(name);
|
||||
}
|
||||
List<PsiType> types = findTypes(deconstructionPattern, record);
|
||||
return new PatternModel(record, names, types, onlyDeconstructionList);
|
||||
|
||||
+5
-12
@@ -1043,17 +1043,12 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, boolean lookForward) {
|
||||
Predicate<PsiVariable> canBeReused =
|
||||
v -> place instanceof PsiParameter && !PsiTreeUtil.isAncestor(((PsiParameter)place).getDeclarationScope(), v, false);
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, false, canBeReused, null);
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, false, canBeReused);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, Predicate<? super PsiVariable> canBeReused) {
|
||||
return suggestUniqueVariableName(baseName, place, true, false, canBeReused, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, boolean lookForward, Predicate<? super PsiVariable> canBeReused, @NotNull Predicate<String> additionalValidator) {
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, false, canBeReused, additionalValidator);
|
||||
return suggestUniqueVariableName(baseName, place, true, false, canBeReused);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1073,7 +1068,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
}
|
||||
String unique = suggestUniqueVariableName(name, place, lookForward);
|
||||
if (!unique.equals(name)) {
|
||||
String withShadowing = suggestUniqueVariableName(name, place, lookForward, place instanceof PsiParameter, v -> false, null);
|
||||
String withShadowing = suggestUniqueVariableName(name, place, lookForward, place instanceof PsiParameter, v -> false);
|
||||
if (withShadowing.equals(name)) {
|
||||
uniqueNames.add(name);
|
||||
}
|
||||
@@ -1093,12 +1088,10 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
PsiElement place,
|
||||
boolean lookForward,
|
||||
boolean allowShadowing,
|
||||
Predicate<? super PsiVariable> canBeReused,
|
||||
@Nullable Predicate<String> additionalValidator) {
|
||||
Predicate<? super PsiVariable> canBeReused) {
|
||||
PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);
|
||||
return UniqueNameGenerator.generateUniqueNameOneBased(
|
||||
baseName, name -> (additionalValidator == null || additionalValidator.test(name)) &&
|
||||
!hasConflictingVariable(place, name, allowShadowing) &&
|
||||
baseName, name -> !hasConflictingVariable(place, name, allowShadowing) &&
|
||||
(!lookForward || !hasConflictingVariableAfterwards(scope, name, canBeReused)));
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -3,12 +3,14 @@ package com.siyeh.ig.fixes;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.psiutils.CreateSwitchBranchesUtil;
|
||||
import com.siyeh.ig.psiutils.SwitchUtils;
|
||||
import com.siyeh.ig.psiutils.VariableNameGenerator;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -118,8 +120,10 @@ public final class CreateMissingDeconstructionRecordClassBranchesFix extends Cre
|
||||
PsiClass recordClass = PsiUtil.resolveClassInClassTypeOnly(TypeConversionUtil.erasure(recordType));
|
||||
if (recordClass == null || !recordClass.isRecord()) return null;
|
||||
for (PsiRecordComponent recordComponent : recordClass.getRecordComponents()) {
|
||||
String nextName = codeStyleManager.suggestUniqueVariableName(recordComponent.getName(), block, false, v -> false,
|
||||
name -> !variableNames.contains(name));
|
||||
String nextName = new VariableNameGenerator(block, VariableKind.LOCAL_VARIABLE)
|
||||
.byName(recordComponent.getName())
|
||||
.skipNames(variableNames)
|
||||
.generate(false);
|
||||
variableNames.add(nextName);
|
||||
}
|
||||
for (List<PsiType> branch : branches.getValue()) {
|
||||
|
||||
@@ -199,24 +199,6 @@ public abstract class JavaCodeStyleManager {
|
||||
@NotNull
|
||||
public abstract String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, Predicate<? super PsiVariable> canBeReused);
|
||||
|
||||
/**
|
||||
* 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 lookForward if true, the existing variables are searched in both directions; if false - only backward
|
||||
* @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)
|
||||
* @param additionalValidator additional validator, which the generated name should pass
|
||||
* @return the generated unique name
|
||||
*/
|
||||
@NotNull
|
||||
public abstract String suggestUniqueVariableName(@NotNull String baseName,
|
||||
PsiElement place,
|
||||
boolean lookForward,
|
||||
Predicate<? super PsiVariable> canBeReused,
|
||||
@Nullable Predicate<String> additionalValidator);
|
||||
|
||||
/**
|
||||
* Suggests a unique name for the variable used at the specified location.
|
||||
*
|
||||
|
||||
@@ -86,15 +86,14 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull @NonNls String baseName, PsiElement place, boolean lookForward) {
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, v -> false, null);
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull @NonNls String baseName, PsiElement place, boolean lookForward) {
|
||||
return suggestUniqueVariableName(baseName, place, lookForward, v -> false);
|
||||
}
|
||||
|
||||
private static @NotNull String suggestUniqueVariableNameInner(@NotNull @NonNls String baseName,
|
||||
private static @NotNull String suggestUniqueVariableName(@NotNull @NonNls String baseName,
|
||||
PsiElement place,
|
||||
boolean lookForward,
|
||||
Predicate<? super PsiVariable> canBeReused,
|
||||
@Nullable Predicate<String> additionalValidator) {
|
||||
Predicate<? super PsiVariable> canBeReused) {
|
||||
int index = 0;
|
||||
PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);
|
||||
NextName:
|
||||
@@ -104,9 +103,6 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
name += index;
|
||||
}
|
||||
index++;
|
||||
if (additionalValidator != null && !additionalValidator.test(name)) {
|
||||
continue;
|
||||
}
|
||||
if (PsiUtil.isVariableNameUnique(name, place)) {
|
||||
if (lookForward) {
|
||||
final String name1 = name;
|
||||
@@ -144,16 +140,7 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
|
||||
@Override
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull String baseName, PsiElement place, Predicate<? super PsiVariable> canBeReused) {
|
||||
return suggestUniqueVariableName(baseName, place, true, canBeReused, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String suggestUniqueVariableName(@NotNull String baseName,
|
||||
PsiElement place,
|
||||
boolean lookForward,
|
||||
Predicate<? super PsiVariable> canBeReused,
|
||||
@Nullable Predicate<String> additionalValidator) {
|
||||
return suggestUniqueVariableNameInner(baseName, place, lookForward, canBeReused, additionalValidator);
|
||||
return suggestUniqueVariableName(baseName, place, true, canBeReused);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user