[FIR] Make UNSAFE_INFIX_CALL and UNSAFE_OPERATOR_CALL parameter nullable

This fixes an NPE in the IDE in presence of a syntax error when the
argument expression has no source.

#KT-64062 Fixed
This commit is contained in:
Kirill Rakhman
2023-12-04 20:56:54 +01:00
committed by Space Team
parent b059754f64
commit 8496722603
13 changed files with 48 additions and 12 deletions
@@ -4045,7 +4045,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firDiagnostic.b.source!!.psi as KtExpression, firDiagnostic.b.source!!.psi as KtExpression,
firDiagnostic.c, firDiagnostic.c,
firDiagnostic.d.source!!.psi as KtExpression, firDiagnostic.d?.source?.psi as? KtExpression,
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
token, token,
) )
@@ -4055,7 +4055,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firDiagnostic.b.source!!.psi as KtExpression, firDiagnostic.b.source!!.psi as KtExpression,
firDiagnostic.c, firDiagnostic.c,
firDiagnostic.d.source!!.psi as KtExpression, firDiagnostic.d?.source?.psi as? KtExpression,
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
token, token,
) )
@@ -2822,7 +2822,7 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
val receiverType: KtType val receiverType: KtType
val receiverExpression: KtExpression val receiverExpression: KtExpression
val operator: String val operator: String
val argumentExpression: KtExpression val argumentExpression: KtExpression?
} }
interface UnsafeOperatorCall : KtFirDiagnostic<KtExpression> { interface UnsafeOperatorCall : KtFirDiagnostic<KtExpression> {
@@ -2830,7 +2830,7 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
val receiverType: KtType val receiverType: KtType
val receiverExpression: KtExpression val receiverExpression: KtExpression
val operator: String val operator: String
val argumentExpression: KtExpression val argumentExpression: KtExpression?
} }
interface IteratorOnNullable : KtFirDiagnostic<KtExpression> { interface IteratorOnNullable : KtFirDiagnostic<KtExpression> {
@@ -3396,7 +3396,7 @@ internal class UnsafeInfixCallImpl(
override val receiverType: KtType, override val receiverType: KtType,
override val receiverExpression: KtExpression, override val receiverExpression: KtExpression,
override val operator: String, override val operator: String,
override val argumentExpression: KtExpression, override val argumentExpression: KtExpression?,
firDiagnostic: KtPsiDiagnostic, firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken, token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.UnsafeInfixCall ) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.UnsafeInfixCall
@@ -3405,7 +3405,7 @@ internal class UnsafeOperatorCallImpl(
override val receiverType: KtType, override val receiverType: KtType,
override val receiverExpression: KtExpression, override val receiverExpression: KtExpression,
override val operator: String, override val operator: String,
override val argumentExpression: KtExpression, override val argumentExpression: KtExpression?,
firDiagnostic: KtPsiDiagnostic, firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken, token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.UnsafeOperatorCall ) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.UnsafeOperatorCall
@@ -26348,6 +26348,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt"); runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt");
} }
@Test
@TestMetadata("unsafeCallOnOperatorRedCode.kt")
public void testUnsafeCallOnOperatorRedCode() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/unsafeCallOnOperatorRedCode.kt");
}
@Test @Test
@TestMetadata("uselessElvis.kt") @TestMetadata("uselessElvis.kt")
public void testUselessElvis() throws Exception { public void testUselessElvis() throws Exception {
@@ -26348,6 +26348,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt"); runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt");
} }
@Test
@TestMetadata("unsafeCallOnOperatorRedCode.kt")
public void testUnsafeCallOnOperatorRedCode() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/unsafeCallOnOperatorRedCode.kt");
}
@Test @Test
@TestMetadata("uselessElvis.kt") @TestMetadata("uselessElvis.kt")
public void testUselessElvis() throws Exception { public void testUselessElvis() throws Exception {
@@ -24270,6 +24270,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt"); runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt");
} }
@Test
@TestMetadata("unsafeCallOnOperatorRedCode.kt")
public void testUnsafeCallOnOperatorRedCode() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/unsafeCallOnOperatorRedCode.kt");
}
@Test @Test
@TestMetadata("uselessElvis.kt") @TestMetadata("uselessElvis.kt")
public void testUselessElvis() throws Exception { public void testUselessElvis() throws Exception {
@@ -24276,6 +24276,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt"); runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt");
} }
@Test
@TestMetadata("unsafeCallOnOperatorRedCode.kt")
public void testUnsafeCallOnOperatorRedCode() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/unsafeCallOnOperatorRedCode.kt");
}
@Test @Test
@TestMetadata("uselessElvis.kt") @TestMetadata("uselessElvis.kt")
public void testUselessElvis() throws Exception { public void testUselessElvis() throws Exception {
@@ -1405,13 +1405,13 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<ConeKotlinType>("receiverType") parameter<ConeKotlinType>("receiverType")
parameter<FirExpression>("receiverExpression") parameter<FirExpression>("receiverExpression")
parameter<String>("operator") parameter<String>("operator")
parameter<FirExpression>("argumentExpression") parameter<FirExpression?>("argumentExpression")
} }
val UNSAFE_OPERATOR_CALL by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) { val UNSAFE_OPERATOR_CALL by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<ConeKotlinType>("receiverType") parameter<ConeKotlinType>("receiverType")
parameter<FirExpression>("receiverExpression") parameter<FirExpression>("receiverExpression")
parameter<String>("operator") parameter<String>("operator")
parameter<FirExpression>("argumentExpression") parameter<FirExpression?>("argumentExpression")
} }
val ITERATOR_ON_NULLABLE by error<KtExpression>() val ITERATOR_ON_NULLABLE by error<KtExpression>()
val UNNECESSARY_SAFE_CALL by warning<PsiElement>(PositioningStrategy.SAFE_ACCESS) { val UNNECESSARY_SAFE_CALL by warning<PsiElement>(PositioningStrategy.SAFE_ACCESS) {
@@ -707,8 +707,8 @@ object FirErrors {
// Nullability // Nullability
val UNSAFE_CALL by error2<PsiElement, ConeKotlinType, FirExpression?>(SourceElementPositioningStrategies.DOT_BY_QUALIFIED) val UNSAFE_CALL by error2<PsiElement, ConeKotlinType, FirExpression?>(SourceElementPositioningStrategies.DOT_BY_QUALIFIED)
val UNSAFE_IMPLICIT_INVOKE_CALL by error1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val UNSAFE_IMPLICIT_INVOKE_CALL by error1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val UNSAFE_INFIX_CALL by error4<KtExpression, ConeKotlinType, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val UNSAFE_INFIX_CALL by error4<KtExpression, ConeKotlinType, FirExpression, String, FirExpression?>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val UNSAFE_OPERATOR_CALL by error4<KtExpression, ConeKotlinType, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val UNSAFE_OPERATOR_CALL by error4<KtExpression, ConeKotlinType, FirExpression, String, FirExpression?>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val ITERATOR_ON_NULLABLE by error0<KtExpression>() val ITERATOR_ON_NULLABLE by error0<KtExpression>()
val UNNECESSARY_SAFE_CALL by warning1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.SAFE_ACCESS) val UNNECESSARY_SAFE_CALL by warning1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.SAFE_ACCESS)
val SAFE_CALL_WILL_CHANGE_NULLABILITY by warning0<KtSafeQualifiedExpression>(SourceElementPositioningStrategies.CALL_ELEMENT_WITH_DOT) val SAFE_CALL_WILL_CHANGE_NULLABILITY by warning0<KtSafeQualifiedExpression>(SourceElementPositioningStrategies.CALL_ELEMENT_WITH_DOT)
@@ -240,7 +240,7 @@ private fun mapUnsafeCallError(
rootCause.actualType, rootCause.actualType,
receiverExpression, receiverExpression,
candidateFunctionName!!.asString(), candidateFunctionName!!.asString(),
singleArgument, singleArgument.takeIf { it.source != null },
) )
} else { } else {
FirErrors.UNSAFE_OPERATOR_CALL.createOn( FirErrors.UNSAFE_OPERATOR_CALL.createOn(
@@ -248,7 +248,7 @@ private fun mapUnsafeCallError(
rootCause.actualType, rootCause.actualType,
receiverExpression, receiverExpression,
candidateFunctionName!!.asString(), candidateFunctionName!!.asString(),
singleArgument, singleArgument.takeIf { it.source != null },
) )
} }
} }
@@ -0,0 +1,3 @@
fun add(a: Int?, b: Int?): Int {
return a<!UNSAFE_OPERATOR_CALL!>+<!><!SYNTAX!><!>
}
@@ -0,0 +1,3 @@
fun add(a: Int?, b: Int?): Int {
return a<!NONE_APPLICABLE!>+<!><!SYNTAX!><!>
}
@@ -26348,6 +26348,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt"); runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt");
} }
@Test
@TestMetadata("unsafeCallOnOperatorRedCode.kt")
public void testUnsafeCallOnOperatorRedCode() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/unsafeCallOnOperatorRedCode.kt");
}
@Test @Test
@TestMetadata("uselessElvis.kt") @TestMetadata("uselessElvis.kt")
public void testUselessElvis() throws Exception { public void testUselessElvis() throws Exception {