From 995a63322960133fa2da729701fd5afc02c73e6b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 27 Jul 2016 18:09:57 +0300 Subject: [PATCH] Replace with safe call works now on UNSAFE_IMPLICIT_INVOKE #KT-12628 Fixed (cherry picked from commit 208798d) --- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 1 + .../idea/quickfix/ReplaceInfixCallFix.kt | 21 ++++++++++++++++--- .../nullables/unsafeInfixCall/unsafeInvoke.kt | 3 +++ .../unsafeInfixCall/unsafeInvoke.kt.after | 3 +++ .../unsafeInvokeWithReceiver.kt | 7 +++++++ .../idea/quickfix/QuickFixTestGenerated.java | 12 +++++++++++ 6 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt create mode 100644 idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt.after create mode 100644 idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvokeWithReceiver.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 393e676d3f1..d7f3234c25a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -205,6 +205,7 @@ class QuickFixRegistrar : QuickFixContributor { UNNECESSARY_NOT_NULL_ASSERTION.registerFactory(RemoveExclExclCallFix) UNSAFE_INFIX_CALL.registerFactory(ReplaceInfixCallFix) UNSAFE_CALL.registerFactory(ReplaceInfixCallFix) // [] only + UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(ReplaceInfixCallFix) AMBIGUOUS_ANONYMOUS_TYPE_INFERRED.registerActions(SpecifyTypeExplicitlyFix()) PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.registerActions(SpecifyTypeExplicitlyFix()) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixCallFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixCallFix.kt index 375735c49f4..e6340df9df7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixCallFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixCallFix.kt @@ -51,6 +51,11 @@ class ReplaceInfixCallFix(element: KtExpression) : KotlinQuickFixAction { + val newExpression = psiFactory.createExpressionByPattern( + "$0?.invoke($1)", element.calleeExpression ?: return, element.valueArguments.joinToString(", ") { it.text }) + element.replace(newExpression) + } is KtBinaryExpression -> { if (element.operationToken == KtTokens.IDENTIFIER) { val newExpression = psiFactory.createExpressionByPattern( @@ -78,9 +83,19 @@ class ReplaceInfixCallFix(element: KtExpression) : KotlinQuickFixAction { + if (parent.left == null || parent.right == null) null + else ReplaceInfixCallFix(parent) + } + is KtCallExpression -> { + if (parent.calleeExpression == null) null + else if (parent.parent is KtQualifiedExpression) null + else ReplaceInfixCallFix(parent) + } + else -> null + } } } } diff --git a/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt b/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt new file mode 100644 index 00000000000..1639ac13d73 --- /dev/null +++ b/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt @@ -0,0 +1,3 @@ +// "Replace with safe (?.) call" "true" + +fun foo(exec: (() -> Unit)?) = exec() \ No newline at end of file diff --git a/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt.after b/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt.after new file mode 100644 index 00000000000..8242b09bf2f --- /dev/null +++ b/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt.after @@ -0,0 +1,3 @@ +// "Replace with safe (?.) call" "true" + +fun foo(exec: (() -> Unit)?) = exec?.invoke() \ No newline at end of file diff --git a/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvokeWithReceiver.kt b/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvokeWithReceiver.kt new file mode 100644 index 00000000000..0977c5b121e --- /dev/null +++ b/idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvokeWithReceiver.kt @@ -0,0 +1,7 @@ +// "Replace with safe (?.) call" "false" +// ACTION: Convert to block body +// ACTION: Replace overloaded operator with function call +// ACTION: Wrap with '?.let { ... }' call +// ERROR: Reference has a nullable type '(String.() -> Unit)?', use explicit '?.invoke()' to make a function-like call instead + +fun foo(exec: (String.() -> Unit)?) = "".exec() \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index fdb13b6022a..9c0a49993a8 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -6096,6 +6096,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("unsafeInvoke.kt") + public void testUnsafeInvoke() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvoke.kt"); + doTest(fileName); + } + + @TestMetadata("unsafeInvokeWithReceiver.kt") + public void testUnsafeInvokeWithReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/nullables/unsafeInfixCall/unsafeInvokeWithReceiver.kt"); + doTest(fileName); + } + @TestMetadata("unsafePlus.kt") public void testUnsafePlus() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/nullables/unsafeInfixCall/unsafePlus.kt");