From e9fca7074fda79b5cfc85e888175b438e5847692 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Mon, 14 Jan 2019 16:57:13 +0300 Subject: [PATCH] Java: Highlight duplicate values and branches in enhanced 'switch' (IDEA-202629) --- .../DuplicateBranchesInSwitchInspection.java | 615 +++++++++++++++--- .../ExpressionParentheses.java | 9 + .../ReturnInStatement.java | 10 + .../SimpleExpression.java | 11 + .../SimpleStatement.java | 10 + .../StatementParentheses.java | 13 + .../ThrowInExpression.java | 10 + .../ThrowInStatement.java | 9 + .../afterComplexExpressionBranches.java | 27 + .../afterComplexStatementBranches.java | 26 + ...ExpressionDuplicateAfterDefaultDelete.java | 12 + ...xpressionDuplicateBeforeDefaultDelete.java | 10 + ...nDuplicateBeforeDefaultDeleteAdjacent.java | 10 + .../afterExpressionLeftoverComments.java | 14 + .../afterExpressionThreeDuplicates.java | 12 + .../afterExpressionThrow.java | 10 + .../afterSimpleExpression.java | 10 + .../afterSimpleStatement.java | 10 + ...rStatementDuplicateAfterDefaultDelete.java | 17 + ...StatementDuplicateBeforeDefaultDelete.java | 10 + ...tDuplicateBeforeDefaultDeleteAdjacent.java | 10 + .../afterStatementLeftoverComments.java | 14 + .../afterStatementMethodCallInReturn.java | 18 + .../afterStatementReturnUnderIf.java | 19 + .../afterStatementThreeDuplicates.java | 11 + ...StatementThreeDuplicatesDefaultDelete.java | 11 + .../afterStatementThrow.java | 9 + .../beforeComplexExpressionBranches.java | 36 + .../beforeComplexStatementBranches.java | 35 + ...ExpressionDuplicateAfterDefaultDelete.java | 15 + ...xpressionDuplicateBeforeDefaultDelete.java | 11 + ...nDuplicateBeforeDefaultDeleteAdjacent.java | 11 + .../beforeExpressionLeftoverComments.java | 17 + .../beforeExpressionThreeDuplicates.java | 13 + .../beforeExpressionThrow.java | 11 + .../beforeSimpleExpression.java | 11 + .../beforeSimpleStatement.java | 11 + ...eStatementDuplicateAfterDefaultDelete.java | 21 + ...StatementDuplicateBeforeDefaultDelete.java | 11 + ...tDuplicateBeforeDefaultDeleteAdjacent.java | 11 + .../beforeStatementLeftoverComments.java | 17 + .../beforeStatementMethodCallInReturn.java | 21 + .../beforeStatementReturnUnderIf.java | 24 + .../beforeStatementThreeDuplicates.java | 12 + ...StatementThreeDuplicatesDefaultDelete.java | 12 + .../beforeStatementThrow.java | 10 + .../afterBreakAndReturnUnderIf.java | 2 +- .../afterComplexBranches.java | 2 +- .../afterContinue.java | 2 +- .../afterFallThroughToBreak.java | 2 +- .../afterFallThroughToBreak2.java | 2 +- .../afterLeftoverComments.java | 2 +- .../afterManyComments.java | 2 +- .../afterMethodCallInReturn.java | 2 +- .../afterNoLastBreak.java | 2 +- .../afterReturn.java | 2 +- .../afterSameCommentAfterLabel.java | 2 +- .../afterSameCommentBeforeLabel.java | 2 +- .../afterSimple.java | 2 +- .../afterThreeDuplicates.java | 2 +- .../afterThrow.java | 2 +- .../afterTwoCaseLabels.java | 2 +- .../beforeBreakAndReturnUnderIf.java | 2 +- .../beforeComplexBranches.java | 2 +- .../beforeContinue.java | 2 +- .../beforeFallThroughToBreak.java | 2 +- .../beforeFallThroughToBreak2.java | 2 +- .../beforeLeftoverComments.java | 2 +- .../beforeManyComments.java | 2 +- .../beforeMethodCallInReturn.java | 2 +- .../beforeNoLastBreak.java | 2 +- .../beforeReturn.java | 2 +- .../beforeSameCommentAfterLabel.java | 2 +- .../beforeSameCommentBeforeLabel.java | 2 +- .../beforeSimple.java | 2 +- .../beforeThreeDuplicates.java | 2 +- .../beforeThrow.java | 2 +- .../beforeTwoCaseLabels.java | 2 +- ...uplicateBranchesInEnhancedSwitchFixTest.kt | 20 + .../DuplicateBranchesInEnhancedSwitchTest.kt | 35 + .../src/messages/InspectionsBundle.properties | 13 +- 81 files changed, 1248 insertions(+), 141 deletions(-) create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ExpressionParentheses.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ReturnInStatement.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleExpression.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleStatement.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/StatementParentheses.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInExpression.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInStatement.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexExpressionBranches.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexStatementBranches.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateAfterDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDeleteAdjacent.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionLeftoverComments.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThreeDuplicates.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThrow.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleExpression.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleStatement.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateAfterDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDeleteAdjacent.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementLeftoverComments.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementMethodCallInReturn.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementReturnUnderIf.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicates.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicatesDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThrow.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexExpressionBranches.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexStatementBranches.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateAfterDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDeleteAdjacent.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionLeftoverComments.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThreeDuplicates.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThrow.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleExpression.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleStatement.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateAfterDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDeleteAdjacent.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementLeftoverComments.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementMethodCallInReturn.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementReturnUnderIf.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicates.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicatesDefaultDelete.java create mode 100644 java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThrow.java create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchFixTest.kt create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchTest.kt diff --git a/java/java-impl/src/com/intellij/codeInspection/DuplicateBranchesInSwitchInspection.java b/java/java-impl/src/com/intellij/codeInspection/DuplicateBranchesInSwitchInspection.java index 224ebf8721d7..e430b1dc725a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/DuplicateBranchesInSwitchInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/DuplicateBranchesInSwitchInspection.java @@ -2,7 +2,10 @@ package com.intellij.codeInspection; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -13,6 +16,7 @@ import com.intellij.refactoring.util.duplicates.DuplicatesFinder; import com.intellij.refactoring.util.duplicates.Match; import com.intellij.refactoring.util.duplicates.ReturnValue; import com.intellij.util.ArrayUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.ControlFlowUtils; @@ -48,25 +52,44 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { public void visitSwitchStatement(PsiSwitchStatement switchStatement) { super.visitSwitchStatement(switchStatement); + if (isEnhancedSwitch(switchStatement)) { + visitEnhancedSwitch(switchStatement); + return; + } + for (List branches : collectProbablySimilarBranches(switchStatement)) { registerProblems(branches); } } - void registerProblems(List branches) { + @Override + public void visitSwitchExpression(PsiSwitchExpression switchExpression) { + super.visitSwitchExpression(switchExpression); + + visitEnhancedSwitch(switchExpression); + } + + private void visitEnhancedSwitch(@NotNull PsiSwitchBlock switchBlock) { + Collection> probablySimilarRules = collectProbablySimilarRules(switchBlock); + for (List rules : probablySimilarRules) { + registerProblems(rules); + } + } + + void registerProblems(List branches) { int size = branches.size(); if (size > 1) { boolean[] isDuplicate = new boolean[size]; - int defaultIndex = ContainerUtil.indexOf(branches, Branch::isDefault); + int defaultIndex = ContainerUtil.indexOf(branches, BranchBase::isDefault); if (defaultIndex >= 0) { - Branch defaultBranch = branches.get(defaultIndex); + BranchBase defaultBranch = branches.get(defaultIndex); for (int index = 0; index < size; index++) { if (index != defaultIndex) { - Branch branch = branches.get(index); + BranchBase branch = branches.get(index); if (areDuplicates(defaultBranch, branch)) { isDuplicate[index] = isDuplicate[defaultIndex] = true; - highlightDefaultDuplicate(branch.myStatements); + highlightDefaultDuplicate(branch); } } } @@ -75,39 +98,89 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { int compareCount = 0; for (int index = 0; index < size - 1; index++) { if (isDuplicate[index]) continue; - Branch branch = branches.get(index); + BranchBase branch = branches.get(index); for (int otherIndex = index + 1; otherIndex < size; otherIndex++) { if (isDuplicate[otherIndex]) continue; if (++compareCount > 200) return; // avoid quadratic loop over too large list, but at least try to do something in that case - Branch otherBranch = branches.get(otherIndex); + BranchBase otherBranch = branches.get(otherIndex); if (areDuplicates(branch, otherBranch)) { isDuplicate[otherIndex] = true; - highlightDuplicate(otherBranch.myStatements, branch.getSwitchLabelText()); + highlightDuplicate(otherBranch, branch); } } } } } - private void highlightDuplicate(@NotNull PsiStatement[] statements, String switchLabelText) { + private void highlightDuplicate(@NotNull BranchBase duplicate, @NotNull BranchBase original) { ProblemDescriptor descriptor = InspectionManager.getInstance(myHolder.getProject()) - .createProblemDescriptor(statements[0], statements[statements.length - 1], - InspectionsBundle.message("inspection.duplicate.branches.in.switch.message"), + .createProblemDescriptor(duplicate.getFirstStatement(), duplicate.getLastStatement(), + duplicate.getCaseBranchMessage(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, myHolder.isOnTheFly(), - switchLabelText != null ? new MergeBranchesFix(switchLabelText) : null); + original.newMergeCasesFix()); myHolder.registerProblem(descriptor); } - private void highlightDefaultDuplicate(PsiStatement[] statements) { + private void highlightDefaultDuplicate(BranchBase branch) { ProblemDescriptor descriptor = InspectionManager.getInstance(myHolder.getProject()) - .createProblemDescriptor(statements[0], statements[statements.length - 1], - InspectionsBundle.message("inspection.duplicate.branches.in.switch.redundant.message"), + .createProblemDescriptor(branch.getFirstStatement(), branch.getLastStatement(), + branch.getDefaultBranchMessage(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, myHolder.isOnTheFly(), - new DeleteRedundantBranchFix(), new MergeWithDefaultBranchFix()); + branch.newDeleteCaseFix(), branch.newMergeWithDefaultFix()); myHolder.registerProblem(descriptor); } + + private boolean isEnhancedSwitch(@NotNull PsiSwitchStatement switchStatement) { + PsiFile file = myHolder.getFile(); + if (file instanceof PsiJavaFile && ((PsiJavaFile)file).getLanguageLevel().isAtLeast(LanguageLevel.JDK_12_PREVIEW)) { + PsiCodeBlock body = switchStatement.getBody(); + if (body != null) { + for (PsiElement element = body.getFirstChild(); element != null; element = element.getNextSibling()) { + if (element instanceof PsiSwitchLabeledRuleStatement) { + return true; + } + if (element instanceof PsiSwitchLabelStatement) { + return false; + } + } + } + } + return false; + } + } + + @NotNull + private static Collection> collectProbablySimilarRules(@NotNull PsiSwitchBlock switchBlock) { + PsiCodeBlock switchBody = switchBlock.getBody(); + if (switchBody == null) { + return Collections.emptyList(); + } + + TIntObjectHashMap> rulesByHash = new TIntObjectHashMap<>(); + List commentTexts = new ArrayList<>(); + for (PsiElement element = switchBody.getFirstChild(); element != null; element = element.getNextSibling()) { + if (!(element instanceof PsiSwitchLabeledRuleStatement)) { + collectCommentTexts(element, commentTexts); + continue; + } + PsiSwitchLabeledRuleStatement ruleStatement = (PsiSwitchLabeledRuleStatement)element; + PsiStatement body = ruleStatement.getBody(); + if (body != null) { + collectCommentTexts(ruleStatement, commentTexts); + Rule rule = new Rule(ruleStatement, body, ArrayUtil.toStringArray(commentTexts)); + commentTexts.clear(); + int hash = rule.hash(); + List list = rulesByHash.get(hash); + if (list == null) rulesByHash.put(hash, list = new ArrayList<>()); + list.add(rule); + } + } + + Collection> result = new ArrayList<>(); + rulesByHash.forEachValue(result::add); // mini-hack: ArrayList.add() always returns true + return result; } @NotNull @@ -167,9 +240,9 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { return branch; } - static boolean areDuplicates(Branch branch, Branch otherBranch) { + static boolean areDuplicates(@NotNull BranchBase branch, @NotNull BranchBase otherBranch) { if (branch.isSimpleExit() != otherBranch.isSimpleExit() || - branch.canFallThrough() || otherBranch.canFallThrough() || + branch.canFallThrough() != otherBranch.canFallThrough() || branch.length() != otherBranch.length()) { return false; } @@ -178,7 +251,9 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { if (match != null) { Match otherMatch = otherBranch.match(branch); if (otherMatch != null) { - if (branch.isSimpleExit() && otherBranch.isSimpleExit() && !Arrays.equals(branch.myCommentTexts, otherBranch.myCommentTexts)) { + if (branch.isSimpleExit() && + otherBranch.isSimpleExit() && + !Arrays.equals(branch.getCommentTexts(), otherBranch.getCommentTexts())) { return false; } return ReturnValue.areEquivalent(match.getReturnValue(), otherMatch.getReturnValue()); @@ -199,6 +274,15 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { return statement instanceof PsiBreakStatement && ((PsiBreakStatement)statement).getLabelExpression() == null; } + @Contract("_,null -> false") + private static boolean isRedundantComment(@NotNull Set existingComments, @Nullable PsiElement element) { + if (element instanceof PsiComment) { + String text = getCommentText((PsiComment)element); + return text.isEmpty() || existingComments.contains(text); + } + return false; + } + private static class MergeBranchesFix implements LocalQuickFix { @NotNull private final String mySwitchLabelText; @@ -222,7 +306,7 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - FixContext context = new FixContext(); + BranchFixContext context = new BranchFixContext(); if (context.prepare(descriptor.getStartElement(), branch -> mySwitchLabelText.equals(branch.getSwitchLabelText()))) { context.moveBranchLabel(); context.deleteRedundantComments(); @@ -241,7 +325,7 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - FixContext context = new FixContext(); + BranchFixContext context = new BranchFixContext(); if (context.prepare(descriptor.getStartElement(), Branch::isDefault)) { context.moveBranchLabel(); context.deleteRedundantComments(); @@ -267,7 +351,7 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - FixContext context = new FixContext(); + BranchFixContext context = new BranchFixContext(); if (context.prepare(descriptor.getStartElement(), Branch::isDefault)) { context.deleteBranchLabel(); context.deleteStatements(); @@ -275,7 +359,7 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { } } - static class FixContext { + static class BranchFixContext { private Branch myBranchToDelete; private Branch myBranchToMergeWith; private List myBranchPrefixToMove; @@ -313,7 +397,7 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { myNextFromLabelToMergeWith = PsiTreeUtil.skipWhitespacesForward(myLabelToMergeWith); - myCommentsToMergeWith = ContainerUtil.set(myBranchToMergeWith.myCommentTexts); + myCommentsToMergeWith = ContainerUtil.set(myBranchToMergeWith.getCommentTexts()); return true; } @@ -362,15 +446,6 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { redundantComments.forEach(PsiElement::delete); } - @Contract("_,null -> false") - private static boolean isRedundantComment(@NotNull Set existingComments, @Nullable PsiElement element) { - if (element instanceof PsiComment) { - String text = getCommentText((PsiComment)element); - return text.isEmpty() || existingComments.contains(text); - } - return false; - } - void deleteBranchLabel() { List toDelete = new ArrayList<>(); CommentTracker tracker = new CommentTracker(); @@ -397,54 +472,94 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { } } - private static class Branch { - private final PsiStatement[] myStatements; + private static abstract class BranchBase { private final String[] myCommentTexts; - private final boolean myIsDefault; - private final boolean myIsSimpleExit; - private final boolean myCanFallThrough; - private DuplicatesFinder myFinder; - Branch(@NotNull List statementList, boolean hasImplicitBreak, @NotNull String[] commentTexts) { - int lastIndex = statementList.size() - 1; - PsiStatement lastStatement = statementList.get(lastIndex); - myCanFallThrough = !hasImplicitBreak && ControlFlowUtils.statementMayCompleteNormally(lastStatement); - myIsSimpleExit = lastIndex == 0 && isSimpleExit(lastStatement); - if (lastIndex > 0 && isBreakWithoutLabel(lastStatement)) { - statementList = statementList.subList(0, lastIndex); // trailing 'break' is already taken into account in myCanFallThrough - } - myStatements = statementList.toArray(PsiStatement.EMPTY_ARRAY); + BranchBase(@NotNull String[] commentTexts) { myCommentTexts = commentTexts; - myIsDefault = calculateIsDefault(statementList.get(0)); + } + + abstract boolean isDefault(); + + @NotNull + abstract PsiStatement[] getStatements(); + + @Nullable + abstract String getSwitchLabelText(); + + abstract boolean isSimpleExit(); + + abstract boolean canFallThrough(); + + abstract int length(); + + String[] getCommentTexts() { + return myCommentTexts; + } + + abstract PsiStatement getFirstStatement(); + + abstract PsiStatement getLastStatement(); + + @Nullable + abstract LocalQuickFix newMergeCasesFix(); + + abstract LocalQuickFix newDeleteCaseFix(); + + abstract LocalQuickFix newMergeWithDefaultFix(); + + @Nullable + Match match(BranchBase other) { + return getFinder().isDuplicate(other.getFirstStatement(), true); + } + + @NotNull + private DuplicatesFinder getFinder() { + if (myFinder == null) { + myFinder = createFinder(getStatements()); + } + return myFinder; + } + + String getCaseBranchMessage() { + return InspectionsBundle.message("inspection.duplicate.branches.in.switch.statement.message"); + } + + String getDefaultBranchMessage() { + return InspectionsBundle.message("inspection.duplicate.branches.in.switch.statement.default.message"); + } + + @Override + public String toString() { + return StringUtil.notNullize(getSwitchLabelText()); + } + + @NotNull + private static DuplicatesFinder createFinder(@NotNull PsiStatement[] statements) { + Project project = statements[0].getProject(); + InputVariables noVariables = new InputVariables(Collections.emptyList(), project, new LocalSearchScope(statements), false); + return new DuplicatesFinder(statements, noVariables, null, Collections.emptyList()); } @Nullable - Match match(Branch other) { - return getFinder().isDuplicate(other.myStatements[0], true); - } - - boolean canFallThrough() { - return myCanFallThrough; - } - - boolean isSimpleExit() { - return myIsSimpleExit; - } - - int length() { - return myStatements.length; - } - - int hash() { - int hash = myStatements.length; - for (PsiStatement statement : myStatements) { - hash = hash * 31 + hashElement(statement, 2); // Don't want to hash the whole PSI tree because it might be quite slow + static String getSwitchLabelText(@Nullable PsiSwitchLabelStatementBase switchLabel) { + if (switchLabel != null) { + if (switchLabel.isDefaultCase()) { + return PsiKeyword.DEFAULT; + } + PsiExpressionList caseValues = switchLabel.getCaseValues(); + if (caseValues != null) { + PsiExpression[] expressions = caseValues.getExpressions(); + if (expressions.length != 0) { + return PsiKeyword.CASE + ' ' + expressions[0].getText(); + } + } } - return hash; + return null; } - private static int hashElement(PsiElement element, int depth) { + static int hashElement(@NotNull PsiElement element, int depth) { if (element instanceof PsiExpression) { return hashExpression((PsiExpression)element); } @@ -467,7 +582,7 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { return hash; } - private static int hashExpression(@Nullable PsiExpression expression) { + static int hashExpression(@Nullable PsiExpression expression) { if (expression == null) { return 0; } @@ -496,15 +611,64 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { return index; } - private static int hashReference(@NotNull PsiJavaCodeReferenceElement reference, short index) { + static int hashReference(@NotNull PsiJavaCodeReferenceElement reference, short index) { return Objects.hashCode(reference.getReferenceName()) * 31 + index; } + static int hashStatements(@NotNull PsiStatement[] statements) { + int hash = statements.length; + for (PsiStatement statement : statements) { + hash = hash * 31 + hashElement(statement, 2); // Don't want to hash the whole PSI tree because it might be quite slow + } + return hash; + } + } + + private static class Branch extends BranchBase { + private final PsiStatement[] myStatements; + private final boolean myIsDefault; + private final boolean myIsSimpleExit; + private final boolean myCanFallThrough; + + Branch(@NotNull List statementList, boolean hasImplicitBreak, @NotNull String[] commentTexts) { + super(commentTexts); + int lastIndex = statementList.size() - 1; + PsiStatement lastStatement = statementList.get(lastIndex); + myCanFallThrough = !hasImplicitBreak && ControlFlowUtils.statementMayCompleteNormally(lastStatement); + myIsSimpleExit = lastIndex == 0 && isSimpleExit(lastStatement); + if (lastIndex > 0 && isBreakWithoutLabel(lastStatement)) { + statementList = statementList.subList(0, lastIndex); // trailing 'break' is already taken into account in myCanFallThrough + } + myStatements = statementList.toArray(PsiStatement.EMPTY_ARRAY); + myIsDefault = calculateIsDefault(statementList.get(0)); + } + + @Override + boolean canFallThrough() { + return myCanFallThrough; + } + + @Override + boolean isSimpleExit() { + return myIsSimpleExit; + } + + @Override + int length() { + return myStatements.length; + } + + int hash() { + return hashStatements(myStatements); + } + + @Override boolean isDefault() { return myIsDefault; } @Nullable + @Override String getSwitchLabelText() { PsiSwitchLabelStatement switchLabel = null; for (PsiStatement statement = PsiTreeUtil.getPrevSiblingOfType(myStatements[0], PsiStatement.class); @@ -513,19 +677,40 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { switchLabel = (PsiSwitchLabelStatement)statement; } - if (switchLabel != null) { - if (switchLabel.isDefaultCase()) { - return PsiKeyword.DEFAULT; - } - PsiExpressionList caseValues = switchLabel.getCaseValues(); - if (caseValues != null) { - PsiExpression[] expressions = caseValues.getExpressions(); - if (expressions.length != 0) { - return PsiKeyword.CASE + ' ' + expressions[0].getText(); - } - } - } - return null; + return getSwitchLabelText(switchLabel); + } + + @NotNull + @Override + PsiStatement[] getStatements() { + return myStatements; + } + + @Override + PsiStatement getFirstStatement() { + return myStatements[0]; + } + + @Override + PsiStatement getLastStatement() { + return myStatements[myStatements.length - 1]; + } + + @Nullable + @Override + LocalQuickFix newMergeCasesFix() { + String switchLabelText = getSwitchLabelText(); + return switchLabelText != null ? new MergeBranchesFix(switchLabelText) : null; + } + + @Override + LocalQuickFix newMergeWithDefaultFix() { + return new MergeWithDefaultBranchFix(); + } + + @Override + LocalQuickFix newDeleteCaseFix() { + return new DeleteRedundantBranchFix(); } /** @@ -557,21 +742,6 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { return myStatements; } - @NotNull - private DuplicatesFinder getFinder() { - if (myFinder == null) { - myFinder = createFinder(myStatements); - } - return myFinder; - } - - @NotNull - private static DuplicatesFinder createFinder(@NotNull PsiStatement[] statements) { - Project project = statements[0].getProject(); - InputVariables noVariables = new InputVariables(Collections.emptyList(), project, new LocalSearchScope(statements), false); - return new DuplicatesFinder(statements, noVariables, null, Collections.emptyList()); - } - private static boolean isSimpleExit(@Nullable PsiStatement statement) { if (statement instanceof PsiBreakStatement || statement instanceof PsiContinueStatement || @@ -609,11 +779,6 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { } return false; } - - @Override - public String toString() { - return getSwitchLabelText(); - } } private static class Comments { @@ -640,4 +805,242 @@ public class DuplicateBranchesInSwitchInspection extends LocalInspectionTool { myPending.add(element); } } + + private static class Rule extends BranchBase { + private final PsiSwitchLabeledRuleStatement myRule; + private final PsiStatement myBody; + + Rule(@NotNull PsiSwitchLabeledRuleStatement rule, @NotNull PsiStatement body, @NotNull String[] commentTexts) { + super(commentTexts); + myRule = rule; + myBody = body; + } + + int hash() { + PsiStatement body = myRule.getBody(); + if (body instanceof PsiExpressionStatement) { + return hashExpression(((PsiExpressionStatement)body).getExpression()) * 31 + JavaElementType.EXPRESSION_STATEMENT.getIndex(); + } + if (body instanceof PsiThrowStatement) { + return hashExpression(((PsiThrowStatement)body).getException()) * 31 + JavaElementType.THROW_STATEMENT.getIndex(); + } + if (body instanceof PsiBlockStatement) { + PsiCodeBlock block = ((PsiBlockStatement)body).getCodeBlock(); + return hashStatements(block.getStatements()) * 31 + JavaElementType.BLOCK_STATEMENT.getIndex(); + } + return 0; + } + + @Override + boolean isDefault() { + return myRule.isDefaultCase(); + } + + @Override + boolean isSimpleExit() { + return myBody instanceof PsiExpressionStatement || myBody instanceof PsiThrowStatement; + } + + @Override + boolean canFallThrough() { + return false; + } + + @Override + int length() { + return myBody instanceof PsiBlockStatement ? ((PsiBlockStatement)myBody).getCodeBlock().getStatementCount() : 1; + } + + @NotNull + @Override + PsiStatement[] getStatements() { + return new PsiStatement[]{myBody}; + } + + @Override + PsiStatement getFirstStatement() { + return myBody; + } + + @Override + PsiStatement getLastStatement() { + return myBody; + } + + @Nullable + @Override + String getSwitchLabelText() { + return getSwitchLabelText(myRule); + } + + @Override + String getCaseBranchMessage() { + if (myRule.getEnclosingSwitchBlock() instanceof PsiSwitchExpression) { + return myBody instanceof PsiExpressionStatement + ? InspectionsBundle.message("inspection.duplicate.branches.in.switch.result.message") + : InspectionsBundle.message("inspection.duplicate.branches.in.switch.expression.message"); + } + return super.getCaseBranchMessage(); + } + + @Override + String getDefaultBranchMessage() { + if (myRule.getEnclosingSwitchBlock() instanceof PsiSwitchExpression) { + return myBody instanceof PsiExpressionStatement + ? InspectionsBundle.message("inspection.duplicate.branches.in.switch.default.result.message") + : InspectionsBundle.message("inspection.duplicate.branches.in.switch.expression.default.message"); + } + return super.getDefaultBranchMessage(); + } + + @Nullable + @Override + LocalQuickFix newMergeCasesFix() { + String switchLabelText = getSwitchLabelText(); + return switchLabelText != null ? new MergeRulesFix(switchLabelText, isResultExpression()) : null; + } + + @Override + LocalQuickFix newMergeWithDefaultFix() { + return null; + } + + @Override + LocalQuickFix newDeleteCaseFix() { + return new DeleteRedundantRuleFix(isResultExpression()); + } + + private boolean isResultExpression() { + return myRule.getEnclosingSwitchBlock() instanceof PsiSwitchExpression && myBody instanceof PsiExpressionStatement; + } + } + + private static class MergeRulesFix implements LocalQuickFix { + @NotNull private final String mySwitchLabelText; + private final boolean myIsResultExpression; + + MergeRulesFix(@NotNull String switchLabelText, boolean isResultExpression) { + mySwitchLabelText = switchLabelText; + myIsResultExpression = isResultExpression; + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getFamilyName() { + return myIsResultExpression + ? InspectionsBundle.message("inspection.duplicate.branches.in.switch.expression.fix.family.name") + : InspectionsBundle.message("inspection.duplicate.branches.in.switch.fix.family.name"); + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getName() { + return InspectionsBundle.message("inspection.duplicate.branches.in.switch.fix.name", mySwitchLabelText); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + RuleFixContext context = new RuleFixContext(); + if (context.prepare(descriptor.getStartElement(), rule -> mySwitchLabelText.equals(rule.getSwitchLabelText()))) { + context.copyCaseValues(); + context.deleteRule(); + } + } + } + + private static class DeleteRedundantRuleFix implements LocalQuickFix { + private final boolean myIsResultExpression; + + DeleteRedundantRuleFix(boolean isResultExpression) { + myIsResultExpression = isResultExpression; + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getName() { + return myIsResultExpression + ? InspectionsBundle.message("inspection.duplicate.branches.in.switch.redundant.expression.fix.name") + : InspectionsBundle.message("inspection.duplicate.branches.in.switch.redundant.fix.name"); + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getFamilyName() { + return myIsResultExpression + ? InspectionsBundle.message("inspection.duplicate.branches.in.switch.redundant.expression.fix.family.name") + : InspectionsBundle.message("inspection.duplicate.branches.in.switch.redundant.fix.family.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + RuleFixContext context = new RuleFixContext(); + if (context.prepare(descriptor.getStartElement(), Rule::isDefault)) { + context.deleteRule(); + } + } + } + + private static class RuleFixContext { + private Rule myRuleToDelete; + private Rule myRuleToMergeWith; + private Set myCommentsToMergeWith; + + boolean prepare(PsiElement startElement, Predicate shouldMergeWith) { + if (startElement != null) { + PsiSwitchLabeledRuleStatement ruleStatement = ObjectUtils.tryCast(startElement.getParent(), PsiSwitchLabeledRuleStatement.class); + if (ruleStatement != null) { + PsiSwitchBlock switchBlock = ruleStatement.getEnclosingSwitchBlock(); + if (switchBlock != null) { + List candidateRules = null; + for (List rules : collectProbablySimilarRules(switchBlock)) { + myRuleToDelete = ContainerUtil.find(rules, r -> r.myRule == ruleStatement); + if (myRuleToDelete != null) { + candidateRules = rules; + break; + } + } + if (candidateRules == null) { + return false; + } + for (Rule rule : candidateRules) { + if (shouldMergeWith.test(rule)) { + myRuleToMergeWith = rule; + break; + } + } + if (myRuleToMergeWith == null) { + return false; + } + } + } + } + myCommentsToMergeWith = ContainerUtil.set(myRuleToMergeWith.getCommentTexts()); + return true; + } + + void copyCaseValues() { + PsiExpressionList caseValuesToMergeWith = myRuleToMergeWith.myRule.getCaseValues(); + if (myRuleToDelete.myRule.getCaseValues() != null && caseValuesToMergeWith != null) { + for (PsiExpression caseValue : myRuleToDelete.myRule.getCaseValues().getExpressions()) { + caseValuesToMergeWith.addAfter(caseValue, caseValuesToMergeWith.getLastChild()); + } + } + } + + void deleteRule() { + CommentTracker tracker = new CommentTracker(); + PsiTreeUtil.processElements(myRuleToDelete.myRule, child -> { + if (isRedundantComment(myCommentsToMergeWith, child)) { + tracker.markUnchanged(child); + } + return true; + }); + + tracker.deleteAndRestoreComments(myRuleToDelete.myRule); + } + } } diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ExpressionParentheses.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ExpressionParentheses.java new file mode 100644 index 000000000000..8e28a3e704b0 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ExpressionParentheses.java @@ -0,0 +1,9 @@ +class C { + String test(int i) { + return switch (i) { + case 0 -> null; + case 1 -> (null); + default -> ""; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ReturnInStatement.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ReturnInStatement.java new file mode 100644 index 000000000000..af3138baf412 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ReturnInStatement.java @@ -0,0 +1,10 @@ +class C { + String foo(int n) { + return switch (n) { + case 1 -> "A"; + case 2 -> "B"; + case 3 -> "A"; + default -> ""; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleExpression.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleExpression.java new file mode 100644 index 000000000000..1f60738ff1b2 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleExpression.java @@ -0,0 +1,11 @@ +class C { + void foo(int n) { + String string = switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + default -> ""; + }; + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleStatement.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleStatement.java new file mode 100644 index 000000000000..948ef11901aa --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/SimpleStatement.java @@ -0,0 +1,10 @@ +class C { + void foo(int n) { + switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/StatementParentheses.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/StatementParentheses.java new file mode 100644 index 000000000000..427560266afa --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/StatementParentheses.java @@ -0,0 +1,13 @@ +class C { + String test(int i) { + switch (i) { + case 0 ->{ + return null; + } + case 1 ->{ + return (null); + } + } + return ""; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInExpression.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInExpression.java new file mode 100644 index 000000000000..9a1ecfc6f582 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInExpression.java @@ -0,0 +1,10 @@ +class C { + void foo(int n) { + String string = switch (n) { + case 1 -> throw new IllegalArgumentException(); + case 2 -> throw new IllegalStateException(); + case 3 -> throw new IllegalArgumentException(); + default -> ""; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInStatement.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInStatement.java new file mode 100644 index 000000000000..c5c80b5c5d84 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitch/ThrowInStatement.java @@ -0,0 +1,9 @@ +class C { + void foo(int n) { + switch (n) { + case 1 -> throw new IllegalArgumentException(); + case 2 -> throw new IllegalStateException(); + case 3 -> throw new IllegalArgumentException(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexExpressionBranches.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexExpressionBranches.java new file mode 100644 index 000000000000..eb7885089438 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexExpressionBranches.java @@ -0,0 +1,27 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n, boolean b) { + String s = switch (n) { + case 1, 3 -> { + if (b) { + break bar("A"); + } + else { + bar("z"); + } + break bar("o"); + } + case 2 -> { + if (b) { + break bar("B"); + } + else { + bar("z"); + } + break bar("o"); + } + default -> ""; + }; + } + String bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexStatementBranches.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexStatementBranches.java new file mode 100644 index 000000000000..4bb1d7b95e94 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterComplexStatementBranches.java @@ -0,0 +1,26 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n, boolean b) { + switch (n) { + case 1, 3 -> { + if (b) { + bar("A"); + } + else { + bar("z"); + } + bar("o"); + } + case 2 -> { + if (b) { + bar("B"); + } + else { + bar("z"); + } + bar("o"); + } + } + } + void bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateAfterDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateAfterDefaultDelete.java new file mode 100644 index 000000000000..3a7856ff93c0 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateAfterDefaultDelete.java @@ -0,0 +1,12 @@ +// "Delete redundant 'switch' result expression" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 2 -> bar("B"); + default -> + /*comment 1*/ + bar("A"); + }; + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDelete.java new file mode 100644 index 000000000000..d778394d1bcd --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDelete.java @@ -0,0 +1,10 @@ +// "Delete redundant 'switch' result expression" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 2 -> bar("B"); + default -> bar("A"); + } + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDeleteAdjacent.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDeleteAdjacent.java new file mode 100644 index 000000000000..d778394d1bcd --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionDuplicateBeforeDefaultDeleteAdjacent.java @@ -0,0 +1,10 @@ +// "Delete redundant 'switch' result expression" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 2 -> bar("B"); + default -> bar("A"); + } + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionLeftoverComments.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionLeftoverComments.java new file mode 100644 index 000000000000..4a0418457910 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionLeftoverComments.java @@ -0,0 +1,14 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + String foo(int n) { + return switch (n) { + case 1, 2 -> { + foo(); // same comment + break "A"; + } + // another comment + default -> ""; + }; + } + void foo(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThreeDuplicates.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThreeDuplicates.java new file mode 100644 index 000000000000..df785be93b4f --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThreeDuplicates.java @@ -0,0 +1,12 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 1, 4 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + default -> ""; + } + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThrow.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThrow.java new file mode 100644 index 000000000000..34711487adbc --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterExpressionThrow.java @@ -0,0 +1,10 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 1, 3 -> throw new IllegalArgumentException("A"); + case 2 -> throw new IllegalStateException("A"); + default -> ""; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleExpression.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleExpression.java new file mode 100644 index 000000000000..1203d1b1083e --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleExpression.java @@ -0,0 +1,10 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1, 3 -> bar("A"); + case 2 -> bar("B"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleStatement.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleStatement.java new file mode 100644 index 000000000000..1203d1b1083e --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterSimpleStatement.java @@ -0,0 +1,10 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1, 3 -> bar("A"); + case 2 -> bar("B"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateAfterDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateAfterDefaultDelete.java new file mode 100644 index 000000000000..a374d0f64e66 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateAfterDefaultDelete.java @@ -0,0 +1,17 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 2 -> { + bar("B"); + } + default -> { + /*comment 2*/ + bar("A"); + /*comment 1*/ + } + /*comment 3*/ + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDelete.java new file mode 100644 index 000000000000..ac5f84001f63 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDelete.java @@ -0,0 +1,10 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 2 -> bar("B"); + default ->bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDeleteAdjacent.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDeleteAdjacent.java new file mode 100644 index 000000000000..8eb544a6b818 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementDuplicateBeforeDefaultDeleteAdjacent.java @@ -0,0 +1,10 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 2 -> bar("B"); + default -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementLeftoverComments.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementLeftoverComments.java new file mode 100644 index 000000000000..59d72a1dc18f --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementLeftoverComments.java @@ -0,0 +1,14 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + String foo(int n) { + switch (n) { + case 1, 2 -> { + foo(); // same comment + return "A"; + } + // another comment + } + return ""; + } + void foo(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementMethodCallInReturn.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementMethodCallInReturn.java new file mode 100644 index 000000000000..f26bad20290b --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementMethodCallInReturn.java @@ -0,0 +1,18 @@ +// "Merge with 'case A'" "GENERIC_ERROR_OR_WARNING" +enum T { + A, B, C; + + int foo(T t) { + switch (t) { + case A, B -> { + return t.ordinal(); // comment 1 + } + case C -> { + return t.ordinal(); // comment 2 + } + default -> { + return 0; + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementReturnUnderIf.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementReturnUnderIf.java new file mode 100644 index 000000000000..ecb1aee369f7 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementReturnUnderIf.java @@ -0,0 +1,19 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + int foo(int n, boolean b) { + switch (n) { + case 1, 3 -> { + if(b) { + return bar("A"); + } + } + case 2 -> { + if(b) { + return bar("B"); + } + } + } + return 0; + } + int bar(String s){return s.charAt(0);} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicates.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicates.java new file mode 100644 index 000000000000..dd8174814a48 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicates.java @@ -0,0 +1,11 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1, 4 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicatesDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicatesDefaultDelete.java new file mode 100644 index 000000000000..e4db0fd093f1 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThreeDuplicatesDefaultDelete.java @@ -0,0 +1,11 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 2 -> bar("B"); + case 3 -> bar("A"); + default -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThrow.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThrow.java new file mode 100644 index 000000000000..8b9aa2115c40 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/afterStatementThrow.java @@ -0,0 +1,9 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1, 3 -> throw new IllegalArgumentException("A"); + case 2 -> throw new IllegalStateException("A"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexExpressionBranches.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexExpressionBranches.java new file mode 100644 index 000000000000..38b18754db99 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexExpressionBranches.java @@ -0,0 +1,36 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n, boolean b) { + String s = switch (n) { + case 1 -> { + if (b) { + break bar("A"); + } + else { + bar("z"); + } + break bar("o"); + } + case 2 -> { + if (b) { + break bar("B"); + } + else { + bar("z"); + } + break bar("o"); + } + case 3 -> { + if (b) { + break bar("A"); + } + else { + bar("z"); + } + break bar("o"); + } + default -> ""; + }; + } + String bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexStatementBranches.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexStatementBranches.java new file mode 100644 index 000000000000..4949b801e4f9 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeComplexStatementBranches.java @@ -0,0 +1,35 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n, boolean b) { + switch (n) { + case 1 -> { + if (b) { + bar("A"); + } + else { + bar("z"); + } + bar("o"); + } + case 2 -> { + if (b) { + bar("B"); + } + else { + bar("z"); + } + bar("o"); + } + case 3 -> { + if (b) { + bar("A"); + } + else { + bar("z"); + } + bar("o"); + } + } + } + void bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateAfterDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateAfterDefaultDelete.java new file mode 100644 index 000000000000..c0d30dd573a3 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateAfterDefaultDelete.java @@ -0,0 +1,15 @@ +// "Delete redundant 'switch' result expression" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 2 -> bar("B"); + default -> + /*comment 1*/ + bar("A"); + case 1 -> + /*comment 1*/ + bar("A"); + }; + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDelete.java new file mode 100644 index 000000000000..d0f4dde0acf3 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDelete.java @@ -0,0 +1,11 @@ +// "Delete redundant 'switch' result expression" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + default -> bar("A"); + } + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDeleteAdjacent.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDeleteAdjacent.java new file mode 100644 index 000000000000..dfd840b71ced --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionDuplicateBeforeDefaultDeleteAdjacent.java @@ -0,0 +1,11 @@ +// "Delete redundant 'switch' result expression" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 2 -> bar("B"); + case 1 -> bar("A"); + default -> bar("A"); + } + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionLeftoverComments.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionLeftoverComments.java new file mode 100644 index 000000000000..3cee20837af3 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionLeftoverComments.java @@ -0,0 +1,17 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + String foo(int n) { + return switch (n) { + case 1 -> { + foo(); // same comment + break "A"; + } + case 2 ->{ + foo(); // same comment + break "A"; // another comment + } + default -> ""; + }; + } + void foo(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThreeDuplicates.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThreeDuplicates.java new file mode 100644 index 000000000000..5f7ab639c608 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThreeDuplicates.java @@ -0,0 +1,13 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + case 4 -> bar("A"); + default -> ""; + } + } + String bar(String s){return s;} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThrow.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThrow.java new file mode 100644 index 000000000000..92ec5ac7753e --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeExpressionThrow.java @@ -0,0 +1,11 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + String s = switch (n) { + case 1 -> throw new IllegalArgumentException("A"); + case 2 -> throw new IllegalStateException("A"); + case 3 -> throw new IllegalArgumentException("A"); + default -> ""; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleExpression.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleExpression.java new file mode 100644 index 000000000000..8b342cde8ef7 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleExpression.java @@ -0,0 +1,11 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleStatement.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleStatement.java new file mode 100644 index 000000000000..8b342cde8ef7 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeSimpleStatement.java @@ -0,0 +1,11 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateAfterDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateAfterDefaultDelete.java new file mode 100644 index 000000000000..ba3c27bb6a4b --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateAfterDefaultDelete.java @@ -0,0 +1,21 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 2 -> { + bar("B"); + } + default -> { + /*comment 2*/ + bar("A"); + /*comment 1*/ + } + case 1 -> { + /*comment 2*/ + bar("A"); + /*comment 3*/ + } + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDelete.java new file mode 100644 index 000000000000..9ff71bf4fc89 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDelete.java @@ -0,0 +1,11 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + default ->bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDeleteAdjacent.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDeleteAdjacent.java new file mode 100644 index 000000000000..70d6a955680d --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementDuplicateBeforeDefaultDeleteAdjacent.java @@ -0,0 +1,11 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 2 -> bar("B"); + case 1 -> bar("A"); + default -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementLeftoverComments.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementLeftoverComments.java new file mode 100644 index 000000000000..b74c5925ea67 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementLeftoverComments.java @@ -0,0 +1,17 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + String foo(int n) { + switch (n) { + case 1 -> { + foo(); // same comment + return "A"; + } + case 2 ->{ + foo(); // same comment + return "A"; // another comment + } + } + return ""; + } + void foo(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementMethodCallInReturn.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementMethodCallInReturn.java new file mode 100644 index 000000000000..b5272e3eee06 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementMethodCallInReturn.java @@ -0,0 +1,21 @@ +// "Merge with 'case A'" "GENERIC_ERROR_OR_WARNING" +enum T { + A, B, C; + + int foo(T t) { + switch (t) { + case A -> { + return t.ordinal(); // comment 1 + } + case B -> { + return t.ordinal(); + } + case C -> { + return t.ordinal(); // comment 2 + } + default -> { + return 0; + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementReturnUnderIf.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementReturnUnderIf.java new file mode 100644 index 000000000000..6a97dfb16c6c --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementReturnUnderIf.java @@ -0,0 +1,24 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + int foo(int n, boolean b) { + switch (n) { + case 1 -> { + if(b) { + return bar("A"); + } + } + case 2 -> { + if(b) { + return bar("B"); + } + } + case 3 -> { + if(b) { + return bar("A"); + } + } + } + return 0; + } + int bar(String s){return s.charAt(0);} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicates.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicates.java new file mode 100644 index 000000000000..5d28fc431936 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicates.java @@ -0,0 +1,12 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + case 4 -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicatesDefaultDelete.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicatesDefaultDelete.java new file mode 100644 index 000000000000..54a89e0548da --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThreeDuplicatesDefaultDelete.java @@ -0,0 +1,12 @@ +// "Delete redundant 'switch' branch" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1 -> bar("A"); + case 2 -> bar("B"); + case 3 -> bar("A"); + default -> bar("A"); + } + } + void bar(String s){} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThrow.java b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThrow.java new file mode 100644 index 000000000000..4e4bc2ca5b57 --- /dev/null +++ b/java/java-tests/testData/inspection/duplicateBranchesInEnhancedSwitchFix/beforeStatementThrow.java @@ -0,0 +1,10 @@ +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" +class C { + void foo(int n) { + switch (n) { + case 1 -> throw new IllegalArgumentException("A"); + case 2 -> throw new IllegalStateException("A"); + case 3 -> throw new IllegalArgumentException("A"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterBreakAndReturnUnderIf.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterBreakAndReturnUnderIf.java index 5da8e991bd52..e3b8c7f7e8ba 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterBreakAndReturnUnderIf.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterBreakAndReturnUnderIf.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { int foo(int n, boolean b) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterComplexBranches.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterComplexBranches.java index fde660f56688..09033a9151c7 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterComplexBranches.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterComplexBranches.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n, boolean b) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterContinue.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterContinue.java index ea6d858535f4..9e4c5d58f8d4 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterContinue.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterContinue.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { int foo(int n) { int s = 0; diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak.java index 8c0d0b3183a2..002cb2d35821 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak2.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak2.java index 8b084e6be7d1..24577f44b177 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak2.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterFallThroughToBreak2.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterLeftoverComments.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterLeftoverComments.java index 2bbc2c93b23f..8eb3113242b3 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterLeftoverComments.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterLeftoverComments.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterManyComments.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterManyComments.java index 56d8f85cea3c..1455567a28f5 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterManyComments.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterManyComments.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterMethodCallInReturn.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterMethodCallInReturn.java index b5f5d1c23ea0..84961ace2a60 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterMethodCallInReturn.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterMethodCallInReturn.java @@ -1,4 +1,4 @@ -// "Merge with 'case A:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case A'" "GENERIC_ERROR_OR_WARNING" enum T { A, B, C; diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterNoLastBreak.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterNoLastBreak.java index acfdea991d36..06cdd065f877 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterNoLastBreak.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterNoLastBreak.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterReturn.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterReturn.java index 1410369ed422..9679df567db8 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterReturn.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterReturn.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentAfterLabel.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentAfterLabel.java index a34edc876cbf..2a867c3c910c 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentAfterLabel.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentAfterLabel.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentBeforeLabel.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentBeforeLabel.java index d1efe42d3568..3029a29fc576 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentBeforeLabel.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSameCommentBeforeLabel.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSimple.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSimple.java index acfdea991d36..06cdd065f877 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSimple.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterSimple.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThreeDuplicates.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThreeDuplicates.java index 56846e0d59f1..9f841586d3dc 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThreeDuplicates.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThreeDuplicates.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThrow.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThrow.java index 50ea996bb52e..5010a082f8a1 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThrow.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterThrow.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterTwoCaseLabels.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterTwoCaseLabels.java index ef3857766ffd..f40b3447f91e 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterTwoCaseLabels.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/afterTwoCaseLabels.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeBreakAndReturnUnderIf.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeBreakAndReturnUnderIf.java index 816a74373831..ef0928c3ffd7 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeBreakAndReturnUnderIf.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeBreakAndReturnUnderIf.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { int foo(int n, boolean b) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeComplexBranches.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeComplexBranches.java index b89524c38bef..680231b7c066 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeComplexBranches.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeComplexBranches.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n, boolean b) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeContinue.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeContinue.java index a61416708468..6ea3f7f377b5 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeContinue.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeContinue.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { int foo(int n) { int s = 0; diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak.java index 50a350cd0472..11bab0a233d0 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak2.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak2.java index 376aa430deb5..e9694adea0e8 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak2.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeFallThroughToBreak2.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeLeftoverComments.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeLeftoverComments.java index 066ff31784ae..b1f5d5129784 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeLeftoverComments.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeLeftoverComments.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeManyComments.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeManyComments.java index bc85b65f586f..26ed09b2d10a 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeManyComments.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeManyComments.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeMethodCallInReturn.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeMethodCallInReturn.java index 56ffab490ebd..30c1761e43ae 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeMethodCallInReturn.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeMethodCallInReturn.java @@ -1,4 +1,4 @@ -// "Merge with 'case A:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case A'" "GENERIC_ERROR_OR_WARNING" enum T { A, B, C; diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeNoLastBreak.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeNoLastBreak.java index 66696c51d912..75235293cc1d 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeNoLastBreak.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeNoLastBreak.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeReturn.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeReturn.java index 004133f9a283..9fd4d6224fa7 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeReturn.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeReturn.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentAfterLabel.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentAfterLabel.java index ce9c139969fd..8f42fdfafca9 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentAfterLabel.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentAfterLabel.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentBeforeLabel.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentBeforeLabel.java index c1839f34a5b5..95e826831e5d 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentBeforeLabel.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSameCommentBeforeLabel.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSimple.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSimple.java index 9b4deda0c55e..eedf8d0bd291 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSimple.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeSimple.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThreeDuplicates.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThreeDuplicates.java index e834493c60cb..6860c43f3c52 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThreeDuplicates.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThreeDuplicates.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThrow.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThrow.java index b9aeb5cbe6fc..b338c5e8c73a 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThrow.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeThrow.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { String foo(int n) { switch (n) { diff --git a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeTwoCaseLabels.java b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeTwoCaseLabels.java index a344313f340a..469410685c55 100644 --- a/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeTwoCaseLabels.java +++ b/java/java-tests/testData/inspection/duplicateBranchesInSwitchFix/beforeTwoCaseLabels.java @@ -1,4 +1,4 @@ -// "Merge with 'case 1:'" "GENERIC_ERROR_OR_WARNING" +// "Merge with 'case 1'" "GENERIC_ERROR_OR_WARNING" class C { void foo(int n) { switch (n) { diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchFixTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchFixTest.kt new file mode 100644 index 000000000000..19880a9c5a5c --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchFixTest.kt @@ -0,0 +1,20 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.java.codeInspection + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase +import com.intellij.codeInspection.DuplicateBranchesInSwitchInspection +import com.intellij.codeInspection.LocalInspectionTool +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +/** + * @author Pavel.Dolgov + */ +class DuplicateBranchesInEnhancedSwitchFixTest : LightQuickFixParameterizedTestCase() { + + override fun configureLocalInspectionTools(): Array = arrayOf(DuplicateBranchesInSwitchInspection()) + + override fun getBasePath() = "/inspection/duplicateBranchesInEnhancedSwitchFix" + + override fun getProjectDescriptor(): LightProjectDescriptor = LightCodeInsightFixtureTestCase.JAVA_12 +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchTest.kt new file mode 100644 index 000000000000..99e145c77443 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DuplicateBranchesInEnhancedSwitchTest.kt @@ -0,0 +1,35 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.java.codeInspection + +import com.intellij.JavaTestUtil +import com.intellij.codeInspection.DuplicateBranchesInSwitchInspection +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +/** + * @author Pavel.Dolgov + */ +class DuplicateBranchesInEnhancedSwitchTest : LightCodeInsightFixtureTestCase() { + val inspection = DuplicateBranchesInSwitchInspection() + + override fun setUp() { + super.setUp() + myFixture.enableInspections(inspection) + } + + override fun getBasePath() = JavaTestUtil.getRelativeJavaTestDataPath() + "/inspection/duplicateBranchesInEnhancedSwitch" + + override fun getProjectDescriptor(): LightProjectDescriptor = JAVA_12 + + fun testSimpleExpression() = doTest() + fun testSimpleStatement() = doTest() + fun testThrowInExpression() = doTest() + fun testThrowInStatement() = doTest() + fun testReturnInStatement() = doTest() + fun testExpressionParentheses() = doTest() + fun testStatementParentheses() = doTest() + + private fun doTest() { + myFixture.testHighlighting("${getTestName(false)}.java") + } +} \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index d63c4dca11ab..77f51551555c 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -1050,12 +1050,19 @@ inspection.switch.expression.backward.statement.migration.inspection.name='switc inspection.replace.with.old.style.switch.statement.fix.name=Replace with old style 'switch' statement inspection.duplicate.branches.in.switch.display.name=Duplicate branches in 'switch' statement -inspection.duplicate.branches.in.switch.message=Duplicate branch in 'switch' statement +inspection.duplicate.branches.in.switch.statement.message=Duplicate branch in 'switch' statement +inspection.duplicate.branches.in.switch.expression.message=Duplicate branch in 'switch' expression +inspection.duplicate.branches.in.switch.result.message=Duplicate result expression in 'switch' expression +inspection.duplicate.branches.in.switch.statement.default.message=Branch in 'switch' statement is a duplicate of the default branch +inspection.duplicate.branches.in.switch.expression.default.message=Branch in 'switch' expression is a duplicate of the default branch +inspection.duplicate.branches.in.switch.default.result.message=Result expression in 'switch' expression is a duplicate of the default result inspection.duplicate.branches.in.switch.fix.family.name=Merge duplicate branches of 'switch' statement -inspection.duplicate.branches.in.switch.fix.name=Merge with ''{0}:'' -inspection.duplicate.branches.in.switch.redundant.message=Branch in 'switch' statement is a duplicate of the default branch +inspection.duplicate.branches.in.switch.expression.fix.family.name=Merge duplicate results of 'switch' statement +inspection.duplicate.branches.in.switch.fix.name=Merge with ''{0}'' inspection.duplicate.branches.in.switch.redundant.fix.family.name=Delete redundant branches of 'switch' statement +inspection.duplicate.branches.in.switch.redundant.expression.fix.family.name=Delete redundant branches of 'switch' statement inspection.duplicate.branches.in.switch.redundant.fix.name=Delete redundant 'switch' branch +inspection.duplicate.branches.in.switch.redundant.expression.fix.name=Delete redundant 'switch' result expression inspection.duplicate.branches.in.switch.merge.with.default.fix.name=Merge with the default 'switch' branch inspection.switch.labeled.rule.can.be.code.block.display.name=Labeled switch rule can have code block