branches = StreamEx.of(newBody.getStatements())
+ .select(PsiSwitchLabelStatement.class)
+ .toList();
+ if (branches.size() != branchTrackers.size()) return newBlock;
+ for (int i = 0; i < branches.size(); i++) {
+ PsiSwitchLabelStatement branch = branches.get(i);
+ branchTrackers.get(i).insertCommentsBefore(branch);
+ }
+ return newBlock;
+ }
+
+ // rule changes inside, must be copied
+ private String generateBranch(PsiSwitchLabeledRuleStatement rule,
+ CommentTracker ct,
+ PsiSwitchBlock switchBlock) {
+ StreamEx.ofTree((PsiElement)rule, el -> StreamEx.of(el.getChildren()))
+ .select(PsiBreakStatement.class)
+ .filter(breakStatement -> breakStatement.getValueExpression() != null && breakStatement.findExitedElement() == switchBlock)
+ .forEach(breakStatement -> handleBreakInside(breakStatement, ct));
+ PsiExpressionList caseValues = rule.getCaseValues();
+ String caseValuesText = caseValues == null ? "" : ct.text(caseValues);
+ PsiStatement body = rule.getBody();
+ String finalBody;
+ if (!(body instanceof PsiBlockStatement) && body != null) {
+ finalBody = generateExpressionBranch(body, ct);
+ } else {
+ finalBody = StreamEx.of(ControlFlowUtils.unwrapBlock(body))
+ .map(el -> ct.text(el))
+ .joining("\n");
+ }
+ ct.grabComments(rule);
+
+
+ String prefix = rule.isDefaultCase() ? "default" : "case " + caseValuesText;
+ return prefix + ":" + finalBody;
+ }
+
+ abstract void handleBreakInside(@NotNull PsiBreakStatement breakStatement, CommentTracker ct);
+
+ abstract String generateExpressionBranch(@NotNull PsiStatement statement, CommentTracker ct);
+ }
+
+ private static class ReturnSwitchGenerator extends SwitchGenerator {
+ ReturnSwitchGenerator(PsiSwitchBlock switchBlock) {
+ super(switchBlock);
+ }
+
+ @Override
+ void handleBreakInside(@NotNull PsiBreakStatement breakStatement, CommentTracker ct) {
+ PsiExpression valueExpression = breakStatement.getValueExpression();
+ assert valueExpression != null;
+ PsiStatement replacement = myFactory.createStatementFromText("return " + ct.text(valueExpression) + ";", breakStatement);
+ ct.markUnchanged(valueExpression);
+ ct.grabComments(breakStatement);
+ breakStatement.replace(replacement);
+ }
+
+ @Override
+ String generateExpressionBranch(@NotNull PsiStatement statement, CommentTracker ct) {
+ return "return " + ct.text(statement);
+ }
+ }
+
+ private static class VarSavingSwitchGenerator extends SwitchGenerator {
+ private final @NotNull PsiLocalVariable myVariable;
+
+ VarSavingSwitchGenerator(PsiSwitchBlock switchBlock, @NotNull PsiLocalVariable variable) {
+ super(switchBlock);
+ myVariable = variable;
+ }
+
+ @Override
+ void handleBreakInside(@NotNull PsiBreakStatement breakStatement, CommentTracker ct) {
+ PsiExpression valueExpression = breakStatement.getValueExpression();
+ assert valueExpression != null;
+ String assignText = myVariable.getName() + " = " + valueExpression.getText() + ";\n";
+ PsiStatement assignment = myFactory.createStatementFromText(assignText, valueExpression);
+ ct.markUnchanged(valueExpression);
+ ct.grabComments(breakStatement);
+ PsiStatement newAssignment = (PsiStatement)breakStatement.replace(assignment);
+ BlockUtils.addAfter(newAssignment, myFactory.createStatementFromText("break;", null));
+ }
+
+ @Override
+ String generateExpressionBranch(@NotNull PsiStatement statement, CommentTracker ct) {
+ return myVariable.getName() + " = " + ct.text(statement) + "\nbreak;";
+ }
+ }
+
+ private static class SwitchStatementGenerator extends SwitchGenerator {
+ SwitchStatementGenerator(PsiSwitchBlock switchBlock) {
+ super(switchBlock);
+ }
+
+ @Override
+ void handleBreakInside(@NotNull PsiBreakStatement breakStatement, CommentTracker ct) {
+ // impossible, only if code is already broken, it can happen
+ }
+
+ @Override
+ String generateExpressionBranch(@NotNull PsiStatement statement, CommentTracker ct) {
+ return ct.text(statement) + "\nbreak;";
+ }
+ }
+}
diff --git a/java/java-impl/src/inspectionDescriptions/EnhancedSwitchBackwardMigration.html b/java/java-impl/src/inspectionDescriptions/EnhancedSwitchBackwardMigration.html
new file mode 100644
index 000000000000..3011472d270b
--- /dev/null
+++ b/java/java-impl/src/inspectionDescriptions/EnhancedSwitchBackwardMigration.html
@@ -0,0 +1,10 @@
+
+
+
+ Reports 'switch' statements, which can be replaced with enhanced 'switch' statement or expression.
+
+Available if the language level is at least Java 12 Preview.
+
+New in 2019.1
+
+
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturning.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturning.java
new file mode 100644
index 000000000000..4621d588eb41
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturning.java
@@ -0,0 +1,21 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ switch (x) {
+ case 1:
+ if (true)
+ return 0;
+ else
+ return 1;
+ case 2:
+ return 2;
+ case 3, 4:
+ System.out.println("asda");
+ return 3;
+ default:
+ return 12;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturningComments.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturningComments.java
new file mode 100644
index 000000000000..ff953d4fb6f0
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturningComments.java
@@ -0,0 +1,25 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ /*1*//*3*//*4*//*6*//*7*//*8*//*18*//*2*/
+ switch (x +/*5*/ x) {/*14*//*9*//*11*/
+ case 1 +/*10*/ 1:
+ if (true /*12*/)
+ /*13*/ return 0;
+ else
+ return 1;
+ /*15*/
+ /*16*/
+ case 2:
+ return 2 +/*17*/ 2;
+ case 3, 4:
+ System.out.println("asda");
+ return 3;
+ /*19*/
+ default:
+ return 12 /*20*/ + 12;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturningWithNestedSwitch.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturningWithNestedSwitch.java
new file mode 100644
index 000000000000..1f10c49719ef
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchReturningWithNestedSwitch.java
@@ -0,0 +1,23 @@
+// "Replace with old style 'switch' statement" "true"
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ switch (x) {
+ case 1:
+ if (true) {
+ return 0;
+ } else {
+ return 1;
+ }
+ case 2:
+ return switch (1) {
+ case 1 -> {
+ break 12;
+ }
+ default -> 55;
+ };
+ default:
+ return 12;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchStatements.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchStatements.java
new file mode 100644
index 000000000000..2f479b089a87
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchStatements.java
@@ -0,0 +1,17 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static String m(int n) {
+ /*1*/
+ /*3*/
+ switch (n +/*cond*/ n) {/*case*/
+ case 1:
+ System.out.println("a"/*2*/);
+ break;
+ case 2:
+ System.out.println("b");
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigning.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigning.java
new file mode 100644
index 000000000000..ccc0b5f93e2f
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigning.java
@@ -0,0 +1,28 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ int x;
+ switch (x) {
+ case 1:
+ if (true) {
+ x = 0;
+ break;
+ } else {
+ x = 1;
+ break;
+ }
+ case 2:
+ x = 2;
+ break;
+ case 3, 4:
+ System.out.println("asda");
+ x = 3;
+ break;
+ default:
+ x = 12;
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigningComments.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigningComments.java
new file mode 100644
index 000000000000..0ac9b558f2f5
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigningComments.java
@@ -0,0 +1,32 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ /*4*/
+ /*1*/
+ /*2*/
+ /*3*/
+ int x;
+ switch (x +/*cond*/ x) {/*5*/
+ case 1:
+ if (true) {
+ x = 0;
+ break;
+ } else {
+ x = 1;
+ break;
+ }
+ case 2:
+ x = 2;
+ break;
+ case 3, 4:
+ System.out.println("asda");
+ x = 3;
+ break;
+ default:
+ x = 12/*6*/;
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigningInferred.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigningInferred.java
new file mode 100644
index 000000000000..677212e92a6c
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/afterSwitchVarAssigningInferred.java
@@ -0,0 +1,16 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ int y;
+ switch (x) {
+ case 1:
+ y = 1;
+ break;
+ default:
+ y = 0;
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturning.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturning.java
new file mode 100644
index 000000000000..1b7d717ffa57
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturning.java
@@ -0,0 +1,20 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ return switch (x) {
+ case 1 -> {if (true)
+ break 0;
+ else
+ break 1;
+ }
+ case 2 -> 2;
+ case 3, 4 -> {
+ System.out.println("asda");
+ break 3;
+ }
+ default -> 12;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturningComments.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturningComments.java
new file mode 100644
index 000000000000..38f742e6ca0e
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturningComments.java
@@ -0,0 +1,20 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ /*1*/return/*2*/ switch /*3*/(/*4*/x +/*5*/ x/*6*/) /*7*/ {
+ /*8*/case /*9*/ 1 +/*10*/ 1 -> /*11*/{if (true /*12*/)
+ /*13*/break /*14*/ 0;
+ else
+ break 1;
+ }
+ case/*15*/ 2 -> /*16*/2 +/*17*/ 2;
+ case 3, 4 -> {
+ System.out.println("asda");
+ break 3;
+ }
+ /*18*/default/*19*/ -> 12 /*20*/ + 12;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturningWithNestedSwitch.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturningWithNestedSwitch.java
new file mode 100644
index 000000000000..d6a1f4f3bc9b
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchReturningWithNestedSwitch.java
@@ -0,0 +1,23 @@
+// "Replace with old style 'switch' statement" "true"
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ return switch (x){
+ case 1 -> {
+ if (true) {
+ break 0;
+ }
+ else {
+ break 1;
+ }
+ }
+ case 2 -> switch (1) {
+ case 1 -> {
+ break 12;
+ }
+ default -> 55;
+ };
+ default -> 12;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchStatements.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchStatements.java
new file mode 100644
index 000000000000..c294b253616b
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchStatements.java
@@ -0,0 +1,12 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static String m(int n) {
+ switch (n +/*cond*/ n) {
+ /*1*/
+ case /*case*/1 -> System.out.println("a"/*2*/); /*3*/
+ case 2 -> System.out.println("b");
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigning.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigning.java
new file mode 100644
index 000000000000..d3d459a20067
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigning.java
@@ -0,0 +1,20 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ int x = switch (x) {
+ case 1 -> {if (true)
+ break 0;
+ else
+ break 1;
+ }
+ case 2 -> 2;
+ case 3, 4 -> {
+ System.out.println("asda");
+ break 3;
+ }
+ default -> 12;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigningComments.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigningComments.java
new file mode 100644
index 000000000000..6ba44f865df7
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigningComments.java
@@ -0,0 +1,20 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ int/*1*/ x /*2*/= /*3*/switch/*4*/ (x +/*cond*/ x) {
+ case 1 -> {if (true)
+ break /*5*/0;
+ else
+ break 1;
+ }
+ case 2 -> 2;
+ case 3, 4 -> {
+ System.out.println("asda");
+ break 3;
+ }
+ default -> 12/*6*/;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigningInferred.java b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigningInferred.java
new file mode 100644
index 000000000000..be0fb079ebc9
--- /dev/null
+++ b/java/java-tests/testData/inspection/switchExpressionBackwardMigration/beforeSwitchVarAssigningInferred.java
@@ -0,0 +1,11 @@
+// "Replace with old style 'switch' statement" "true"
+import java.util.*;
+
+class SwitchExpressionMigration {
+ private static void m(int x) {
+ var y = switch (x) {
+ case 1 -> 1;
+ default -> 0;
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/EnhancedSwitchBackwardMigrationInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/EnhancedSwitchBackwardMigrationInspectionTest.java
new file mode 100644
index 000000000000..9de8fbc1968f
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/EnhancedSwitchBackwardMigrationInspectionTest.java
@@ -0,0 +1,28 @@
+// Copyright 2000-2018 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.EnhancedSwitchBackwardMigrationInspection;
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.pom.java.LanguageLevel;
+import org.jetbrains.annotations.NotNull;
+
+public class EnhancedSwitchBackwardMigrationInspectionTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[]{
+ new EnhancedSwitchBackwardMigrationInspection()
+ };
+ }
+
+ @Override
+ protected String getBasePath() {
+ return "/inspection/switchExpressionBackwardMigration/";
+ }
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_12_PREVIEW;
+ }
+}
diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties
index 5e7c63f374d1..c3274cb9b59a 100644
--- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties
@@ -1034,6 +1034,11 @@ inspection.switch.expression.migration.inspection.if.name=If statement can be re
inspection.replace.with.switch.expression.fix.name=Replace with 'switch' expression
inspection.replace.with.enhanced.switch.statement.fix.name=Replace with enhanced 'switch' statement
+inspection.switch.expression.backward.migration.inspection.name='switch' expression can be replaced with old style 'switch' statement
+inspection.switch.expression.backward.expression.migration.inspection.name='switch' expression can be replaced with old style 'switch' statement
+inspection.switch.expression.backward.statement.migration.inspection.name='switch' statement can be replaced with old style 'switch' statement
+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.fix.family.name=Merge duplicate branches of 'switch' statement