FIR IDE: Don't offer AddExclExclCallFix when expression is definitely
null.
This commit is contained in:
committed by
teamcityserver
parent
97ea901507
commit
2773506f4c
+10
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.unwrapParenthesesLabelsAndAnnotations
|
import org.jetbrains.kotlin.psi.psiUtil.unwrapParenthesesLabelsAndAnnotations
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
object AddExclExclCallFixFactories {
|
object AddExclExclCallFixFactories {
|
||||||
val unsafeCallFactory = diagnosticFixFactory<KtFirDiagnostic.UnsafeCall> { diagnostic ->
|
val unsafeCallFactory = diagnosticFixFactory<KtFirDiagnostic.UnsafeCall> { diagnostic ->
|
||||||
@@ -79,6 +80,15 @@ object AddExclExclCallFixFactories {
|
|||||||
else -> return emptyList()
|
else -> return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't want to offer AddExclExclCallFix if we know the expression is definitely null, e.g.:
|
||||||
|
//
|
||||||
|
// if (nullableInt == null) {
|
||||||
|
// val x = nullableInt.length // No AddExclExclCallFix here
|
||||||
|
// }
|
||||||
|
if (target?.safeAs<KtExpression>()?.isDefinitelyNull() == true) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
return listOfNotNull(target.asAddExclExclCallFix(hasImplicitReceiver = hasImplicitReceiver))
|
return listOfNotNull(target.asAddExclExclCallFix(hasImplicitReceiver = hasImplicitReceiver))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
|
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
object TypeMismatchFactories {
|
object TypeMismatchFactories {
|
||||||
val argumentTypeMismatchFactory = diagnosticFixFactory<KtFirDiagnostic.ArgumentTypeMismatch> { diagnostic ->
|
val argumentTypeMismatchFactory = diagnosticFixFactory<KtFirDiagnostic.ArgumentTypeMismatch> { diagnostic ->
|
||||||
@@ -37,6 +39,14 @@ object TypeMismatchFactories {
|
|||||||
): List<IntentionAction> {
|
): List<IntentionAction> {
|
||||||
// TODO: Add more fixes than just AddExclExclCallFix when available.
|
// TODO: Add more fixes than just AddExclExclCallFix when available.
|
||||||
if (!expectedType.canBeNull && actualType.canBeNull) {
|
if (!expectedType.canBeNull && actualType.canBeNull) {
|
||||||
|
// We don't want to offer AddExclExclCallFix if we know the expression is definitely null, e.g.:
|
||||||
|
//
|
||||||
|
// if (nullableInt == null) {
|
||||||
|
// val x: Int = nullableInt // No AddExclExclCallFix here
|
||||||
|
// }
|
||||||
|
if (psi.safeAs<KtExpression>()?.isDefinitelyNull() == true) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
val nullableExpectedType = expectedType.withNullability(KtTypeNullability.NULLABLE)
|
val nullableExpectedType = expectedType.withNullability(KtTypeNullability.NULLABLE)
|
||||||
if (actualType isSubTypeOf nullableExpectedType) {
|
if (actualType isSubTypeOf nullableExpectedType) {
|
||||||
return listOfNotNull(psi.asAddExclExclCallFix())
|
return listOfNotNull(psi.asAddExclExclCallFix())
|
||||||
|
|||||||
Generated
+5
@@ -324,6 +324,11 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes
|
|||||||
runTest("idea/testData/quickfix/addExclExclCall/nullExpression.kt");
|
runTest("idea/testData/quickfix/addExclExclCall/nullExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nullReceiver.kt")
|
||||||
|
public void testNullReceiver() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addExclExclCall/nullReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("operationBinary.kt")
|
@TestMetadata("operationBinary.kt")
|
||||||
public void testOperationBinary() throws Exception {
|
public void testOperationBinary() throws Exception {
|
||||||
runTest("idea/testData/quickfix/addExclExclCall/operationBinary.kt");
|
runTest("idea/testData/quickfix/addExclExclCall/operationBinary.kt");
|
||||||
|
|||||||
@@ -8,7 +8,4 @@ fun foo(arg: String?) {
|
|||||||
if (arg == null) {
|
if (arg == null) {
|
||||||
val x: String = arg<caret>
|
val x: String = arg<caret>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Need data flow info from null check
|
|
||||||
/* IGNORE_FIR */
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "false"
|
||||||
|
|
||||||
|
fun foo(arg: String?) {
|
||||||
|
if (arg == null) {
|
||||||
|
arg<caret>.length
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
fun foo(arg: String?) {
|
||||||
|
if (arg == null) {
|
||||||
|
arg<caret>.length
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
fun foo(arg: String?) {
|
||||||
|
if (arg == null) {
|
||||||
|
arg!!.length
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-4
@@ -12,7 +12,4 @@ fun test(i: Int?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun other(i: Int) {}
|
fun other(i: Int) {}
|
||||||
|
|
||||||
// TODO: Need data flow info from null check
|
|
||||||
/* IGNORE_FIR */
|
|
||||||
@@ -737,6 +737,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
runTest("idea/testData/quickfix/addExclExclCall/nullExpression.kt");
|
runTest("idea/testData/quickfix/addExclExclCall/nullExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nullReceiver.kt")
|
||||||
|
public void testNullReceiver() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addExclExclCall/nullReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("operationBinary.kt")
|
@TestMetadata("operationBinary.kt")
|
||||||
public void testOperationBinary() throws Exception {
|
public void testOperationBinary() throws Exception {
|
||||||
runTest("idea/testData/quickfix/addExclExclCall/operationBinary.kt");
|
runTest("idea/testData/quickfix/addExclExclCall/operationBinary.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user