Wrap with let: apply to unsafe qualified expression
#KT-18125 Fixed
This commit is contained in:
committed by
Vladimir Dolzhenko
parent
18fbf5729d
commit
6db0785615
@@ -31,10 +31,9 @@ import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
||||
import org.jetbrains.kotlin.types.isNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
|
||||
|
||||
class WrapWithSafeLetCallFix(
|
||||
@@ -83,18 +82,23 @@ class WrapWithSafeLetCallFix(
|
||||
object UnsafeFactory : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val element = diagnostic.psiElement
|
||||
|
||||
if (element is KtNameReferenceExpression) {
|
||||
val resolvedCall = element.resolveToCall()
|
||||
if (resolvedCall?.call?.callType != Call.CallType.INVOKE) return null
|
||||
}
|
||||
|
||||
val expression = element.getParentOfType<KtExpression>(true) ?: return null
|
||||
|
||||
val parent = element.parent
|
||||
val nullableExpression = (parent as? KtCallExpression)?.calleeExpression ?: return null
|
||||
|
||||
return WrapWithSafeLetCallFix(expression, nullableExpression)
|
||||
val expression = element.getStrictParentOfType<KtExpression>() ?: return null
|
||||
val (targetExpression, nullableExpression) = if (expression is KtQualifiedExpression) {
|
||||
val argument = expression.parent as? KtValueArgument ?: return null
|
||||
val call = argument.getStrictParentOfType<KtCallExpression>() ?: return null
|
||||
val parameter = call.resolveToCall()?.getParameterForArgument(argument) ?: return null
|
||||
if (parameter.type.isNullable()) return null
|
||||
val targetExpression = call.getLastParentOfTypeInRow<KtQualifiedExpression>() ?: call
|
||||
targetExpression to expression.receiverExpression
|
||||
} else {
|
||||
val nullableExpression = (element.parent as? KtCallExpression)?.calleeExpression ?: return null
|
||||
expression to nullableExpression
|
||||
}
|
||||
return WrapWithSafeLetCallFix(targetExpression, nullableExpression)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
// WITH_RUNTIME
|
||||
fun foo(s: String) {}
|
||||
|
||||
fun bar(s: String?) {
|
||||
foo(s<caret>.substring(1))
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
// WITH_RUNTIME
|
||||
fun foo(s: String) {}
|
||||
|
||||
fun bar(s: String?) {
|
||||
s?.let { foo(it.substring(1)) }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
// WITH_RUNTIME
|
||||
class A(val b: B)
|
||||
class B {
|
||||
fun c(s: String) {}
|
||||
}
|
||||
|
||||
class X(val y: Y)
|
||||
class Y(val z: String)
|
||||
|
||||
fun test(a: A, x: X?) {
|
||||
a.b.c(x?.y<caret>.z)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
// WITH_RUNTIME
|
||||
class A(val b: B)
|
||||
class B {
|
||||
fun c(s: String) {}
|
||||
}
|
||||
|
||||
class X(val y: Y)
|
||||
class Y(val z: String)
|
||||
|
||||
fun test(a: A, x: X?) {
|
||||
x?.y?.let { a.b.c(it.z) }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Wrap with '?.let { ... }' call" "false"
|
||||
// ACTION: Add 's =' to argument
|
||||
// ACTION: Add non-null asserted (!!) call
|
||||
// ACTION: Replace with safe (?.) call
|
||||
// ACTION: Surround with null check
|
||||
// DISABLE-ERRORS
|
||||
// WITH_RUNTIME
|
||||
fun foo(s: String?) {}
|
||||
|
||||
fun bar(s: String?) {
|
||||
foo(s<caret>.substring(1))
|
||||
}
|
||||
@@ -15529,6 +15529,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
runTest("idea/testData/quickfix/wrapWithSafeLetCall/objectQualifier.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsafe.kt")
|
||||
public void testUnsafe() throws Exception {
|
||||
runTest("idea/testData/quickfix/wrapWithSafeLetCall/unsafe.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsafe2.kt")
|
||||
public void testUnsafe2() throws Exception {
|
||||
runTest("idea/testData/quickfix/wrapWithSafeLetCall/unsafe2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsafeForNullableParameter.kt")
|
||||
public void testUnsafeForNullableParameter() throws Exception {
|
||||
runTest("idea/testData/quickfix/wrapWithSafeLetCall/unsafeForNullableParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unstableValue.kt")
|
||||
public void testUnstableValue() throws Exception {
|
||||
runTest("idea/testData/quickfix/wrapWithSafeLetCall/unstableValue.kt");
|
||||
|
||||
Reference in New Issue
Block a user