From f94fd394cd0035efc5d6d1cd459fa8aefe8f0084 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 21 Nov 2018 17:37:38 +0700 Subject: [PATCH] ControlFlowAnalyzer: support breaks from switch expressions (IDEA-202132) --- .../dataFlow/ControlFlowAnalyzer.java | 12 ++- .../fixture/SwitchExpressionsJava12.java | 98 +++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index ed225c789c98..8a17917afaa6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -173,7 +173,8 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { private void finishElement(PsiElement element) { myCurrentFlow.finishElement(element); - if (element instanceof PsiStatement && !(element instanceof PsiReturnStatement)) { + if (element instanceof PsiStatement && !(element instanceof PsiReturnStatement) && + !(element instanceof PsiSwitchLabeledRuleStatement)) { List synthetics = getSynthetics(element); FinishElementInstruction instruction = new FinishElementInstruction(element); instruction.getVarsToFlush().addAll(synthetics); @@ -401,7 +402,14 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { @Override public void visitBreakStatement(PsiBreakStatement statement) { startElement(statement); - jumpOut(statement.findExitedStatement()); + PsiExpression expression = statement.getExpression(); + PsiElement exitedElement = statement.findExitedElement(); + if (expression != null && exitedElement instanceof PsiSwitchExpression && + myInlinedBlockContext != null && myInlinedBlockContext.myCodeBlock == ((PsiSwitchExpression)exitedElement).getBody()) { + myInlinedBlockContext.generateReturn(expression, this); + } else { + jumpOut(exitedElement); + } finishElement(statement); } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/SwitchExpressionsJava12.java b/java/java-tests/testData/inspection/dataFlow/fixture/SwitchExpressionsJava12.java index 84e11ada1e01..28d7ca6748fb 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/SwitchExpressionsJava12.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/SwitchExpressionsJava12.java @@ -73,4 +73,102 @@ public class SwitchExpressionsJava12 { } } } + + static void testSimpleBreak(int i) { + int j = switch(i) { + case 1 -> { + System.out.println("Hello"); + break 10; + } + case 2 -> { + i = i+1; + break 20; + } + case 3 -> { + break 33-i; + } + default -> 0; + }; + if (j == 20 && i == 3) {} + if (j == 30 && i == 3) {} + if (j == 10 && i == 1) {} + if (i == 2) {} + if (j == 0 && (i < 1 || i > 3)) {} + } + + static void testSwitchInInlinedLambda(int i) { + int x = ((IntSupplier)() -> { + int j = switch (i) { + case 1 -> 2; + case 2 -> 3; + case 3 -> { + System.out.println("hello"); + break 1; + } + default -> 4; + }; + if (j < 2) {} + if (j == 4 && i == 2) {} + if (i == 3 && j == 1) {} + return 0; + }).getAsInt(); + if (x == 1 && i == 3) {} + } + + static void testSwitchWithInnerFinally(int i) { + int j = switch (i) { + case 1 -> 2; + case 2 -> 3; + case 3 -> { + try { + System.out.println("hello"); + break 1; // never happens + } + finally { + break 2; + } + } + default -> 4; + }; + if (j < 2) {} + if (j == 4 && i == 2) {} + } + + static int get(int x) { + return x; + } + + void testStatementInsideExpressionInsideBlockLambda(int x, int y) { + int i = ((IntSupplier)() -> { + System.out.println(); + return switch(x) { + case 1 -> { + switch (y) { + default -> get(x); + } + break 5; + } + default -> 10; + }; + }).getAsInt(); + if (i != 10) {} + } + + void testSwitchWithCatch(int x) { + int i = switch(x) { + case 1, 2: + try { + if (x % 2 == 1) throw new IllegalArgumentException(); + } + catch (IllegalArgumentException ex) { + break 100; + } + case 3: + break 200; + default: + break 300; + }; + if (i == 100 && x == 1) {} + if (i == 200 && (x == 2 || x == 3)) {} + } }