From 42f43778e2baff715e452efb1d9231d689aedbfc Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 18 May 2022 09:50:17 +0200 Subject: [PATCH] [java-dfa] Do not report unreachable switch branches if they are throwing GitOrigin-RevId: 5164e1b5f86abb797f7aa1a33b61fd28d85ca1d5 --- .../dataFlow/DataFlowInspectionBase.java | 22 +++++++++++++++++++ .../dataFlow/fixture/SwitchStatements.java | 16 ++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 5996d82a33ad..7943b5610e00 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -369,6 +369,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec unreachableLabels.put(label, switchBlock); } unreachableLabels.forEach((label, switchBlock) -> { + if (isThrowing(label)) return; // duplicate case label is a compilation error so no need to highlight by the inspection Set suspiciousElements = SwitchBlockHighlightingModel.findSuspiciousLabelElements(switchBlock); if (!suspiciousElements.contains(label)) { @@ -378,6 +379,27 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec }); } + private static boolean isThrowing(PsiCaseLabelElement label) { + PsiCaseLabelElementList caseLabelList = tryCast(label.getParent(), PsiCaseLabelElementList.class); + if (caseLabelList == null) return false; + PsiSwitchLabelStatementBase labelStatement = tryCast(caseLabelList.getParent(), PsiSwitchLabelStatementBase.class); + if (labelStatement == null) return false; + if (labelStatement instanceof PsiSwitchLabeledRuleStatement) { + return ControlFlowUtils.stripBraces(((PsiSwitchLabeledRuleStatement)labelStatement).getBody()) instanceof PsiThrowStatement; + } + if (labelStatement instanceof PsiSwitchLabelStatement) { + PsiElement cur = labelStatement; + while(true) { + PsiElement next = cur.getNextSibling(); + if (!(next instanceof PsiComment) && !(next instanceof PsiWhiteSpace) && !(next instanceof PsiSwitchLabelStatement)) { + return next instanceof PsiThrowStatement; + } + cur = next; + } + } + return false; + } + private static boolean canRemoveUnreachableBranches(PsiSwitchLabelStatementBase labelStatement, PsiSwitchBlock statement) { if (Objects.requireNonNull(labelStatement.getCaseLabelElementList()).getElementCount() != 1) return true; List allBranches = diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/SwitchStatements.java b/java/java-tests/testData/inspection/dataFlow/fixture/SwitchStatements.java index dac6aba5cb56..4b9451c79775 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/SwitchStatements.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/SwitchStatements.java @@ -54,4 +54,20 @@ public class SwitchStatements { case 2 -> System.out.println("two"); } } + + enum X {A, B, C} + + void testThrowingBranch(X x) { + if (x == X.A) return; + switch(x) { + case A -> throw new AssertionError(); + case B -> System.out.println(1); + case C -> System.out.println(2); + } + switch(x) { + case B: System.out.println(1);break; + case C: System.out.println(2);break; + case A: default: throw new AssertionError(); + } + } }