[kotlin] Add brackets to casted type if it's definitely non-nullable

For example, `foo(z as (T & Any))`. `foo(z as T & Any)` wouldn't work

KTIJ-32081 CastExpressionModCommandAction fails with exception on casting parameter to definitely non-nullable


(cherry picked from commit 6a0e12503b9d7738305a27d40ecd12a2cdf0a6b4)

IJ-CR-149170

GitOrigin-RevId: 234038e18861ba2ae6269ec2e6295cd76fae1019
This commit is contained in:
Victoria.Petrakovich
2024-11-18 13:27:34 +00:00
committed by intellij-monorepo-bot
parent e7888d2bef
commit 259374c93b
5 changed files with 37 additions and 1 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic
import org.jetbrains.kotlin.analysis.api.renderer.types.impl.KaTypeRendererForSource
import org.jetbrains.kotlin.analysis.api.types.KaDefinitelyNotNullType
import org.jetbrains.kotlin.analysis.api.types.KaErrorType
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferences
@@ -30,6 +31,7 @@ object CastExpressionFixFactories {
private data class ElementContext(
val typePresentation: String,
val typeSourceCode: String,
val isDefinitelyNotNull: Boolean,
)
private class CastExpressionModCommandAction(
@@ -59,9 +61,10 @@ object CastExpressionFixFactories {
elementContext: ElementContext,
updater: ModPsiUpdater,
) {
val pattern = if (elementContext.isDefinitelyNotNull) "$0 as ($1)" else "$0 as $1"
val expressionToInsert = KtPsiFactory(actionContext.project)
.createExpressionByPattern(
"$0 as $1",
pattern,
element,
elementContext.typeSourceCode,
)
@@ -135,6 +138,7 @@ object CastExpressionFixFactories {
val elementContext = ElementContext(
expectedType.render(KaTypeRendererForSource.WITH_SHORT_NAMES, position = Variance.OUT_VARIANCE),
expectedType.render(KaTypeRendererForSource.WITH_QUALIFIED_NAMES, position = Variance.OUT_VARIANCE),
expectedType is KaDefinitelyNotNullType,
)
return listOf(
@@ -4108,6 +4108,11 @@ public abstract class HighLevelQuickFixTestGenerated extends AbstractHighLevelQu
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("castFunctionParameter.kt")
public void testCastFunctionParameter() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/casts/castFunctionParameter.kt");
}
@TestMetadata("castQualifiedArgument.kt")
public void testCastQualifiedArgument() throws Exception {
runTest("../../../idea/tests/testData/quickfix/typeMismatch/casts/castQualifiedArgument.kt");
@@ -17733,6 +17733,11 @@ public abstract class K1QuickFixTestGenerated extends AbstractK1QuickFixTest {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("castFunctionParameter.kt")
public void testCastFunctionParameter() throws Exception {
runTest("testData/quickfix/typeMismatch/casts/castFunctionParameter.kt");
}
@TestMetadata("castQualifiedArgument.kt")
public void testCastQualifiedArgument() throws Exception {
runTest("testData/quickfix/typeMismatch/casts/castQualifiedArgument.kt");
@@ -0,0 +1,11 @@
// "Cast expression 'z' to 'T & Any'" "true"
fun <T> foo(x: T & Any) {}
fun <T> bar(x: T & Any) {
val z: T = x
foo(<caret>z)
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.CastExpressionFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.CastExpressionFixFactories$CastExpressionModCommandAction
@@ -0,0 +1,11 @@
// "Cast expression 'z' to 'T & Any'" "true"
fun <T> foo(x: T & Any) {}
fun <T> bar(x: T & Any) {
val z: T = x
foo(z as (T & Any))
}
// FUS_QUICKFIX_NAME: org.jetbrains.kotlin.idea.quickfix.CastExpressionFix
// FUS_K2_QUICKFIX_NAME: org.jetbrains.kotlin.idea.k2.codeinsight.fixes.CastExpressionFixFactories$CastExpressionModCommandAction