FIR IDE: AddWhenRemainingBranchFix

The fix reuses logic that is already available from
FirWhenExhaustivenessTransformer to collect missing when branches. The
current logic unfortunately uses hackyAllowRunningOnEdt to shorten the
generated code.
This commit is contained in:
Tianyu Geng
2021-05-30 19:08:22 -07:00
committed by Ilya Kirillov
parent 6ec247b861
commit 63c65edda2
34 changed files with 319 additions and 77 deletions
@@ -33,6 +33,59 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
WhenOnEnumExhaustivenessChecker,
WhenOnSealedClassExhaustivenessChecker
)
@OptIn(ExperimentalStdlibApi::class)
fun computeAllMissingCases(session: FirSession, whenExpression: FirWhenExpression): List<WhenMissingCase> {
val subjectType = getSubjectType(session, whenExpression) ?: return emptyList()
return buildList {
for (type in subjectType.unwrapIntersectionType()) {
val checkers = getCheckers(type, session)
collectMissingCases(checkers, whenExpression, type, session)
}
}
}
private fun getSubjectType(session: FirSession, whenExpression: FirWhenExpression): ConeKotlinType? {
val subjectType = whenExpression.subjectVariable?.returnTypeRef?.coneType
?: whenExpression.subject?.typeRef?.coneType
?: return null
return subjectType.fullyExpandedType(session).lowerBoundIfFlexible()
}
private fun ConeKotlinType.unwrapIntersectionType(): Collection<ConeKotlinType> {
return (this as? ConeIntersectionType)?.intersectedTypes ?: listOf(this)
}
@OptIn(ExperimentalStdlibApi::class)
private fun getCheckers(
subjectType: ConeKotlinType,
session: FirSession
): List<WhenExhaustivenessChecker> {
return buildList {
exhaustivenessCheckers.filterTo<WhenExhaustivenessChecker, MutableCollection<in WhenExhaustivenessChecker>>(this) {
it.isApplicable(subjectType, session)
}
if (isNotEmpty() && subjectType.isMarkedNullable) {
this.add(WhenOnNullableExhaustivenessChecker)
}
}
}
private fun MutableList<WhenMissingCase>.collectMissingCases(
checkers: List<WhenExhaustivenessChecker>,
whenExpression: FirWhenExpression,
subjectType: ConeKotlinType,
session: FirSession
) {
for (checker in checkers) {
checker.computeMissingCases(whenExpression, subjectType, session, this)
}
if (isEmpty() && whenExpression.branches.isEmpty()) {
add(WhenMissingCase.Unknown)
}
}
}
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
@@ -52,21 +105,17 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
}
val session = bodyResolveComponents.session
val subjectType = (whenExpression.subjectVariable?.returnTypeRef?.coneType
?: whenExpression.subject?.typeRef?.coneType)
?.fullyExpandedType(session)?.lowerBoundIfFlexible()
?: run {
whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH)
return
}
val subjectType = getSubjectType(session, whenExpression) ?: run {
whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH)
return
}
if (whenExpression.branches.isEmpty() && subjectType.isNothing) {
whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.ExhaustiveAsNothing)
return
}
val unwrappedIntersectionTypes = (subjectType as? ConeIntersectionType)?.intersectedTypes ?: listOf(subjectType)
val unwrappedIntersectionTypes = subjectType.unwrapIntersectionType()
var status: ExhaustivenessStatus = ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH
@@ -86,30 +135,18 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
whenExpression.replaceExhaustivenessStatus(status)
}
@OptIn(ExperimentalStdlibApi::class)
private fun computeStatusForNonIntersectionType(
unwrappedSubjectType: ConeKotlinType,
session: FirSession,
whenExpression: FirWhenExpression,
): ExhaustivenessStatus {
val checkers = buildList {
exhaustivenessCheckers.filterTo(this) { it.isApplicable(unwrappedSubjectType, session) }
if (isNotEmpty() && unwrappedSubjectType.isMarkedNullable) {
add(WhenOnNullableExhaustivenessChecker)
}
}
val checkers = getCheckers(unwrappedSubjectType, session)
if (checkers.isEmpty()) {
return ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH
}
val whenMissingCases = mutableListOf<WhenMissingCase>()
for (checker in checkers) {
checker.computeMissingCases(whenExpression, unwrappedSubjectType, session, whenMissingCases)
}
if (whenMissingCases.isEmpty() && whenExpression.branches.isEmpty()) {
whenMissingCases.add(WhenMissingCase.Unknown)
}
whenMissingCases.collectMissingCases(checkers, whenExpression, unwrappedSubjectType, session)
return if (whenMissingCases.isEmpty()) {
ExhaustivenessStatus.ProperlyExhaustive
@@ -124,9 +124,6 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
registerApplicator(TypeMismatchFactories.assignmentTypeMismatch)
registerApplicator(TypeMismatchFactories.initializerTypeMismatch)
// TODO: NON_EXHAUSTIVE_WHEN[_ON_SEALED_CLASS] will be replaced in future. We need to register the fix for those diagnostics as well
registerPsiQuickFixes(KtFirDiagnostic.NoElseInWhen::class, AddWhenElseBranchFix)
registerApplicator(WrapWithSafeLetCallFixFactories.forUnsafeCall)
registerApplicator(WrapWithSafeLetCallFixFactories.forUnsafeImplicitInvokeCall)
registerApplicator(WrapWithSafeLetCallFixFactories.forUnsafeInfixCall)
@@ -137,6 +134,12 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
registerPsiQuickFixes(KtFirDiagnostic.InapplicableLateinitModifier::class, RemoveNullableFix.removeForLateInitProperty)
}
private val whenStatements = KtQuickFixesListBuilder.registerPsiQuickFix {
// TODO: NON_EXHAUSTIVE_WHEN[_ON_SEALED_CLASS] will be replaced in future. We need to register the fix for those diagnostics as well
registerPsiQuickFixes(KtFirDiagnostic.NoElseInWhen::class, AddWhenElseBranchFix)
registerApplicator(AddWhenRemainingBranchFixFactories.noElseInWhen)
}
private val typeMismatch = KtQuickFixesListBuilder.registerPsiQuickFix {
registerApplicator(ChangeTypeQuickFixFactories.componentFunctionReturnTypeMismatch)
registerApplicator(ChangeTypeQuickFixFactories.returnTypeMismatch)
@@ -156,6 +159,7 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
imports,
mutability,
expressions,
whenStatements,
typeMismatch
)
}
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.quickfix.fixes
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.api.applicator.HLApplicator
import org.jetbrains.kotlin.idea.api.applicator.HLApplicatorInput
import org.jetbrains.kotlin.idea.api.applicator.applicator
import org.jetbrains.kotlin.idea.fir.api.fixes.HLQuickFix
import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory
import org.jetbrains.kotlin.idea.frontend.api.analyse
import org.jetbrains.kotlin.idea.frontend.api.components.ShortenOption
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassKind
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt
import org.jetbrains.kotlin.idea.util.generateWhenBranches
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtWhenExpression
object AddWhenRemainingBranchFixFactories {
class Input(val whenMissingCases: List<WhenMissingCase>, val enumToStarImport: ClassId?) : HLApplicatorInput
val applicator: HLApplicator<KtWhenExpression, Input> = getApplicator(false)
val applicatorUsingStarImport: HLApplicator<KtWhenExpression, Input> = getApplicator(true)
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
private fun getApplicator(useStarImport: Boolean = false) = applicator<KtWhenExpression, Input> {
familyAndActionName(
if (useStarImport) KotlinBundle.lazyMessage("fix.add.remaining.branches.with.star.import")
else KotlinBundle.lazyMessage("fix.add.remaining.branches")
)
applyTo { whenExpression, input ->
if (useStarImport) assert(input.enumToStarImport != null)
generateWhenBranches(whenExpression, input.whenMissingCases)
val shortenCommand = hackyAllowRunningOnEdt {
analyse(whenExpression) {
collectPossibleReferenceShorteningsInElement(
whenExpression,
callableShortenOption = {
if (useStarImport && it.callableIdIfNonLocal?.classId == input.enumToStarImport) {
ShortenOption.SHORTEN_AND_STAR_IMPORT
} else {
ShortenOption.DO_NOT_SHORTEN
}
})
}
}
shortenCommand.invokeShortening()
}
}
@OptIn(ExperimentalStdlibApi::class)
val noElseInWhen = diagnosticFixFactory(KtFirDiagnostic.NoElseInWhen::class) { diagnostic ->
val whenExpression = diagnostic.psi
val subjectExpression = whenExpression.subjectExpression ?: return@diagnosticFixFactory emptyList()
buildList {
val missingCases = diagnostic.missingWhenCases.takeIf {
it.isNotEmpty() && it.singleOrNull() != WhenMissingCase.Unknown
} ?: return@buildList
add(HLQuickFix(whenExpression, Input(missingCases, null), applicator))
val baseClassSymbol = subjectExpression.getKtType().expandedClassSymbol ?: return@buildList
val enumToStarImport = baseClassSymbol.classIdIfNonLocal
if (baseClassSymbol.classKind == KtClassKind.ENUM_CLASS && enumToStarImport != null) {
add(HLQuickFix(whenExpression, Input(missingCases, enumToStarImport), applicatorUsingStarImport))
}
}
}
}
@@ -1946,6 +1946,21 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes
runTest("idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt");
}
@TestMetadata("addRemainingBranchesMissingLeftBracket.kt")
public void testAddRemainingBranchesMissingLeftBracket() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesMissingLeftBracket.kt");
}
@TestMetadata("addRemainingBranchesMissingRightBracket.kt")
public void testAddRemainingBranchesMissingRightBracket() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesMissingRightBracket.kt");
}
@TestMetadata("addRemainingBranchesMissingRightParenthesis.kt")
public void testAddRemainingBranchesMissingRightParenthesis() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesMissingRightParenthesis.kt");
}
@TestMetadata("addRemainingBranchesSealed.kt")
public void testAddRemainingBranchesSealed() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesSealed.kt");
@@ -5,14 +5,19 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.psi.KtReturnExpression
import org.jetbrains.kotlin.psi.KtWhenExpression
abstract class KtExpressionInfoProvider : KtAnalysisSessionComponent() {
abstract fun getReturnExpressionTargetSymbol(returnExpression: KtReturnExpression): KtCallableSymbol?
abstract fun getWhenMissingCases(whenExpression: KtWhenExpression): List<WhenMissingCase>
}
interface KtExpressionInfoProviderMixIn : KtAnalysisSessionMixIn {
fun KtReturnExpression.getReturnTargetSymbol(): KtCallableSymbol? =
analysisSession.expressionInfoProvider.getReturnExpressionTargetSymbol(this)
fun KtWhenExpression.getMissingCases(): List<WhenMissingCase> = analysisSession.expressionInfoProvider.getWhenMissingCases(this)
}
@@ -5,13 +5,17 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.components.KtExpressionInfoProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.psi.KtReturnExpression
import org.jetbrains.kotlin.psi.KtWhenExpression
internal class KtFirExpressionInfoProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -22,4 +26,9 @@ internal class KtFirExpressionInfoProvider(
val firTargetSymbol = fir.target.labeledElement
return firSymbolBuilder.callableBuilder.buildCallableSymbol(firTargetSymbol)
}
override fun getWhenMissingCases(whenExpression: KtWhenExpression): List<WhenMissingCase> {
val firWhenExpression = whenExpression.getOrBuildFirSafe<FirWhenExpression>(analysisSession.firResolveState) ?: return emptyList()
return FirWhenExhaustivenessTransformer.computeAllMissingCases(analysisSession.firResolveState.rootModuleSession, firWhenExpression)
}
}
@@ -5,18 +5,17 @@
package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.*
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.parentOfType
import com.intellij.psi.util.parentsOfType
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.renderer.render
fun KtElement.getElementTextInContext(): String {
val context = parentOfType<KtImportDirective>()
@@ -60,3 +59,44 @@ fun KtExpression.resultingWhens(): List<KtWhenExpression> = when (this) {
is KtBlockExpression -> statements.lastOrNull()?.resultingWhens() ?: listOf()
else -> listOf()
}
fun generateWhenBranches(element: KtWhenExpression, missingCases: List<WhenMissingCase>) {
val psiFactory = KtPsiFactory(element)
val whenCloseBrace = element.closeBrace ?: run {
val craftingMaterials = psiFactory.createExpression("when(1){}") as KtWhenExpression
if (element.rightParenthesis == null) {
element.addAfter(
craftingMaterials.rightParenthesis!!,
element.subjectExpression ?: throw AssertionError("caller should have checked the presence of subject expression.")
)
}
if (element.openBrace == null) {
element.addAfter(craftingMaterials.openBrace!!, element.rightParenthesis!!)
}
element.addAfter(craftingMaterials.closeBrace!!, element.entries.lastOrNull() ?: element.openBrace!!)
element.closeBrace!!
}
val elseBranch = element.entries.find { it.isElse }
(whenCloseBrace.prevSibling as? PsiWhiteSpace)?.replace(psiFactory.createNewLine())
for (case in missingCases) {
val branchConditionText = when (case) {
WhenMissingCase.Unknown,
WhenMissingCase.NullIsMissing,
is WhenMissingCase.BooleanIsMissing,
is WhenMissingCase.ConditionTypeIsExpect -> case.branchConditionText
is WhenMissingCase.IsTypeCheckIsMissing ->
if (case.isSingleton) {
""
} else {
"is "
} + case.classId.asSingleFqName().render()
is WhenMissingCase.EnumCheckIsMissing -> case.callableId.asSingleFqName().render()
}
val entry = psiFactory.createWhenEntry("$branchConditionText -> TODO()")
if (elseBranch != null) {
element.addBefore(entry, elseBranch)
} else {
element.addBefore(entry, whenCloseBrace)
}
}
}
@@ -19,18 +19,20 @@ package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.cfg.*
import org.jetbrains.kotlin.cfg.WhenChecker
import org.jetbrains.kotlin.cfg.hasUnknown
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
import org.jetbrains.kotlin.idea.intentions.ImportAllMembersIntention
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.util.generateWhenBranches
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtWhenConditionWithExpression
import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
class AddWhenRemainingBranchesFix(
@@ -82,31 +84,7 @@ class AddWhenRemainingBranchesFix(
if (element == null) return
val missingCases = WhenChecker.getMissingCases(element, element.analyze())
val whenCloseBrace = element.closeBrace ?: throw AssertionError("isAvailable should check if close brace exist")
val elseBranch = element.entries.find { it.isElse }
val psiFactory = KtPsiFactory(element)
(whenCloseBrace.prevSibling as? PsiWhiteSpace)?.replace(psiFactory.createNewLine())
for (case in missingCases) {
val branchConditionText = when (case) {
WhenMissingCase.Unknown,
WhenMissingCase.NullIsMissing,
is WhenMissingCase.BooleanIsMissing,
is WhenMissingCase.ConditionTypeIsExpect -> case.branchConditionText
is WhenMissingCase.IsTypeCheckIsMissing ->
if (case.isSingleton) {
""
} else {
"is "
} + case.classId.asSingleFqName().quoteIfNeeded().asString()
is WhenMissingCase.EnumCheckIsMissing -> case.callableId.asSingleFqName().quoteIfNeeded().asString()
}
val entry = psiFactory.createWhenEntry("$branchConditionText -> TODO()")
if (elseBranch != null) {
element.addBefore(entry, elseBranch)
} else {
element.addBefore(entry, whenCloseBrace)
}
}
generateWhenBranches(element, missingCases)
ShortenReferences.DEFAULT.process(element)
@@ -9,4 +9,3 @@ fun test(a: A) {
}
}
/* IGNORE_FIR */
@@ -9,4 +9,3 @@ fun test(a: A) {
is B -> TODO()
}
}
/* IGNORE_FIR */
@@ -11,4 +11,3 @@ fun test(a: A) {
}
}
/* IGNORE_FIR */
@@ -11,4 +11,3 @@ fun test(a: A) {
is B -> TODO()
}
}
/* IGNORE_FIR */
@@ -3,4 +3,3 @@
fun test(b: Boolean) = wh<caret>en(b) {
false -> 0
}
/* IGNORE_FIR */
@@ -4,4 +4,3 @@ fun test(b: Boolean) = when(b) {
false -> 0
true -> TODO()
}
/* IGNORE_FIR */
@@ -5,4 +5,3 @@ enum class Color { R, G, B }
fun test(c: Color) = wh<caret>en(c) {
Color.B -> 0xff
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ fun test(c: Color) = when(c) {
Color.R -> TODO()
Color.G -> TODO()
}
/* IGNORE_FIR */
@@ -8,4 +8,3 @@ enum class FooEnum {
fun test(foo: FooEnum?) = <caret>when (foo) {
FooEnum.A -> "A"
}
/* IGNORE_FIR */
@@ -14,4 +14,3 @@ fun test(foo: FooEnum?) = <caret>when (foo) {
FooEnum.`null` -> TODO()
null -> TODO()
}
/* IGNORE_FIR */
@@ -6,4 +6,3 @@ enum class Color { R, G, B }
fun test(c: Color) = wh<caret>en(c) {
Color.B -> 0xff
}
/* IGNORE_FIR */
@@ -8,4 +8,3 @@ fun test(c: Color) = when(c) {
Color.R -> TODO()
Color.G -> TODO()
}
/* IGNORE_FIR */
@@ -0,0 +1,8 @@
// "Add remaining branches" "true"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a)
@@ -0,0 +1,10 @@
// "Add remaining branches" "true"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a) {
is B -> TODO()
}
@@ -0,0 +1,8 @@
// "Add remaining branches" "false"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a)
@@ -0,0 +1,8 @@
// "Add remaining branches" "true"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a) {
@@ -0,0 +1,10 @@
// "Add remaining branches" "true"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a) {
is B -> TODO()
}
@@ -0,0 +1,9 @@
// "Add remaining branches" "false"
// ACTION: Eliminate argument of 'when'
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a) {
@@ -0,0 +1,8 @@
// "Add remaining branches" "true"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a
@@ -0,0 +1,10 @@
// "Add remaining branches" "true"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
val i = w<caret>hen (a) {
is B -> TODO()
}
@@ -0,0 +1,8 @@
// "Add remaining branches" "false"
// WITH_RUNTIME
sealed class A
class B : A()
fun test(a: A) {
<caret>when (a
@@ -12,4 +12,3 @@ sealed class Variant {
fun test(v: Variant?) = wh<caret>en(v) {
Variant.Singleton -> "s"
}
/* IGNORE_FIR */
@@ -15,4 +15,3 @@ fun test(v: Variant?) = when(v) {
is Variant.Something -> TODO()
null -> TODO()
}
/* IGNORE_FIR */
@@ -13,4 +13,3 @@ object `null`: FooSealed()
fun test(foo: FooSealed?) = <caret>when (foo) {
A -> "A"
}
/* IGNORE_FIR */
@@ -20,4 +20,3 @@ fun test(foo: FooSealed?) = <caret>when (foo) {
is `true` -> TODO()
null -> TODO()
}
/* IGNORE_FIR */
@@ -15518,6 +15518,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/when/addRemainingBranchesInNonDefaultPackage.kt");
}
@TestMetadata("addRemainingBranchesMissingLeftBracket.kt")
public void testAddRemainingBranchesMissingLeftBracket() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesMissingLeftBracket.kt");
}
@TestMetadata("addRemainingBranchesMissingRightBracket.kt")
public void testAddRemainingBranchesMissingRightBracket() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesMissingRightBracket.kt");
}
@TestMetadata("addRemainingBranchesMissingRightParenthesis.kt")
public void testAddRemainingBranchesMissingRightParenthesis() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesMissingRightParenthesis.kt");
}
@TestMetadata("addRemainingBranchesSealed.kt")
public void testAddRemainingBranchesSealed() throws Exception {
runTest("idea/testData/quickfix/when/addRemainingBranchesSealed.kt");