Wrap with let: apply to unsafe qualified expression

#KT-18125 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-07-08 09:50:03 +09:00
committed by Vladimir Dolzhenko
parent 18fbf5729d
commit 6db0785615
7 changed files with 83 additions and 12 deletions
@@ -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)
}
}
+7
View File
@@ -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)) }
}
+13
View File
@@ -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");