diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt index 3f094c0976f..4ec6e13fb49 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/BranchedFoldingUtils.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.intentions.branchedTransformations +import org.jetbrains.kotlin.cfg.WhenChecker import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.branches import org.jetbrains.kotlin.lexer.KtTokens @@ -60,7 +61,7 @@ object BranchedFoldingUtils { fun collectAssignmentsAndCheck(e: KtExpression?): Boolean = when (e) { is KtWhenExpression -> { val entries = e.entries - KtPsiUtil.checkWhenExpressionHasSingleElse(e) && + !e.hasMissingCases() && entries.isNotEmpty() && entries.all { entry -> val assignment = getFoldableBranchedAssignment(entry.expression)?.run { assignments.add(this) } @@ -128,7 +129,7 @@ object BranchedFoldingUtils { is KtWhenExpression -> { val entries = expression.entries when { - !KtPsiUtil.checkWhenExpressionHasSingleElse(expression) -> null + expression.hasMissingCases() -> null entries.isEmpty() -> null else -> getFoldableReturns(entries.map { it.expression }) } @@ -211,4 +212,7 @@ object BranchedFoldingUtils { private fun KtTryExpression.tryBlockAndCatchBodies(): List = listOf(tryBlock) + catchClauses.map { it.catchBody } + private fun KtWhenExpression.hasMissingCases(): Boolean = + !KtPsiUtil.checkWhenExpressionHasSingleElse(this) && WhenChecker.getMissingCases(this, this.analyze()).isNotEmpty() + } diff --git a/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasMissingCase.kt b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasMissingCase.kt new file mode 100644 index 00000000000..8cd145ff714 --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasMissingCase.kt @@ -0,0 +1,16 @@ +// PROBLEM: none + +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + var res: Int = 0 + + when (e) { + TestEnum.A -> res = 1 + TestEnum.B -> res = 2 + } + + return res +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt new file mode 100644 index 00000000000..bc63867062b --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt @@ -0,0 +1,15 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + var res: Int = 0 + + when (e) { + TestEnum.A -> res = 1 + TestEnum.B -> res = 2 + TestEnum.C -> res = 3 + } + + return res +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt.after b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt.after new file mode 100644 index 00000000000..fddc30ad642 --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt.after @@ -0,0 +1,15 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + var res: Int = 0 + + res = when (e) { + TestEnum.A -> 1 + TestEnum.B -> 2 + TestEnum.C -> 3 + } + + return res +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt new file mode 100644 index 00000000000..0a43a26dab5 --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt @@ -0,0 +1,15 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + var res: Int = 0 + + when (e) { + TestEnum.A -> res = 1 + TestEnum.B -> res = 2 + else -> res = 3 + } + + return res +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt.after b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt.after new file mode 100644 index 00000000000..f1f79105a54 --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt.after @@ -0,0 +1,15 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + var res: Int = 0 + + res = when (e) { + TestEnum.A -> 1 + TestEnum.B -> 2 + else -> 3 + } + + return res +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasMissingCase.kt b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasMissingCase.kt new file mode 100644 index 00000000000..ddb360ec274 --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasMissingCase.kt @@ -0,0 +1,13 @@ +// ERROR: A 'return' expression required in a function with a block body ('{...}') +// PROBLEM: none + +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + when (e) { + TestEnum.A -> return 1 + TestEnum.B -> return 2 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt new file mode 100644 index 00000000000..c2f8a36ceba --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt @@ -0,0 +1,11 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + when (e) { + TestEnum.A -> return 1 + TestEnum.B -> return 2 + TestEnum.C -> return 3 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt.after b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt.after new file mode 100644 index 00000000000..8101a6a4a94 --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt.after @@ -0,0 +1,11 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + return when (e) { + TestEnum.A -> 1 + TestEnum.B -> 2 + TestEnum.C -> 3 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt new file mode 100644 index 00000000000..b8dc3e1452f --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt @@ -0,0 +1,11 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + when (e) { + TestEnum.A -> return 1 + TestEnum.B -> return 2 + else -> return 3 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt.after b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt.after new file mode 100644 index 00000000000..c309d2c22ab --- /dev/null +++ b/idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt.after @@ -0,0 +1,11 @@ +enum class TestEnum{ + A, B, C +} + +fun test(e: TestEnum): Int { + return when (e) { + TestEnum.A -> 1 + TestEnum.B -> 2 + else -> 3 + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index d1402003074..8f3f4c0626d 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -873,6 +873,24 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToAssignment/simpleWhenWithoutTerminatingAssignment.kt"); doTest(fileName); } + + @TestMetadata("whenHasMissingCase.kt") + public void testWhenHasMissingCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasMissingCase.kt"); + doTest(fileName); + } + + @TestMetadata("whenHasNoMissingCase.kt") + public void testWhenHasNoMissingCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCase.kt"); + doTest(fileName); + } + + @TestMetadata("whenHasNoMissingCaseWithElse.kt") + public void testWhenHasNoMissingCaseWithElse() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToAssignment/whenHasNoMissingCaseWithElse.kt"); + doTest(fileName); + } } @TestMetadata("idea/testData/inspectionsLocal/liftOut/whenToReturn") @@ -925,6 +943,24 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { doTest(fileName); } + @TestMetadata("whenHasMissingCase.kt") + public void testWhenHasMissingCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasMissingCase.kt"); + doTest(fileName); + } + + @TestMetadata("whenHasNoMissingCase.kt") + public void testWhenHasNoMissingCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCase.kt"); + doTest(fileName); + } + + @TestMetadata("whenHasNoMissingCaseWithElse.kt") + public void testWhenHasNoMissingCaseWithElse() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToReturn/whenHasNoMissingCaseWithElse.kt"); + doTest(fileName); + } + @TestMetadata("whenOneReturn.kt") public void testWhenOneReturn() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/liftOut/whenToReturn/whenOneReturn.kt");