From c3cce53aa2c68f7e8ffa02438d343e8819254ba4 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 12 Jan 2016 15:24:23 +0300 Subject: [PATCH] Quick fix "add when remaining branches" refactoring + enum / sealed generated name w/o package name --- .../org/jetbrains/kotlin/cfg/WhenChecker.kt | 5 ++- .../kotlin/idea/KotlinBundle.properties | 2 - .../quickfix/AddWhenRemainingBranchesFix.kt | 40 ++++++------------- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 2 +- .../when/addRemainingBranchesBoolean.kt | 1 + .../when/addRemainingBranchesBoolean.kt.after | 3 +- .../quickfix/when/addRemainingBranchesEnum.kt | 2 + .../when/addRemainingBranchesEnum.kt.after | 6 ++- ...addRemainingBranchesInNonDefaultPackage.kt | 8 ++++ ...ainingBranchesInNonDefaultPackage.kt.after | 10 +++++ .../when/addRemainingBranchesSealed.kt | 3 ++ .../when/addRemainingBranchesSealed.kt.after | 9 +++-- .../idea/quickfix/QuickFixTestGenerated.java | 6 +++ 13 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt create mode 100644 idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt index aea913189bd..c62329b59b0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.kt @@ -37,7 +37,6 @@ import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumClass import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import java.util.* interface WhenMissingCase { @@ -132,7 +131,9 @@ 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" } - override val branchConditionText = descriptor.fqNameSafe.asString().let { if (descriptor.kind.isSingleton) it else "is $it" } + override val branchConditionText = DescriptorUtils.getFqNameFromTopLevelClass(descriptor).asString().let { + if (descriptor.kind.isSingleton) it else "is $it" + } } private abstract class WhenOnClassExhaustivenessChecker : WhenExhaustivenessChecker { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties index 2a1bdf208c5..978c737a23c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties @@ -150,8 +150,6 @@ remove.val.var.from.parameter=Remove ''{0}'' from parameter add.override.to.equals.hashCode.toString=Add 'override' to equals, hashCode, toString in project add.when.else.branch.action.family.name=Add else branch add.when.else.branch.action=Add else branch -add.when.remaining.branches.action.family.name=Add remaining branches -add.when.remaining.branches.action=Add remaining branches move.when.else.branch.to.the.end.action=Move else branch to the end move.when.else.branch.to.the.end.family.name=Move else branch to the end change.to.property.name.family.name=Change to property name diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt index 13eaacebd80..acb85ab29e0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddWhenRemainingBranchesFix.kt @@ -16,20 +16,18 @@ package org.jetbrains.kotlin.idea.quickfix -import com.intellij.codeInsight.CodeInsightUtilCore import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile -import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.cfg.WhenChecker import org.jetbrains.kotlin.cfg.hasUnknown import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtWhenEntry import org.jetbrains.kotlin.psi.KtWhenExpression +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType class AddWhenRemainingBranchesFix(expression: KtWhenExpression) : KotlinQuickFixAction(expression) { @@ -37,10 +35,11 @@ class AddWhenRemainingBranchesFix(expression: KtWhenExpression) : KotlinQuickFix override fun getText() = "Add remaining branches" - override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { - return super.isAvailable(project, editor, file) && element.closeBrace != null && - !WhenChecker.getNecessaryCases(element, element.analyze()).hasUnknown - } + override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean = + super.isAvailable(project, editor, file) && element.closeBrace != null && + with(WhenChecker.getNecessaryCases(element, element.analyze())) { + isNotEmpty() && !hasUnknown + } override fun invoke(project: Project, editor: Editor?, file: KtFile) { val necessaryCases = WhenChecker.getNecessaryCases(element, element.analyze()) @@ -48,33 +47,18 @@ class AddWhenRemainingBranchesFix(expression: KtWhenExpression) : KotlinQuickFix val whenCloseBrace = element.closeBrace assert(whenCloseBrace != null) { "isAvailable should check if close brace exist" } val psiFactory = KtPsiFactory(file) - var insertedBranch: PsiElement? = null for (case in necessaryCases) { - val entry = psiFactory.createWhenEntry("${case.branchConditionText} -> throw AssertionError(\"\")") - insertedBranch = element.addBefore(entry, whenCloseBrace) + val entry = psiFactory.createWhenEntry("${case.branchConditionText} -> TODO()") + val insertedBranch = element.addBefore(entry, whenCloseBrace) element.addAfter(psiFactory.createNewLine(), insertedBranch) - - } - - if (insertedBranch != null) { - val insertedWhenEntry = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(insertedBranch) as KtWhenEntry - val textRange = insertedWhenEntry.textRange - val indexOfOpenBrace = insertedWhenEntry.text.indexOf('{') - editor!!.caretModel.moveToOffset(textRange.startOffset + indexOfOpenBrace + 1) } } - companion object { - @JvmStatic - fun createFactory(): KotlinSingleIntentionActionFactory { - return object : KotlinSingleIntentionActionFactory() { - public override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { - val element = diagnostic.psiElement - val whenExpression = PsiTreeUtil.getParentOfType(element, KtWhenExpression::class.java, false) ?: return null - return AddWhenRemainingBranchesFix(whenExpression) - } - } + companion object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { + val whenExpression = diagnostic.psiElement.getNonStrictParentOfType() ?: return null + return AddWhenRemainingBranchesFix(whenExpression) } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 6cf3df9c370..b67b5ed73d1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -189,7 +189,7 @@ class QuickFixRegistrar : QuickFixContributor { ELSE_MISPLACED_IN_WHEN.registerFactory(MoveWhenElseBranchFix.createFactory()) NO_ELSE_IN_WHEN.registerFactory(AddWhenElseBranchFix.createFactory()) - NO_ELSE_IN_WHEN.registerFactory(AddWhenRemainingBranchesFix.createFactory()) + NO_ELSE_IN_WHEN.registerFactory(AddWhenRemainingBranchesFix) BREAK_OR_CONTINUE_IN_WHEN.registerFactory(AddLoopLabelFix) NO_TYPE_ARGUMENTS_ON_RHS.registerFactory(AddStarProjectionsFix.createFactoryForIsExpression()) diff --git a/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt b/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt index 2b8fdece1b4..bc8e9e031cc 100644 --- a/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt +++ b/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt @@ -1,4 +1,5 @@ // "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO fun test(b: Boolean) = when(b) { false -> 0 } diff --git a/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt.after b/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt.after index 774e4658dc9..9f9f71c7a01 100644 --- a/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt.after +++ b/idea/testData/quickfix/when/addRemainingBranchesBoolean.kt.after @@ -1,5 +1,6 @@ // "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO fun test(b: Boolean) = when(b) { false -> 0 - true -> throw AssertionError("") + true -> TODO() } diff --git a/idea/testData/quickfix/when/addRemainingBranchesEnum.kt b/idea/testData/quickfix/when/addRemainingBranchesEnum.kt index 813c355e766..477ec32bb25 100644 --- a/idea/testData/quickfix/when/addRemainingBranchesEnum.kt +++ b/idea/testData/quickfix/when/addRemainingBranchesEnum.kt @@ -1,4 +1,6 @@ // "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO enum class Color { R, G, B } fun test(c: Color) = when(c) { Color.B -> 0xff diff --git a/idea/testData/quickfix/when/addRemainingBranchesEnum.kt.after b/idea/testData/quickfix/when/addRemainingBranchesEnum.kt.after index 7e12c8c35f3..28b04c4c7ee 100644 --- a/idea/testData/quickfix/when/addRemainingBranchesEnum.kt.after +++ b/idea/testData/quickfix/when/addRemainingBranchesEnum.kt.after @@ -1,7 +1,9 @@ // "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO enum class Color { R, G, B } fun test(c: Color) = when(c) { Color.B -> 0xff - Color.R -> throw AssertionError("") - Color.G -> throw AssertionError("") + Color.R -> TODO() + Color.G -> TODO() } diff --git a/idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt b/idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt new file mode 100644 index 00000000000..ed81538bb48 --- /dev/null +++ b/idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt @@ -0,0 +1,8 @@ +// "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO +package test +enum class Color { R, G, B } +fun test(c: Color) = when(c) { + Color.B -> 0xff +} diff --git a/idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt.after b/idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt.after new file mode 100644 index 00000000000..6c5cc283db7 --- /dev/null +++ b/idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt.after @@ -0,0 +1,10 @@ +// "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO +package test +enum class Color { R, G, B } +fun test(c: Color) = when(c) { + Color.B -> 0xff + Color.R -> TODO() + Color.G -> TODO() +} diff --git a/idea/testData/quickfix/when/addRemainingBranchesSealed.kt b/idea/testData/quickfix/when/addRemainingBranchesSealed.kt index 042dcf6a0e3..199276d3064 100644 --- a/idea/testData/quickfix/when/addRemainingBranchesSealed.kt +++ b/idea/testData/quickfix/when/addRemainingBranchesSealed.kt @@ -1,4 +1,7 @@ // "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO sealed class Variant { object Singleton : Variant() diff --git a/idea/testData/quickfix/when/addRemainingBranchesSealed.kt.after b/idea/testData/quickfix/when/addRemainingBranchesSealed.kt.after index 910ba32fb5e..a8c8961cbe3 100644 --- a/idea/testData/quickfix/when/addRemainingBranchesSealed.kt.after +++ b/idea/testData/quickfix/when/addRemainingBranchesSealed.kt.after @@ -1,4 +1,7 @@ // "Add remaining branches" "true" +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO +// ERROR: Unresolved reference: TODO sealed class Variant { object Singleton : Variant() @@ -8,7 +11,7 @@ sealed class Variant { } fun test(v: Variant?) = when(v) { Variant.Singleton -> "s" - is Variant.Something -> throw AssertionError("") - Variant.Another -> throw AssertionError("") - null -> throw AssertionError("") + is Variant.Something -> TODO() + Variant.Another -> TODO() + null -> TODO() } diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 7505e6ad889..3c9dbdc5897 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -7580,6 +7580,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("addRemainingBranchesInNonDefaultPackage.kt") + public void testAddRemainingBranchesInNonDefaultPackage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt"); + doTest(fileName); + } + @TestMetadata("addRemainingBranchesSealed.kt") public void testAddRemainingBranchesSealed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/when/addRemainingBranchesSealed.kt");