[java-inspections] IDEA-311650 Improvements to conversion of if-else to switch that use guarded patterns

- check guards to reuse pattern variables

GitOrigin-RevId: f09354cfa0dd3f58f154de372b56bc100a461322
This commit is contained in:
Mikhail Pyltsin
2023-10-31 18:43:41 +01:00
committed by intellij-monorepo-bot
parent 3d7a18e986
commit 6c45f6a32e
4 changed files with 76 additions and 10 deletions

View File

@@ -4,7 +4,10 @@ package com.siyeh.ig.migration;
import com.intellij.codeInsight.Nullability;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.CommonQuickFixBundle;
import com.intellij.codeInspection.EnhancedSwitchMigrationInspection;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.dataFlow.NullabilityUtil;
import com.intellij.codeInspection.options.OptPane;
import com.intellij.codeInspection.util.IntentionFamilyName;
@@ -32,10 +35,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
public class IfCanBeSwitchInspection extends BaseInspection {
@@ -133,12 +133,9 @@ public class IfCanBeSwitchInspection extends BaseInspection {
PsiTypeElement type = targetInstanceOf.getCheckType();
if (type == null) return;
List<PsiTypeCastExpression> relatedCastExpressions =
SyntaxTraverser.psiTraverser(ifStatement.getThenBranch())
.filter(PsiTypeCastExpression.class)
.filter(cast -> InstanceOfUtils.findPatternCandidate(cast) == targetInstanceOf)
.toList();
List<PsiTypeCastExpression> relatedCastExpressions = new ArrayList<>(getRelatesCastExpressions(ifStatement.getThenBranch(), targetInstanceOf));
processConditions(ifStatement, targetInstanceOf, relatedCastExpressions);
PsiLocalVariable castedVariable = null;
for (PsiTypeCastExpression castExpression : relatedCastExpressions) {
castedVariable = findCastedLocalVariable(castExpression);
@@ -162,6 +159,39 @@ public class IfCanBeSwitchInspection extends BaseInspection {
);
}
private static void processConditions(PsiIfStatement ifStatement,
PsiInstanceOfExpression targetInstanceOf,
List<PsiTypeCastExpression> relatedCastExpressions) {
PsiElement current = targetInstanceOf;
while (true) {
PsiElement parent = current.getParent();
if (parent == null || parent == ifStatement) {
break;
}
if (!(parent instanceof PsiPolyadicExpression polyadicExpression) ||
polyadicExpression.getOperationTokenType() != JavaTokenType.ANDAND) {
break;
}
PsiExpression[] operands = polyadicExpression.getOperands();
int index = Arrays.asList(operands).indexOf(current);
if (index == -1 || index == operands.length - 1) {
break;
}
for (int i = index; i < operands.length; i++) {
relatedCastExpressions.addAll(getRelatesCastExpressions(operands[i], targetInstanceOf));
}
current = parent;
}
}
@NotNull
private static List<PsiTypeCastExpression> getRelatesCastExpressions(PsiElement expression, PsiInstanceOfExpression targetInstanceOf) {
return SyntaxTraverser.psiTraverser(expression)
.filter(PsiTypeCastExpression.class)
.filter(cast -> InstanceOfUtils.findPatternCandidate(cast) == targetInstanceOf)
.toList();
}
private static @Nullable PsiLocalVariable findCastedLocalVariable(PsiTypeCastExpression castExpression) {
PsiLocalVariable variable = PsiTreeUtil.getParentOfType(castExpression, PsiLocalVariable.class);
if (variable == null) return null;

View File

@@ -0,0 +1,15 @@
package com.siyeh.ipp.switchtoif.replace_if_with_switch;
import java.math.BigDecimal;
public class Test {
String getText(Object object) {
final String result = switch (object) {
case String s when (s.startsWith("PU") || s.startsWith("PU1")) -> s;
case Character c -> "Tuesday";
case null, default -> "Sunday";
};<caret>
return result;
}
}

View File

@@ -0,0 +1,20 @@
package com.siyeh.ipp.switchtoif.replace_if_with_switch;
import java.math.BigDecimal;
public class Test {
String getText(Object object) {
final String result;
i<caret>f (object instanceof String && (((String)object).startsWith("PU") || ((String)object).startsWith("PU1"))) {
result = (String)object;
}
else if (object instanceof Character) {
result = "Tuesday";
}
else {
result = "Sunday";
}
return result;
}
}

View File

@@ -49,4 +49,5 @@ public class IfCanBePatternSwitchFixTest extends IGQuickFixesTestCase {
public void testLeakScope() { assertQuickfixNotAvailable(); }
public void testNullCast() { doTest(); }
public void testNotDoubleCall() { doTest(); }
public void testWhenCast() { doTest(); }
}