[java-inspections] IDEA-360755 Convert to enhanced switch erases the default value

GitOrigin-RevId: 7562bb688c2bf6e93bab7537113bb54246949006
This commit is contained in:
Mikhail Pyltsin
2024-10-28 21:01:30 +00:00
committed by intellij-monorepo-bot
parent 874d716d2a
commit bf865ed4ae
3 changed files with 74 additions and 27 deletions
@@ -78,7 +78,9 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
JavaBundle.message("inspection.switch.expression.migration.warn.only.on.expression"),
true)));
}
if (replacer.getType() == ReplacementType.Expression && replacer.getMaxNumberStatementsInBranch() != null && replacer.getMaxNumberStatementsInBranch() > 1) {
if (replacer.getType() == ReplacementType.Expression &&
replacer.getMaxNumberStatementsInBranch() != null &&
replacer.getMaxNumberStatementsInBranch() > 1) {
int newMaxValue = replacer.getMaxNumberStatementsInBranch() - 1;
fixes.add(LocalQuickFix.from(new UpdateInspectionOptionFix(
EnhancedSwitchMigrationInspection.this, "myMaxNumberStatementsForBranch",
@@ -226,7 +228,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
}
StreamEx.ofTree((PsiElement)switchBlock, block -> Arrays.stream(block.getChildren()))
.select(PsiBreakStatement.class)
.filter(breakStmt -> ControlFlowUtils.statementCompletesWithStatement(switchBlock, breakStmt) && breakStmt.findExitedStatement() == switchBlock)
.filter(breakStmt -> ControlFlowUtils.statementCompletesWithStatement(switchBlock, breakStmt) &&
breakStmt.findExitedStatement() == switchBlock)
.forEach(statement -> new CommentTracker().delete(statement));
return switchBlock;
}
@@ -237,7 +240,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
if (existsDefaultLabelElement(branch.myLabelStatement)) return true;
}
CompletenessResult completenessResult = evaluateSwitchCompleteness(switchStatement, true);
return completenessResult == CompletenessResult.COMPLETE_WITHOUT_UNCONDITIONAL || completenessResult == CompletenessResult.COMPLETE_WITH_UNCONDITIONAL;
return completenessResult == CompletenessResult.COMPLETE_WITHOUT_UNCONDITIONAL ||
completenessResult == CompletenessResult.COMPLETE_WITH_UNCONDITIONAL;
}
private static boolean isConvertibleBranch(@NotNull OldSwitchStatementBranch branch, boolean hasNext) {
@@ -255,7 +259,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
this.key = key;
}
@Nls String getFixName() {
@Nls
String getFixName() {
return JavaBundle.message(key);
}
}
@@ -315,10 +320,11 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
* This method is used to rearrange branches.
* Now it can change the order of branches or divide some branches into several separate branches.
* For example, a null branch will be extracted from others.
*
* @return rearranged branches
*/
private static @NotNull List<SwitchBranch> rearrangeBranches(@NotNull List<SwitchBranch> branches,
@NotNull PsiElement context) {
@NotNull PsiElement context) {
if (branches.isEmpty()) {
return branches;
}
@@ -344,6 +350,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
/**
* This method is used to rearrange case elements.
* Method is used by {@link #rearrangeBranches(List, PsiElement)}.
*
* @param result - container, where sorted cases will be added
*/
private static void rearrangeCases(@NotNull SwitchBranch branch,
@@ -375,7 +382,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
}
private static @Nullable PsiCaseLabelElement findNullLabel(@NotNull List<? extends PsiCaseLabelElement> expressions) {
return ContainerUtil.find(expressions, label -> label instanceof PsiExpression literal && TypeConversionUtil.isNullType(literal.getType()));
return ContainerUtil.find(expressions,
label -> label instanceof PsiExpression literal && TypeConversionUtil.isNullType(literal.getType()));
}
private static final class ReturningSwitchReplacer implements SwitchReplacer {
@@ -457,13 +465,13 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
*/
private static @Nullable SwitchReplacer inspectReturningSwitch(@NotNull PsiStatement statement,
@NotNull List<OldSwitchStatementBranch> branches,
boolean isExhaustive, int maxNumberStatementsForExpression) {
@NotNull List<OldSwitchStatementBranch> branches,
boolean isExhaustive, int maxNumberStatementsForExpression) {
PsiReturnStatement returnAfterSwitch =
tryCast(PsiTreeUtil.getNextSiblingOfType(statement, PsiStatement.class), PsiReturnStatement.class);
PsiThrowStatement throwAfterSwitch =
tryCast(PsiTreeUtil.getNextSiblingOfType(statement, PsiStatement.class), PsiThrowStatement.class);
if (returnAfterSwitch == null && throwAfterSwitch==null && !isExhaustive) return null;
if (returnAfterSwitch == null && throwAfterSwitch == null && !isExhaustive) return null;
List<SwitchBranch> newBranches = new ArrayList<>();
boolean hasReturningBranch = false;
boolean isInfo = false;
@@ -500,7 +508,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
}
int lastIndex = statements.length - 1;
if (ContainerUtil.exists(statements,
st -> !PsiTreeUtil.findChildrenOfAnyType(st, PsiContinueStatement.class, PsiBreakStatement.class, PsiYieldStatement.class).isEmpty())) {
st -> !PsiTreeUtil.findChildrenOfAnyType(st, PsiContinueStatement.class, PsiBreakStatement.class,
PsiYieldStatement.class).isEmpty())) {
return null;
}
PsiReturnStatement returnStmt = tryCast(statements[lastIndex], PsiReturnStatement.class);
@@ -595,7 +604,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
private static @NotNull PsiStatement createYieldStatement(@NotNull PsiExpression expr) {
Project project = expr.getProject();
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
return factory.createStatementFromText("yield " + StringUtil.trim(expr.getText()) + ";", expr);
return factory.createStatementFromText("yield " + StringUtil.trim(expr.getText()) + ";", expr);
}
private static final class SwitchExistingVariableReplacer implements SwitchReplacer {
@@ -637,7 +646,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
PsiSwitchBlock replacement = generateEnhancedSwitch(switchStatement, myNewBranches, commentTracker, true);
if (replacement == null) return;
PsiExpression initializer = myVariableToAssign.getInitializer();
if (myIsRightAfterDeclaration && isNotUsed(myVariableToAssign, switchStatement)) {
if (myIsRightAfterDeclaration &&
(isNotUsed(myVariableToAssign, switchStatement) && isNotUsed(myVariableToAssign, replacement))) {
if (initializer != null) {
List<PsiExpression> sideEffectExpressions = SideEffectChecker.extractSideEffectExpressions(initializer);
PsiStatement[] sideEffectStatements = StatementExtractor.generateStatements(sideEffectExpressions, initializer);
@@ -661,10 +671,10 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
}
}
private static boolean isNotUsed(@NotNull PsiVariable variable, @NotNull PsiStatement switchStatement) {
private static boolean isNotUsed(@NotNull PsiVariable variable, @NotNull PsiElement switchElement) {
try {
ControlFlow controlFlow = ControlFlowFactory
.getControlFlow(switchStatement, AllVariablesControlFlowPolicy.getInstance(), ControlFlowOptions.NO_CONST_EVALUATE);
.getControlFlow(switchElement, AllVariablesControlFlowPolicy.getInstance(), ControlFlowOptions.NO_CONST_EVALUATE);
List<PsiReferenceExpression> references = ControlFlowUtil.getReadBeforeWrite(controlFlow);
for (PsiReferenceExpression reference : references) {
if (reference != null && reference.resolve() == variable) {
@@ -695,8 +705,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
* </pre>
*/
private static @Nullable SwitchReplacer inspectVariableAssigningSwitch(@NotNull PsiStatement statement,
@NotNull List<OldSwitchStatementBranch> branches,
boolean isExhaustive, int maxNumberStatementsForExpression) {
@NotNull List<OldSwitchStatementBranch> branches,
boolean isExhaustive, int maxNumberStatementsForExpression) {
PsiElement parent = statement.getParent();
PsiElement anchor = parent instanceof PsiLabeledStatement ? parent : statement;
PsiLocalVariable assignedVariable = null;
@@ -777,7 +787,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
return null;
}
}
return new SwitchExistingVariableReplacer(assignedVariable, statement, newBranches, isRightAfterDeclaration, isInfo, maxNumberStatementsInBranch);
return new SwitchExistingVariableReplacer(assignedVariable, statement, newBranches, isRightAfterDeclaration, isInfo,
maxNumberStatementsInBranch);
}
private static boolean existsDefaultLabelElement(@NotNull PsiSwitchLabelStatement statement) {
@@ -795,10 +806,11 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
return SwitchBranch.createDefault(new SwitchRuleExpressionResult(initializer));
}
PsiDeclarationStatement declaration = tryCast(assignedVariable.getParent(), PsiDeclarationStatement.class);
if (declaration == null || declaration.getParent()==null) return null;
if (declaration == null || declaration.getParent() == null) return null;
try {
final LocalsOrMyInstanceFieldsControlFlowPolicy policy = LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance();
final ControlFlow controlFlow = ControlFlowFactory.getInstance(declaration.getProject()).getControlFlow(declaration.getParent(), policy);
final ControlFlow controlFlow =
ControlFlowFactory.getInstance(declaration.getProject()).getControlFlow(declaration.getParent(), policy);
final int switchStart = controlFlow.getStartOffset(statement);
if (switchStart <= 0) {
return null;
@@ -818,7 +830,8 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
}
private static boolean isRightAfterDeclaration(PsiElement anchor, PsiVariable assignedVariable) {
PsiDeclarationStatement declaration = tryCast(PsiTreeUtil.getPrevSiblingOfType(anchor, PsiStatement.class), PsiDeclarationStatement.class);
PsiDeclarationStatement declaration =
tryCast(PsiTreeUtil.getPrevSiblingOfType(anchor, PsiStatement.class), PsiDeclarationStatement.class);
if (declaration != null) {
PsiElement[] elements = declaration.getDeclaredElements();
if (elements.length == 1) {
@@ -872,7 +885,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
* Suggest replacement with an enhanced switch statement
*/
private static @Nullable SwitchReplacer inspectReplacementWithStatement(@NotNull PsiStatement statement,
@NotNull List<OldSwitchStatementBranch> branches) {
@NotNull List<OldSwitchStatementBranch> branches) {
for (int i = 0, size = branches.size(); i < size; i++) {
OldSwitchStatementBranch branch = branches.get(i);
if (!isConvertibleBranch(branch, i != size - 1) &&
@@ -914,12 +927,13 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
private final @Nullable PsiStatement @Nullable [] myOriginalResultStatements;
private SwitchStatementBranch(@Nullable PsiStatement @Nullable[] resultStatements) {
private SwitchStatementBranch(@Nullable PsiStatement @Nullable [] resultStatements) {
myResultStatements = resultStatements;
myOriginalResultStatements = null;
}
private SwitchStatementBranch(@Nullable PsiStatement @Nullable[] resultStatements, @Nullable PsiStatement @Nullable[] originalResultStatements) {
private SwitchStatementBranch(@Nullable PsiStatement @Nullable [] resultStatements,
@Nullable PsiStatement @Nullable [] originalResultStatements) {
myResultStatements = resultStatements;
myOriginalResultStatements = originalResultStatements;
}
@@ -927,7 +941,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
@Override
public String generate(CommentTracker ct, SwitchBranch branch) {
@Nullable PsiStatement @Nullable [] resultStatements = myResultStatements;
if(resultStatements == null) return "";
if (resultStatements == null) return "";
if (resultStatements.length == 1) {
PsiStatement first = resultStatements[0];
if (first instanceof PsiExpressionStatement || first instanceof PsiBlockStatement || first instanceof PsiThrowStatement) {
@@ -940,7 +954,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
if (element == null) continue;
if (i == 0) {
PsiElement current = getElementForComments(element, i);
if(current != null) {
if (current != null) {
current = current.getPrevSibling();
}
while (current instanceof PsiWhiteSpace || current instanceof PsiComment) {
@@ -970,7 +984,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
private static void addNewLine(@NotNull StringBuilder sb) {
String string = sb.toString();
String trimmed = string.trim();
if(!string.substring(trimmed.length()).contains("\n")) {
if (!string.substring(trimmed.length()).contains("\n")) {
sb.append("\n");
}
}
@@ -1192,7 +1206,7 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
public @Nullable PsiExpression getGuardExpression() {
return myLabelStatement.getGuardExpression();
}
private List<PsiCaseLabelElement> getCaseLabelElements() {
List<OldSwitchStatementBranch> branches = getWithFallthroughBranches();
Collections.reverse(branches);
@@ -0,0 +1,15 @@
// "Replace with 'switch' expression" "true-preview"
public final class A {
private void appendColored(String text) {
String style = getRegularAttributes();
style = switch (text) {
case "failed" -> "ERROR_ATTRIBUTES";
case "ignored" -> "IGNORE_ATTRIBUTES";
default -> style;
};
}
private static String getRegularAttributes() {
return "REGULAR_ATTRIBUTES";
}
}
@@ -0,0 +1,18 @@
// "Replace with 'switch' expression" "true-preview"
public final class A {
private void appendColored(String text) {
String style = getRegularAttributes();
switc<caret>h (text) {
case "failed":
style = "ERROR_ATTRIBUTES";
break;
case "ignored":
style = "IGNORE_ATTRIBUTES";
break;
}
}
private static String getRegularAttributes() {
return "REGULAR_ATTRIBUTES";
}
}