Quick fix "add when remaining branches" refactoring + enum / sealed generated name w/o package name

This commit is contained in:
Mikhail Glukhikh
2016-01-12 15:24:23 +03:00
parent 0a3631db6a
commit c3cce53aa2
13 changed files with 58 additions and 39 deletions
@@ -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 {
@@ -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
@@ -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<KtWhenExpression>(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<out PsiElement>? {
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<out PsiElement>? {
val whenExpression = diagnostic.psiElement.getNonStrictParentOfType<KtWhenExpression>() ?: return null
return AddWhenRemainingBranchesFix(whenExpression)
}
}
}
@@ -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())
@@ -1,4 +1,5 @@
// "Add remaining branches" "true"
// ERROR: Unresolved reference: TODO
fun test(b: Boolean) = wh<caret>en(b) {
false -> 0
}
@@ -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()
}
@@ -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) = wh<caret>en(c) {
Color.B -> 0xff
@@ -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()
}
@@ -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) = wh<caret>en(c) {
Color.B -> 0xff
}
@@ -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()
}
@@ -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()
@@ -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()
}
@@ -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");