diff --git a/java/java-impl/src/com/intellij/codeInspection/EnhancedSwitchMigrationInspection.java b/java/java-impl/src/com/intellij/codeInspection/EnhancedSwitchMigrationInspection.java index 57b6c04f9aed..7cf3d4346297 100644 --- a/java/java-impl/src/com/intellij/codeInspection/EnhancedSwitchMigrationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/EnhancedSwitchMigrationInspection.java @@ -5,7 +5,6 @@ import com.intellij.codeInsight.BlockUtils; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.siyeh.ig.psiutils.*; @@ -39,37 +38,14 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp "inspection.switch.expression.migration.inspection.switch.description"), new ReplaceWithSwitchExpressionFix(replacer.getType())); } - - @Override - public void visitIfStatement(PsiIfStatement statement) { - SwitchReplacer replacer = getIfReplacer(statement); - if (replacer == null) return; - PsiElement switchKeyword = statement.getFirstChild(); - holder.registerProblem(switchKeyword, - InspectionsBundle.message("inspection.switch.expression.migration.inspection.if.name"), - ProblemHighlightType.INFORMATION, - new ReplaceWithSwitchExpressionFix(replacer.getType()) - ); - } }; } - private static SwitchReplacer getIfReplacer(PsiIfStatement statement) { - PsiExpression condition = statement.getCondition(); - if (condition == null) return null; - boolean isExhaustive = statement.getElseBranch() != null; - ConstantCheck constantCheck = extractAsEqCheck(statement.getCondition()); - if (constantCheck == null) return null; - List branches = getIfBranches(statement, constantCheck); - if (branches == null) return null; - return runInspections(statement, constantCheck.myExpressionBeingChecked, isExhaustive, branches); - } - @Nullable private static SwitchReplacer runInspections(PsiStatement statement, PsiExpression condition, boolean isExhaustive, - List branches) { + List branches) { for (SwitchInspection inspection : ourInspections) { SwitchReplacer replacer = inspection.suggestReplacer(statement, condition, branches, isExhaustive); if (replacer != null) return replacer; @@ -77,54 +53,6 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp return null; } - private static List getIfBranches(PsiIfStatement ifStatement, ConstantCheck constantCheck) { - IfBranchSource thenBranch = getBranch(ifStatement.getThenBranch(), constantCheck.myIsInverted ? null : constantCheck.myValue); - if (thenBranch == null) return null; - IfBranchSource elseBranch = getBranch(ifStatement.getElseBranch(), constantCheck.myIsInverted ? constantCheck.myValue : null); - if (elseBranch == null) { - if (thenBranch.isDefault()) return null; - return Collections.singletonList(thenBranch); - } - return Arrays.asList(thenBranch, elseBranch); - } - - @Nullable - private static IfBranchSource getBranch(PsiStatement branch, @Nullable PsiExpression caseValue) { - if (branch == null) return null; - PsiStatement[] statements = ControlFlowUtils.unwrapBlock(branch); - if (statements.length == 0) return null; - return new IfBranchSource(statements, branch, caseValue); - } - - @Nullable - private static ConstantCheck extractAsEqCheck(@Nullable PsiExpression expression) { - PsiBinaryExpression binaryExpression = tryCast(expression, PsiBinaryExpression.class); - if (binaryExpression == null) return null; - boolean isInverted; - IElementType tokenType = binaryExpression.getOperationTokenType(); - if (tokenType.equals(JavaTokenType.EQEQ)) { - isInverted = false; - } - else if (tokenType.equals(JavaTokenType.NE)) { - isInverted = true; - } - else { - return null; - } - PsiExpression rOperand = binaryExpression.getROperand(); - PsiExpression lOperand = binaryExpression.getLOperand(); - if (rOperand == null) return null; - if (ExpressionUtils.computeConstantExpression(lOperand) != null) { - return new ConstantCheck(lOperand, rOperand, isInverted); - } - else if (ExpressionUtils.computeConstantExpression(rOperand) != null) { - return new ConstantCheck(rOperand, lOperand, isInverted); - } - else { - return null; - } - } - private static OldSwitchStatementBranch addBranch(List branches, PsiStatement[] statements, int unmatchedCaseIndex, @@ -201,23 +129,11 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp boolean isExpr) { PsiElementFactory factory = JavaPsiFacade.getInstance(statementToReplace.getProject()).getElementFactory(); mainCommentTracker.markUnchanged(expressionBeingSwitched); - if (statementToReplace instanceof PsiSwitchStatement) { - PsiCodeBlock body = ((PsiSwitchStatement)statementToReplace).getBody(); - if (body == null) return null; - for (PsiStatement statement : body.getStatements()) { - mainCommentTracker.markUnchanged(statement); - } - } - else if (statementToReplace instanceof PsiIfStatement) { - PsiIfStatement ifStatement = (PsiIfStatement)statementToReplace; - markUnchangedBranch(mainCommentTracker, ifStatement.getThenBranch()); - markUnchangedBranch(mainCommentTracker, ifStatement.getElseBranch()); - ConstantCheck constantCheck = extractAsEqCheck(ifStatement.getCondition()); - if (constantCheck == null) return null; - mainCommentTracker.markUnchanged(constantCheck.myValue); - } - else { - return null; + if (!(statementToReplace instanceof PsiSwitchStatement)) return null; + PsiCodeBlock body = ((PsiSwitchStatement)statementToReplace).getBody(); + if (body == null) return null; + for (PsiStatement statement : body.getStatements()) { + mainCommentTracker.markUnchanged(statement); } StringBuilder sb = new StringBuilder() @@ -254,14 +170,8 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp return switchBlock; } - private static void markUnchangedBranch(CommentTracker mainCommentTracker, PsiStatement thenBranch) { - for (PsiStatement statement : ControlFlowUtils.unwrapBlock(thenBranch)) { - mainCommentTracker.markUnchanged(statement); - } - } - private static boolean isExhaustiveSwitch(List branches, PsiExpression expressionBeingSwitched) { - for (SwitchBranchSource branch : branches) { + for (OldSwitchStatementBranch branch : branches) { if (branch.isDefault()) return true; } final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(expressionBeingSwitched.getType()); @@ -270,7 +180,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp .select(PsiEnumConstant.class) .map(PsiEnumConstant::getName) .toSet(); - for (SwitchBranchSource branch : branches) { + for (OldSwitchStatementBranch branch : branches) { for (PsiExpression caseValue : branch.getCurrentBranchCaseExpressions()) { PsiReferenceExpression reference = tryCast(caseValue, PsiReferenceExpression.class); if (reference != null) { @@ -284,7 +194,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp return names.isEmpty(); } - private static boolean isConvertibleBranch(SwitchBranchSource branch) { + private static boolean isConvertibleBranch(OldSwitchStatementBranch branch) { int length = branch.getStatements().length; if (length == 0) return branch.isFallthrough(); return length == 1 && !branch.isFallthrough(); @@ -315,7 +225,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp @Nullable SwitchReplacer suggestReplacer(@NotNull PsiStatement statement, @NotNull PsiExpression expressionBeingSwitched, - @NotNull List branches, + @NotNull List branches, boolean isExhaustive ); } @@ -325,43 +235,6 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp String generate(CommentTracker ct); } - private interface SwitchBranchSource { - - List getCurrentBranchCaseExpressions(); - - boolean isDefault(); - - boolean isFallthrough(); - - PsiStatement[] getStatements(); - - /** - * @return all case expressions, also for fallthrough branches - */ - StreamEx getCaseExpressions(); - - /** - * @return elements, that were used in generation (used to avoid comment duplication) - */ - StreamEx getUsedElements(); - - /** - * all statements related to this branch, used to extract comments and place it near this branch - */ - StreamEx getRelatedStatements(); - } - - private static class ConstantCheck { - final @NotNull PsiExpression myValue; - final @NotNull PsiExpression myExpressionBeingChecked; - final boolean myIsInverted; - - private ConstantCheck(@NotNull PsiExpression value, @NotNull PsiExpression expressionBeingChecked, boolean isInverted) { - myValue = value; - myExpressionBeingChecked = expressionBeingChecked; - myIsInverted = isInverted; - } - } static class ReplaceWithSwitchExpressionFix implements LocalQuickFix { private final ReplacementType myReplacementType; @@ -377,15 +250,10 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - PsiStatement statement = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiSwitchStatement.class, PsiIfStatement.class); + PsiSwitchStatement statement = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiSwitchStatement.class); if (statement == null) return; SwitchReplacer replacer; - if (statement instanceof PsiIfStatement) { - replacer = getIfReplacer((PsiIfStatement)statement); - } - else { - replacer = getSwitchReplacer((PsiSwitchStatement)statement); - } + replacer = getSwitchReplacer(statement); if (replacer == null) return; replacer.replace(statement); } @@ -445,13 +313,13 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp @Override public SwitchReplacer suggestReplacer(@NotNull PsiStatement statement, @NotNull PsiExpression expressionBeingSwitched, - @NotNull List branches, + @NotNull List branches, boolean isExhaustive) { PsiReturnStatement returnAfterSwitch = tryCast(PsiTreeUtil.getNextSiblingOfType(statement, PsiStatement.class), PsiReturnStatement.class); if (returnAfterSwitch == null && !isExhaustive) return null; List newBranches = new ArrayList<>(); - for (SwitchBranchSource branch : branches) { + for (OldSwitchStatementBranch branch : branches) { if (!isConvertibleBranch(branch)) return null; if (branch.isFallthrough() && branch.getStatements().length == 0) continue; PsiStatement[] statements = branch.getStatements(); @@ -533,7 +401,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp @Override public SwitchReplacer suggestReplacer(@NotNull PsiStatement statement, @NotNull PsiExpression expressionBeingSwitched, - @NotNull List branches, + @NotNull List branches, boolean isExhaustive) { PsiDeclarationStatement declaration = tryCast(PsiTreeUtil.getPrevSiblingOfType(statement, PsiStatement.class), PsiDeclarationStatement.class); @@ -542,7 +410,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp List newBranches = new ArrayList<>(); PsiExpression initializer = variable.getInitializer(); if (!isExhaustive && initializer == null) return null; - for (SwitchBranchSource branch : branches) { + for (OldSwitchStatementBranch branch : branches) { if (!isConvertibleBranch(branch)) return null; if (branch.isFallthrough() && branch.getStatements().length == 0) continue; PsiExpression rExpression = ExpressionUtils.getAssignmentTo(branch.getStatements()[0], variable); @@ -600,14 +468,14 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp @Override public SwitchReplacer suggestReplacer(@NotNull PsiStatement statement, @NotNull PsiExpression expressionBeingSwitched, - @NotNull List branches, + @NotNull List branches, boolean isExhaustive) { - for (SwitchBranchSource branch : branches) { + for (OldSwitchStatementBranch branch : branches) { if (!isConvertibleBranch(branch)) return null; } List switchRules = new ArrayList<>(); for (int i = 0, branchesSize = branches.size(); i < branchesSize; i++) { - SwitchBranchSource branch = branches.get(i); + OldSwitchStatementBranch branch = branches.get(i); if (branch.isFallthrough() && branch.getStatements().length == 0) continue; boolean allBranchRefsWillBeValid = StreamEx.of(branch.getStatements()) .limit(i) // only previous branches @@ -627,7 +495,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp } private static boolean isInBranchOrOutside(@NotNull PsiStatement switchStmt, - SwitchBranchSource branch, PsiLocalVariable variable) { + OldSwitchStatementBranch branch, PsiLocalVariable variable) { return !PsiTreeUtil.isAncestor(switchStmt, variable, false) || StreamEx.of(branch.getStatements()).anyMatch(stmt -> PsiTreeUtil.isAncestor(stmt, variable, false)); } @@ -698,7 +566,7 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp } } - private static class OldSwitchStatementBranch implements SwitchBranchSource { + private static class OldSwitchStatementBranch { final boolean myIsFallthrough; final @NotNull PsiStatement[] myStatements; final @NotNull PsiSwitchLabelStatement myLabelStatement; @@ -715,18 +583,15 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp myBreakStatement = breakStatement; } - @Override public boolean isDefault() { return myLabelStatement.isDefaultCase(); } - @Override public boolean isFallthrough() { return myIsFallthrough; } // Case expressions in code order, for all branches - @Override public StreamEx getCaseExpressions() { List branches = getWithFallthroughBranches(); Collections.reverse(branches); @@ -737,7 +602,6 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp }); } - @Override public List getCurrentBranchCaseExpressions() { PsiExpressionList caseValues = myLabelStatement.getCaseValues(); if (caseValues == null) { @@ -749,12 +613,10 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp /** * @return only meaningful statements, without break and case statements */ - @Override public PsiStatement[] getStatements() { return myStatements; } - @Override public StreamEx getRelatedStatements() { StreamEx withoutBreak = StreamEx.of(myStatements).prepend(myLabelStatement); return withoutBreak.prepend(myBreakStatement); @@ -772,60 +634,8 @@ public class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLocalInsp } } - @Override public StreamEx getUsedElements() { return StreamEx.of(getWithFallthroughBranches()).flatMap(branch -> branch.getRelatedStatements()); } } - - - // Considering 'if' as a form of 'switch' with 2 branches - private static class IfBranchSource implements SwitchBranchSource { - @NotNull private final PsiStatement[] myStatements; - @NotNull private final PsiStatement myBranch; - @Nullable private final PsiExpression myCondition; - - - private IfBranchSource(@NotNull PsiStatement[] statements, @NotNull PsiStatement branch, @Nullable PsiExpression condition) { - myStatements = statements; - myBranch = branch; - myCondition = condition; - } - - - @Override - public List getCurrentBranchCaseExpressions() { - return myCondition == null ? Collections.emptyList() : Collections.singletonList(myCondition); - } - - @Override - public boolean isDefault() { - return myCondition == null; - } - - @Override - public boolean isFallthrough() { - return false; - } - - @Override - public PsiStatement[] getStatements() { - return myStatements; - } - - @Override - public StreamEx getCaseExpressions() { - return StreamEx.ofNullable(myCondition); - } - - @Override - public StreamEx getUsedElements() { - return StreamEx.of(myStatements); - } - - @Override - public StreamEx getRelatedStatements() { - return StreamEx.of(myBranch); - } - } } diff --git a/java/java-impl/src/inspectionDescriptions/EnhancedSwitchMigration.html b/java/java-impl/src/inspectionDescriptions/EnhancedSwitchMigration.html index ca34b5ccd9b9..7904bfd562fa 100644 --- a/java/java-impl/src/inspectionDescriptions/EnhancedSwitchMigration.html +++ b/java/java-impl/src/inspectionDescriptions/EnhancedSwitchMigration.html @@ -1,6 +1,8 @@ -Reports 'switch' and 'if' statements, which can be replaced with enhanced 'switch' statement or expression +Reports 'switch' and 'if' statements, which can be replaced with enhanced 'switch' statement or expression. + +

Available if the language level is at least Java 12 Preview.

New in 2019.1

diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/afterIf.java b/java/java-tests/testData/inspection/switchExpressionMigration/afterIf.java deleted file mode 100644 index addc839d6ef8..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/afterIf.java +++ /dev/null @@ -1,35 +0,0 @@ -// "Fix all 'Statement can be replaced with enhanced 'switch'' problems in file" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m1(int n, String s) { - String v = switch (n) { - case 0 -> "foo"; - default -> "bar"; - }; - return v; - } - - private static String m2(int n, String s) { - String v = switch (n) { - default -> "foo"; - case 0 -> "bar"; - }; - return v; - } - - private static String m3(int n, String s) { - return switch (n) { - default -> "foo"; - case 0 -> "bar"; - }; - } - - private static String m3(int n, String s) { - System.currentTimeMillis(); - long l = switch (n) { - default -> 12l; - case 0 -> 22l; - }; - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithReturn.java b/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithReturn.java deleted file mode 100644 index 6a50d34a6ffb..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithReturn.java +++ /dev/null @@ -1,22 +0,0 @@ -// "Replace with 'switch' expression" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m(int n) { - /*1*/ - /*2*/ - /*3*/ - /*4*/ - /*5*/ - /*7*/ - /*8*/ - /*9*/ - return switch (n) { - /*6*/ - case 0 +/*cond*/ 1 -> "foo"; - /*10*/ - /*11*/ - default -> "bar"; - }; - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithReturnNoElse.java b/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithReturnNoElse.java deleted file mode 100644 index 5ff85c2dca26..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithReturnNoElse.java +++ /dev/null @@ -1,11 +0,0 @@ -// "Replace with 'switch' expression" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m(int n) { - return switch (n) { - case 0 -> "foo"; - default -> "bar"; - }; - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithVar.java b/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithVar.java deleted file mode 100644 index 139f66972a69..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/afterIfWithVar.java +++ /dev/null @@ -1,12 +0,0 @@ -// "Replace with 'switch' expression" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m(int n) { - String s = switch (n) { - case 0 -> "foo"; - default -> "bar"; - }; - return s; - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIf.java b/java/java-tests/testData/inspection/switchExpressionMigration/beforeIf.java deleted file mode 100644 index 7891600c1956..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIf.java +++ /dev/null @@ -1,41 +0,0 @@ -// "Fix all 'Statement can be replaced with enhanced 'switch'' problems in file" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m1(int n, String s) { - String v; - if(n == 0) { - v = "foo"; - } else { - v = "bar"; - } - return v; - } - - private static String m2(int n, String s) { - String v; - if(n != 0) { - v = "foo"; - } else { - v = "bar"; - } - return v; - } - - private static String m3(int n, String s) { - if(n != 0) { - return "foo"; - } else { - return "bar"; - } - } - - private static String m3(int n, String s) { - long l = System.currentTimeMillis(); - if(n != 0) { - l = 12l; - } else { - l = 22l; - } - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithReturn.java b/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithReturn.java deleted file mode 100644 index 982a82cce49f..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithReturn.java +++ /dev/null @@ -1,12 +0,0 @@ -// "Replace with 'switch' expression" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m(int n) { - if/*1*/(n /*2*/== 0 +/*cond*/ 1) /*3*/ { /*4*/ - /*5*/return /*6*/ "foo"; - }/*7*/ else/*8*/ {/*9*/ - return/*10*/ "bar"/*11*/; - } - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithReturnNoElse.java b/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithReturnNoElse.java deleted file mode 100644 index 325bf023ae73..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithReturnNoElse.java +++ /dev/null @@ -1,11 +0,0 @@ -// "Replace with 'switch' expression" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m(int n) { - if(n == 0) { - return "foo"; - } - return "bar"; - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithVar.java b/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithVar.java deleted file mode 100644 index 07d54656d685..000000000000 --- a/java/java-tests/testData/inspection/switchExpressionMigration/beforeIfWithVar.java +++ /dev/null @@ -1,14 +0,0 @@ -// "Replace with 'switch' expression" "true" -import java.util.*; - -class SwitchExpressionMigration { - private static String m(int n) { - String s; - if(n == 0) { - s = "foo"; - } else { - s = "bar"; - } - return s; - } -} \ No newline at end of file