diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index 469230aebb37..888942e834ae 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
@@ -91,7 +91,7 @@ public class HighlightControlFlowUtil {
String description = JavaErrorMessages.message("unreachable.statement");
PsiElement keyword = null;
if (unreachableStatement instanceof PsiIfStatement ||
- unreachableStatement instanceof PsiSwitchStatement ||
+ unreachableStatement instanceof PsiSwitchBlock ||
unreachableStatement instanceof PsiLoopStatement) {
keyword = unreachableStatement.getFirstChild();
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
index ededb93e5cdf..7714669d42ef 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
@@ -850,8 +850,48 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
finishElement(statement);
}
+ @Override
+ public void visitSwitchLabeledRuleStatement(PsiSwitchLabeledRuleStatement statement) {
+ startElement(statement);
+ PsiExpressionList caseValues = statement.getCaseValues();
+
+ if (caseValues != null) {
+ for (PsiExpression caseValue : caseValues.getExpressions()) {
+ myStartStatementStack.pushStatement(caseValue, false);
+ myEndStatementStack.pushStatement(caseValue, false);
+ caseValue.accept(this);
+ myStartStatementStack.popStatement();
+ myEndStatementStack.popStatement();
+ }
+ }
+
+ PsiStatement body = statement.getBody();
+ if (body != null) {
+ body.accept(this);
+ }
+
+ PsiSwitchBlock switchBlock = statement.getEnclosingSwitchBlock();
+ if (switchBlock != null) {
+ Instruction instruction =
+ new GoToInstruction(0, BranchingInstruction.Role.END, PsiTreeUtil.isAncestor(switchBlock, myCodeFragment, true));
+ myCurrentFlow.addInstruction(instruction);
+ addElementOffsetLater(switchBlock, false);
+ }
+
+ finishElement(statement);
+ }
+
@Override
public void visitSwitchStatement(PsiSwitchStatement statement) {
+ generateSwitchBlockInstructions(statement);
+ }
+
+ @Override
+ public void visitSwitchExpression(PsiSwitchExpression expression) {
+ generateSwitchBlockInstructions(expression);
+ }
+
+ public void generateSwitchBlockInstructions(PsiSwitchBlock statement) {
startElement(statement);
PsiExpression expr = statement.getExpression();
@@ -862,12 +902,12 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
PsiCodeBlock body = statement.getBody();
if (body != null) {
PsiStatement[] statements = body.getStatements();
- PsiSwitchLabelStatement defaultLabel = null;
+ PsiSwitchLabelStatementBase defaultLabel = null;
for (PsiStatement aStatement : statements) {
ProgressManager.checkCanceled();
- if (aStatement instanceof PsiSwitchLabelStatement) {
- if (((PsiSwitchLabelStatement)aStatement).isDefaultCase()) {
- defaultLabel = (PsiSwitchLabelStatement)aStatement;
+ if (aStatement instanceof PsiSwitchLabelStatementBase) {
+ if (((PsiSwitchLabelStatementBase)aStatement).isDefaultCase()) {
+ defaultLabel = (PsiSwitchLabelStatementBase)aStatement;
}
Instruction instruction = new ConditionalGoToInstruction(0, expr);
myCurrentFlow.addInstruction(instruction);
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java
index 4fdbab174b2a..079e00fb06a9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java
@@ -1157,7 +1157,7 @@ public class ControlFlowUtil {
return getUnreachableStatementParent(parent);
}
if (parent instanceof PsiIfStatement && ((PsiIfStatement)parent).getCondition() == expression ||
- parent instanceof PsiSwitchStatement && ((PsiSwitchStatement)parent).getExpression() == expression ||
+ parent instanceof PsiSwitchBlock && ((PsiSwitchBlock)parent).getExpression() == expression ||
parent instanceof PsiWhileStatement && ((PsiWhileStatement)parent).getCondition() == expression ||
parent instanceof PsiForeachStatement && ((PsiForeachStatement)parent).getIteratedValue() == expression) {
return parent;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting12/EnhancedSwitchDefinitelyAssigned.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting12/EnhancedSwitchDefinitelyAssigned.java
new file mode 100644
index 000000000000..e40f0685eee6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting12/EnhancedSwitchDefinitelyAssigned.java
@@ -0,0 +1,108 @@
+class C {
+ void finalVariableAssignedInAllBranches(int k) {
+ final String s;
+ switch (k) {
+ case 1 -> s = "a";
+ case 2 -> s = "b";
+ case 3, 4 -> s = "c";
+ default -> s = "d";
+ }
+ System.out.println(s);
+ }
+
+ enum EnumAB {A, B}
+ void finalVariableAssignedInAllEnumConstantBranches(EnumAB ab) {
+ final int n;
+ switch (ab) {
+ case A -> n = 1;
+ case B -> n = 2;
+ }
+ System.out.println(n);
+ }
+
+ void assignedInSomeBranches(String s) {
+ int n;
+ switch ((int)Math.random()) {
+ case 1 -> n = 1;
+ default -> {}
+ }
+ System.out.println(n);
+ }
+
+ void finalVariableReassignedAfterSwitchStatement(int n) {
+ final String s;
+ switch (n) {
+ case 1 -> s = "a";
+ default -> {}
+ }
+ s = "b";
+ System.out.println(s);
+ }
+
+ void finalVariableReassignedAfterSwitchExpression(int n) {
+ final String s;
+ String t = switch (n) {
+ case 1 -> s = "a";
+ default -> "";
+ };
+ s = t;
+ System.out.println(s);
+ }
+
+ void finalVariableReassignedInSwitchStatement(int n) {
+ final String s = "b";
+ switch (n) {
+ case 1 -> s = "a";
+ default -> {}
+ };
+ System.out.println(s);
+ }
+
+ void finalVariableReassignedInSwitchExpression(int n) {
+ final String s = "b";
+ String string = switch (n) {
+ case 1 -> s = "a";
+ default -> "";
+ };
+ System.out.println(s);
+ }
+
+
+ static class FinalFieldAssignedInSomeBranches {
+ final int n;
+ {
+ switch ((int)Math.random()) {
+ case 1 -> n = 1;
+ default -> {}
+ }
+ }
+ }
+
+ static class FinalFieldAssignedInSomeBranchesNoDefault {
+ final int n;
+ {
+ switch ((int)Math.random()) {
+ case 1 -> n = 1;
+ case 0 -> n = 0;
+ }
+ }
+ }
+
+ static class FinalFieldAssignedInAllBranches {
+ final int n;
+ {
+ switch ((int)Math.random()) {
+ case 1 -> n = 1;
+ default -> n = 0;
+ }
+ }
+ }
+
+ static class FinalFieldInitializedWithswitchExpression {
+ final int n =
+ switch ((int)Math.random()) {
+ case 1 -> 1;
+ default -> 0;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting12/EnhancedSwitchUnreachable.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting12/EnhancedSwitchUnreachable.java
new file mode 100644
index 000000000000..8702dc655179
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting12/EnhancedSwitchUnreachable.java
@@ -0,0 +1,146 @@
+class C {
+ void alwaysThrow(String s) {
+ switch (s) {
+ case "a" -> throw new IllegalArgumentException();
+ default -> throw new IllegalStateException();
+ }
+ System.out.println();
+ }
+
+ void breakFromEndlessLoop() {
+ EndlessLoop:
+ for (;;) {
+ switch ((int)Math.random()) {
+ case 1 -> {break EndlessLoop;}
+ default -> throw new RuntimeException();
+ }
+ }
+ System.out.println();
+ }
+
+ void continueEndlessLoop() {
+ EndlessLoop:
+ for (;;) {
+ switch ((int)Math.random()) {
+ case 1 -> {continue EndlessLoop;}
+ default -> throw new RuntimeException();
+ }
+ }
+ System.out.println();
+ }
+
+ void endlessLoopsInAllBranches(String s) {
+ switch (s) {
+ case "a" -> { while(true); }
+ default -> { for(;;); }
+ }
+ System.out.println();
+ }
+
+ void endlessLoopInBranch(String s) {
+ switch (s) {
+ case "a" -> { while(true); }
+ default -> {}
+ };
+ System.out.println();
+ }
+
+ /* todo
+ void endlessLoopInBranchWithValue(String arg) {
+ int result = switch (arg) {
+ case "one" -> { while(true); break 1;}
+ default -> 0;
+ };
+ System.out.println(result);
+ }
+ */
+
+ static class FinalFieldSwitchExpression {
+ final String s = switch ((int)Math.random()) {
+ case 1 -> "a";
+ default -> "?";
+ };
+ {
+ System.out.println(s);
+ }
+ }
+
+ void finalVariableSwitchExpression(String s) {
+ final int n = switch (s) {
+ case "a" -> 1;
+ default -> 0;
+ };
+ System.out.println(n);
+ }
+
+ void notDefinitelyAssigned(String s) {
+ int n;
+ switch (s) {
+ case "a" -> n = 1;
+ }
+ System.out.println(n);
+ }
+
+ int returnBeforeEnhancedSwitchStatement(String s) {
+ return 2;
+ switch(s) {
+ case "a" -> {return 1;}
+ default -> {return 0;}
+ }
+ }
+
+ int returnBeforeSwitchExpressionInInitializer(String s) {
+ return 2;
+ int n = switch(s) {
+ case "a" -> 1;
+ default -> 0;
+ };
+ }
+
+ int returnBeforeSwitchExpressionInAssignment(String s) {
+ int n;
+ return 2;
+ n = switch(s) {
+ case "a": n= 1;break;
+ default: n= 0;
+ };
+ }
+
+ int returnSwitchExpression(String s) {
+ return switch(s) {
+ case "a" -> 1;
+ default -> 0;
+ };
+ System.out.println();
+ }
+
+ static class SwitchExpressionReturnedFromTry {
+ int foo(String s) throws Exception {
+ try {
+ return switch (s) {
+ case "a" -> bar(1);
+ default -> bar(0);
+ };
+ } finally {
+ System.out.println("b");
+ }
+ System.out.println("c");
+ }
+ int bar(int i) throws Exception { return i; }
+ }
+
+ static class SwitchStatementReturnsFromTry {
+ int foo(String s) throws Exception {
+ try {
+ switch (s) {
+ case "a" -> { return bar(1); }
+ default -> { return bar(0); }
+ }
+ } finally {
+ System.out.println("b");
+ }
+ System.out.println("c");
+ }
+ int bar(int i) throws Exception { return i; }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava12HighlightingTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava12HighlightingTest.kt
index 1421acc8d798..b8c9daf35335 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava12HighlightingTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava12HighlightingTest.kt
@@ -12,6 +12,8 @@ class LightJava12HighlightingTest : LightCodeInsightFixtureTestCase() {
fun testSwitchExpressions() = doTest()
fun testSwitchNumericPromotion() = doTest()
fun testSimpleInferenceCases() = doTest()
+ fun testEnhancedSwitchDefinitelyAssigned() = doTest()
+ fun testEnhancedSwitchUnreachable() = doTest()
private fun doTest() {
myFixture.configureByFile(getTestName(false) + ".java")