[java-highlighting] IJ-CR-110955 IDEA-324714 Add quick-fix to produce missed deconstruction patterns.

Added more tests, added shortenClassReferences

GitOrigin-RevId: e74d9b61a09fb314a8d9dbdceee8c30c0c5a3def
This commit is contained in:
Mikhail Pyltsin
2023-07-18 13:16:41 +00:00
committed by intellij-monorepo-bot
parent e133d90ad7
commit da7fe16e4e
19 changed files with 164 additions and 44 deletions
@@ -782,7 +782,8 @@ final class PatternHighlightingModel {
return filtered;
}
private static boolean oneOfUnconditional(PatternDeconstructionDescription whoType, PatternDeconstructionDescription overWhom) {
private static boolean oneOfUnconditional(@NotNull PatternDeconstructionDescription whoType,
@NotNull PatternDeconstructionDescription overWhom) {
if (!whoType.type().equals(overWhom.type())) {
return false;
}
@@ -1,4 +1,4 @@
// "Create missing switch branch 'PairString<Boxed>(Box2 t, java.lang.String t2)'" "true-preview"
// "Create missing switch branch 'PairString<Boxed>(Box2 t, String t2)'" "true-preview"
record Rec(L1 l1) {}
@@ -1,4 +1,4 @@
// "Create missing switch branch 'StringPair<Boxed>(java.lang.String t2, Box t)'" "true-preview"
// "Create missing switch branch 'StringPair<Boxed>(String t2, Box t)'" "true-preview"
record Rec(L1 l1) {}
@@ -1,4 +1,4 @@
// "Create missing switch branch 'PairString<Boxed>(Box2 t, java.lang.String t2)'" "true-preview"
// "Create missing switch branch 'PairString<Boxed>(Box2 t, String t2)'" "true-preview"
record Rec(L1 l1) {}
@@ -1,4 +1,4 @@
// "Create missing switch branch 'StringPair<Boxed>(java.lang.String t2, Box t)'" "true-preview"
// "Create missing switch branch 'StringPair<Boxed>(String t2, Box t)'" "true-preview"
record Rec(L1 l1) {}
@@ -1,7 +1,4 @@
// "Create missing switch branch 'Pair<Boxed,Boxed>(Box b1, Boxed b2)'" "true-preview"
record Rec(L1 l1) {}
record Pair<T, K>(T b1, K b2) {}
sealed interface Boxed permits Box, Box2 {}
@@ -1,8 +1,4 @@
// "Create missing switch branch 'PairString<Boxed>(Box2 t, java.lang.String t2)'" "true-preview"
record Rec(L1 l1) {}
record Pair<T, K>(T b1, K b2) {}
// "Create missing switch branch 'PairString<Boxed>(Box2 t, String t2)'" "true-preview"
sealed interface Boxed permits Box, Box2 {}
@@ -18,8 +14,6 @@ final class L22 implements L1 {}
record PairString<T>(T t, String t2) { }
record StringPair<T>(String t2, T t) { }
class Test {
void foo4(PairString<Boxed> o) {
switch (o) {
@@ -1,8 +1,4 @@
// "Create missing switch branch 'StringPair<Boxed>(java.lang.String t2, Box t)'" "true-preview"
record Rec(L1 l1) {}
record Pair<T, K>(T b1, K b2) {}
// "Create missing switch branch 'StringPair<Boxed>(String t2, Box t)'" "true-preview"
sealed interface Boxed permits Box, Box2 {}
@@ -16,8 +12,6 @@ final class L21 implements L1 {}
final class L22 implements L1 {}
record PairString<T>(T t, String t2) { }
record StringPair<T>(String t2, T t) { }
class Test {
@@ -0,0 +1,22 @@
// "Create missing branches: 'Pair(A sc1, B sc2)', and 'Pair(B sc1, A sc2)'" "true-preview"
record Pair(SC sc1, SC sc2) {
}
sealed interface SC{}
final class A implements SC{}
final class B implements SC{}
class Test {
void foo1(Pair o) {
switch (o) {
case Pair(A sc1, A sc2) -> System.out.println("1");
case Pair(B sc1, B sc2) -> System.out.println("1");
case Pair(A sc1, B sc2) -> {
}
case Pair(B sc1, A sc2) -> {
}
}
}
}
@@ -0,0 +1,21 @@
// "Create missing branches: 'Pair(A sc1, A sc2)', and 'Pair(B sc1, B sc2)'" "true-preview"
record Pair(SC sc1, SC sc2) {
}
sealed interface SC{}
final class A implements SC{}
final class B implements SC{}
class Test {
void foo2(Pair o) {
switch (o) {
case Pair(A sc1, B sc2) -> System.out.println("1");
case Pair(B sc1, A sc2) -> System.out.println("1");
case Pair(A sc1, A sc2) -> {
}
case Pair(B sc1, B sc2) -> {
}
}
}
}
@@ -0,0 +1,32 @@
// "Create missing branches: 'Pair(A sc1, B sc2)', 'Pair(A sc1, C sc2)', ..." "true-preview"
record Pair(SC sc1, SC sc2) {
}
sealed interface SC{}
final class A implements SC{}
final class B implements SC{}
final class C implements SC{}
class Test {
void foo1(Pair o) {
switch (o) {
case Pair(A sc1, A sc2) -> System.out.println("1");
case Pair(B sc1, B sc2) -> System.out.println("1");
case Pair(C sc1, C sc2) -> System.out.println("1");
case Pair(A sc1, B sc2) -> {
}
case Pair(A sc1, C sc2) -> {
}
case Pair(B sc1, A sc2) -> {
}
case Pair(B sc1, C sc2) -> {
}
case Pair(C sc1, A sc2) -> {
}
case Pair(C sc1, B sc2) -> {
}
}
}
}
@@ -1,7 +1,4 @@
// "Create missing switch branch 'Pair<Boxed,Boxed>(Box b1, Boxed b2)'" "true-preview"
record Rec(L1 l1) {}
record Pair<T, K>(T b1, K b2) {}
sealed interface Boxed permits Box, Box2 {}
@@ -1,8 +1,4 @@
// "Create missing switch branch 'PairString<Boxed>(Box2 t, java.lang.String t2)'" "true-preview"
record Rec(L1 l1) {}
record Pair<T, K>(T b1, K b2) {}
// "Create missing switch branch 'PairString<Boxed>(Box2 t, String t2)'" "true-preview"
sealed interface Boxed permits Box, Box2 {}
@@ -18,8 +14,6 @@ final class L22 implements L1 {}
record PairString<T>(T t, String t2) { }
record StringPair<T>(String t2, T t) { }
class Test {
void foo4(PairString<Boxed> o) {
switch (o<caret>) {
@@ -1,8 +1,4 @@
// "Create missing switch branch 'StringPair<Boxed>(java.lang.String t2, Box t)'" "true-preview"
record Rec(L1 l1) {}
record Pair<T, K>(T b1, K b2) {}
// "Create missing switch branch 'StringPair<Boxed>(String t2, Box t)'" "true-preview"
sealed interface Boxed permits Box, Box2 {}
@@ -16,8 +12,6 @@ final class L21 implements L1 {}
final class L22 implements L1 {}
record PairString<T>(T t, String t2) { }
record StringPair<T>(String t2, T t) { }
class Test {
@@ -0,0 +1,18 @@
// "Create missing branches: 'Pair(A sc1, B sc2)', and 'Pair(B sc1, A sc2)'" "true-preview"
record Pair(SC sc1, SC sc2) {
}
sealed interface SC{}
final class A implements SC{}
final class B implements SC{}
class Test {
void foo1(Pair o) {
switch (o<caret>) {
case Pair(A sc1, A sc2) -> System.out.println("1");
case Pair(B sc1, B sc2) -> System.out.println("1");
}
}
}
@@ -0,0 +1,17 @@
// "Create missing branches: 'Pair(A sc1, A sc2)', and 'Pair(B sc1, B sc2)'" "true-preview"
record Pair(SC sc1, SC sc2) {
}
sealed interface SC{}
final class A implements SC{}
final class B implements SC{}
class Test {
void foo2(Pair o) {
switch (o<caret>) {
case Pair(A sc1, B sc2) -> System.out.println("1");
case Pair(B sc1, A sc2) -> System.out.println("1");
}
}
}
@@ -0,0 +1,20 @@
// "Create missing branches: 'Pair(A sc1, B sc2)', 'Pair(A sc1, C sc2)', ..." "true-preview"
record Pair(SC sc1, SC sc2) {
}
sealed interface SC{}
final class A implements SC{}
final class B implements SC{}
final class C implements SC{}
class Test {
void foo1(Pair o) {
switch (o<caret>) {
case Pair(A sc1, A sc2) -> System.out.println("1");
case Pair(B sc1, B sc2) -> System.out.println("1");
case Pair(C sc1, C sc2) -> System.out.println("1");
}
}
}
@@ -7,6 +7,7 @@ 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 org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -18,12 +19,20 @@ import java.util.function.Function;
public final class CreateMissingDeconstructionRecordClassBranchesFix extends CreateMissingSwitchBranchesFix {
private final List<String> allNames;
private final List<String> missedShorten;
private CreateMissingDeconstructionRecordClassBranchesFix(@NotNull PsiSwitchBlock block,
@NotNull Set<String> missedNames,
@NotNull List<String> allNames) {
@NotNull List<String> allNames,
@NotNull List<String> missedShorten) {
super(block, missedNames);
this.allNames = allNames;
this.missedShorten = missedShorten;
}
@Override
protected String getText(@NotNull PsiSwitchBlock switchBlock) {
return CreateSwitchBranchesUtil.getActionName(missedShorten.stream().sorted().toList());
}
@Override
@@ -82,18 +91,23 @@ public final class CreateMissingDeconstructionRecordClassBranchesFix extends Cre
if (element == null) return null;
allLabels.add(element.getText());
}
List<String> missedLabels = getMissedLabels(switchBlock, missedBranches);
List<String> missedLabels = getMissedLabels(switchBlock, missedBranches, false);
if (missedLabels == null || missedLabels.isEmpty()) {
return null;
}
allLabels.addAll(lastDeconstructionPatternIndex + 1, missedLabels);
allLabels = allLabels.stream().distinct().toList();
return new CreateMissingDeconstructionRecordClassBranchesFix(switchBlock, new HashSet<>(missedLabels), allLabels);
List<String> shortenLabels = getMissedLabels(switchBlock, missedBranches, true);
if (shortenLabels == null) {
return null;
}
return new CreateMissingDeconstructionRecordClassBranchesFix(switchBlock, new HashSet<>(missedLabels), allLabels, shortenLabels);
}
@Nullable
private static List<String> getMissedLabels(@NotNull PsiSwitchBlock block,
@NotNull Map<PsiType, Set<List<PsiType>>> branchesByType) {
@NotNull Map<PsiType, Set<List<PsiType>>> branchesByType,
boolean shorten) {
List<String> result = new ArrayList<>();
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(block.getProject());
for (Map.Entry<PsiType, Set<List<PsiType>>> branches : branchesByType.entrySet()) {
@@ -114,7 +128,8 @@ public final class CreateMissingDeconstructionRecordClassBranchesFix extends Cre
if (branch.size() != variableNames.size()) return null;
for (int i = 0; i < branch.size(); i++) {
PsiType psiType = branch.get(i);
joiner.add(psiType.getCanonicalText() + " " + variableNames.get(i));
String typeText = shorten ? psiType.getPresentableText() : psiType.getCanonicalText();
joiner.add(typeText + " " + variableNames.get(i));
}
result.add(recordTypeString + joiner);
}
@@ -12,6 +12,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -65,6 +66,7 @@ public final class CreateSwitchBranchesUtil {
@NotNull List<String> allNames,
@NotNull Collection<String> missingNames,
@NotNull Function<? super PsiSwitchLabelStatementBase, ? extends List<String>> caseExtractor) {
final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(switchBlock.getProject());
boolean isRuleBasedFormat = SwitchUtils.isRuleFormatSwitch(switchBlock);
final PsiCodeBlock body = switchBlock.getBody();
final PsiExpression switchExpression = switchBlock.getExpression();
@@ -87,6 +89,7 @@ public final class CreateSwitchBranchesUtil {
}
newStatementText.append('}');
PsiSwitchBlock block = (PsiSwitchBlock)commentTracker.replaceAndRestoreComments(switchBlock, newStatementText.toString());
javaCodeStyleManager.shortenClassReferences(block);
return PsiTreeUtil.getChildrenOfTypeAsList(block.getBody(), PsiSwitchLabelStatementBase.class);
}
Map<String, String> prevToNext = StreamEx.of(allNames).pairMap(Couple::of).toMap(c -> c.getFirst(), c -> c.getSecond());
@@ -126,6 +129,7 @@ public final class CreateSwitchBranchesUtil {
addedLabels.add(addSwitchLabelStatementBefore(missingElement, lastChild, switchBlock, isRuleBasedFormat, isPatternsGenerated));
}
}
addedLabels.forEach(label -> javaCodeStyleManager.shortenClassReferences(label));
return addedLabels;
}