diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt index 1880bbfc491..685a7fafd23 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt @@ -38,13 +38,12 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import java.util.* -interface WhenMissingCase { - - val branchConditionText: String +sealed class WhenMissingCase { + abstract val branchConditionText: String } // Always must be first in the list -private object UnknownMissingCase : WhenMissingCase { +object UnknownMissingCase : WhenMissingCase() { override fun toString() = "unknown" override val branchConditionText = "else" @@ -64,7 +63,7 @@ private interface WhenExhaustivenessChecker { fun isApplicable(subjectType: KotlinType): Boolean = false } -private object NullMissingCase : WhenMissingCase { +object NullMissingCase : WhenMissingCase() { override fun toString() = branchConditionText override val branchConditionText = "null" @@ -92,7 +91,7 @@ private object WhenOnNullableExhaustivenessChecker /* : WhenExhaustivenessChecke } } -private class BooleanMissingCase(val b: Boolean) : WhenMissingCase { +class BooleanMissingCase(val b: Boolean) : WhenMissingCase() { override fun toString() = branchConditionText override val branchConditionText = b.toString() @@ -127,12 +126,14 @@ private object WhenOnBooleanExhaustivenessChecker : WhenExhaustivenessChecker { } } -private class ClassMissingCase(val descriptor: ClassDescriptor): WhenMissingCase { - override fun toString() = descriptor.name.identifier.let { if (descriptor.kind.isSingleton) it else "is $it" } +class ClassMissingCase(val descriptor: ClassDescriptor): WhenMissingCase() { + val classIsSingleton get() = descriptor.kind.isSingleton - override val branchConditionText = DescriptorUtils.getFqNameFromTopLevelClass(descriptor).asString().let { - if (descriptor.kind.isSingleton) it else "is $it" - } + val classFqName get() = DescriptorUtils.getFqNameFromTopLevelClass(descriptor) + + override fun toString() = descriptor.name.identifier.let { if (classIsSingleton) it else "is $it" } + + override val branchConditionText = classFqName.asString().let { if (classIsSingleton) it else "is $it" } } internal abstract class WhenOnClassExhaustivenessChecker : WhenExhaustivenessChecker { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt index 535095f836e..0d7917d01cf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt @@ -20,10 +20,11 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.cfg.WhenChecker -import org.jetbrains.kotlin.cfg.hasUnknown +import org.jetbrains.kotlin.cfg.* import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.core.quoteIfNeeded +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtWhenExpression @@ -49,7 +50,18 @@ class AddWhenRemainingBranchesFix(expression: KtWhenExpression) : KotlinQuickFix val psiFactory = KtPsiFactory(file) for (case in missingCases) { - val entry = psiFactory.createWhenEntry("${case.branchConditionText} -> TODO()") + val branchConditionText = when (case) { + UnknownMissingCase, NullMissingCase, is BooleanMissingCase -> + case.branchConditionText + is ClassMissingCase -> + if (case.classIsSingleton) { + case.classFqName.quoteIfNeeded().asString() + } + else { + "is " + case.classFqName.quoteIfNeeded().asString() + } + } + val entry = psiFactory.createWhenEntry("$branchConditionText -> TODO()") element.addBefore(entry, whenCloseBrace) } } diff --git a/idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt b/idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt new file mode 100644 index 00000000000..8ff899d64eb --- /dev/null +++ b/idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt @@ -0,0 +1,10 @@ +// "Add remaining branches" "true" +// WITH_RUNTIME + +enum class FooEnum { + A, B, `C`, `true`, `false`, `null` +} + +fun test(foo: FooEnum?) = when (foo) { + FooEnum.A -> "A" +} \ No newline at end of file diff --git a/idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt.after b/idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt.after new file mode 100644 index 00000000000..4497f9cd83c --- /dev/null +++ b/idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt.after @@ -0,0 +1,16 @@ +// "Add remaining branches" "true" +// WITH_RUNTIME + +enum class FooEnum { + A, B, `C`, `true`, `false`, `null` +} + +fun test(foo: FooEnum?) = when (foo) { + FooEnum.A -> "A" + FooEnum.B -> TODO() + FooEnum.C -> TODO() + FooEnum.`true` -> TODO() + FooEnum.`false` -> TODO() + FooEnum.`null` -> TODO() + null -> TODO() +} \ No newline at end of file diff --git a/idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt b/idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt new file mode 100644 index 00000000000..2ed61b520bf --- /dev/null +++ b/idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt @@ -0,0 +1,15 @@ +// "Add remaining branches" "true" +// WITH_RUNTIME + +sealed class FooSealed +object A: FooSealed() +object B: FooSealed() +object `C`: FooSealed() +class D: FooSealed() +class `true`: FooSealed() +class `false`: FooSealed() +object `null`: FooSealed() + +fun test(foo: FooSealed?) = when (foo) { + A -> "A" +} \ No newline at end of file diff --git a/idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt.after b/idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt.after new file mode 100644 index 00000000000..c26a61bb144 --- /dev/null +++ b/idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt.after @@ -0,0 +1,22 @@ +// "Add remaining branches" "true" +// WITH_RUNTIME + +sealed class FooSealed +object A: FooSealed() +object B: FooSealed() +object `C`: FooSealed() +class D: FooSealed() +class `true`: FooSealed() +class `false`: FooSealed() +object `null`: FooSealed() + +fun test(foo: FooSealed?) = when (foo) { + A -> "A" + B -> TODO() + C -> TODO() + is D -> TODO() + is `true` -> TODO() + is `false` -> TODO() + `null` -> TODO() + null -> TODO() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 75ed6817de8..2f453f88c21 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -11755,6 +11755,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("addRemainingBranchesEnumBackTicks.kt") + public void testAddRemainingBranchesEnumBackTicks() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/when/addRemainingBranchesEnumBackTicks.kt"); + doTest(fileName); + } + @TestMetadata("addRemainingBranchesEnumStatement.kt") public void testAddRemainingBranchesEnumStatement() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/when/addRemainingBranchesEnumStatement.kt"); @@ -11773,6 +11779,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("addRemainingBranchesSealedBackTicks.kt") + public void testAddRemainingBranchesSealedBackTicks() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/when/addRemainingBranchesSealedBackTicks.kt"); + doTest(fileName); + } + @TestMetadata("addRemainingBranchesSealedStatement.kt") public void testAddRemainingBranchesSealedStatement() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/when/addRemainingBranchesSealedStatement.kt");