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.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.types.isNullable
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
|
import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
|
||||||
|
|
||||||
class WrapWithSafeLetCallFix(
|
class WrapWithSafeLetCallFix(
|
||||||
@@ -83,18 +82,23 @@ class WrapWithSafeLetCallFix(
|
|||||||
object UnsafeFactory : KotlinSingleIntentionActionFactory() {
|
object UnsafeFactory : KotlinSingleIntentionActionFactory() {
|
||||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
val element = diagnostic.psiElement
|
val element = diagnostic.psiElement
|
||||||
|
|
||||||
if (element is KtNameReferenceExpression) {
|
if (element is KtNameReferenceExpression) {
|
||||||
val resolvedCall = element.resolveToCall()
|
val resolvedCall = element.resolveToCall()
|
||||||
if (resolvedCall?.call?.callType != Call.CallType.INVOKE) return null
|
if (resolvedCall?.call?.callType != Call.CallType.INVOKE) return null
|
||||||
}
|
}
|
||||||
|
val expression = element.getStrictParentOfType<KtExpression>() ?: return null
|
||||||
val expression = element.getParentOfType<KtExpression>(true) ?: return null
|
val (targetExpression, nullableExpression) = if (expression is KtQualifiedExpression) {
|
||||||
|
val argument = expression.parent as? KtValueArgument ?: return null
|
||||||
val parent = element.parent
|
val call = argument.getStrictParentOfType<KtCallExpression>() ?: return null
|
||||||
val nullableExpression = (parent as? KtCallExpression)?.calleeExpression ?: return null
|
val parameter = call.resolveToCall()?.getParameterForArgument(argument) ?: return null
|
||||||
|
if (parameter.type.isNullable()) return null
|
||||||
return WrapWithSafeLetCallFix(expression, nullableExpression)
|
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");
|
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")
|
@TestMetadata("unstableValue.kt")
|
||||||
public void testUnstableValue() throws Exception {
|
public void testUnstableValue() throws Exception {
|
||||||
runTest("idea/testData/quickfix/wrapWithSafeLetCall/unstableValue.kt");
|
runTest("idea/testData/quickfix/wrapWithSafeLetCall/unstableValue.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user