From c344b85d4e9dd9e8d0334d9425f5d9ed8543bef5 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Thu, 19 Mar 2020 16:01:00 +0900 Subject: [PATCH] Convert parameter <-> receiver intention: do not add label to 'this' if not needed #KT-17615 Fixed #KT-30028 Fixed #KT-32809 Fixed #KT-28085 Fixed #KT-37508 Fixed Convert receiver to parameter: #KT-37508 Fixed --- .../KotlinChangeSignatureUsageProcessor.kt | 6 +++- .../usages/KotlinFunctionCallUsage.kt | 7 ++++- .../explicitThis.kt | 8 +++++ .../explicitThis.kt.after | 8 +++++ .../explicitThisForAnonymousObject.kt | 8 +++++ .../explicitThisForAnonymousObject.kt.after | 8 +++++ .../explicitThisForExtension.kt | 17 +++++++++++ .../explicitThisForExtension.kt.after | 17 +++++++++++ .../explicitThisForExtension2.kt | 10 +++++++ .../explicitThisForExtension2.kt.after | 10 +++++++ .../explicitThisForExtension.kt | 4 +++ .../explicitThisForExtension.kt.after | 4 +++ .../usedInAnonymousObject.kt | 11 +++++++ .../usedInAnonymousObject.kt.after | 11 +++++++ .../intentions/IntentionTestGenerated.java | 30 +++++++++++++++++++ 15 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThis.kt create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThis.kt.after create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt.after create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt.after create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt create mode 100644 idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt.after create mode 100644 idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt create mode 100644 idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt.after create mode 100644 idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt create mode 100644 idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt index e5f22bd1a9b..7d1c53193cf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureUsageProcessor.kt @@ -60,10 +60,12 @@ import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.util.OperatorNameConventions @@ -359,9 +361,11 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor { assert(originalReceiverInfo != null) { "No original receiver info provided: " + functionUsageInfo.declaration.text } result.add(KotlinParameterUsage(expression, originalReceiverInfo!!, functionUsageInfo)) } else { + if (receiverDescriptor.value is ExtensionReceiver) return val targetDescriptor = receiverDescriptor.type.constructor.declarationDescriptor assert(targetDescriptor != null) { "Receiver type has no descriptor: " + functionUsageInfo.declaration.text } - result.add(KotlinNonQualifiedOuterThisUsage(expression.parent as KtThisExpression, targetDescriptor!!)) + if (DescriptorUtils.isAnonymousObject(targetDescriptor!!)) return + result.add(KotlinNonQualifiedOuterThisUsage(expression.parent as KtThisExpression, targetDescriptor)) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinFunctionCallUsage.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinFunctionCallUsage.kt index 255e99a490f..9c452039f7c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinFunctionCallUsage.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinFunctionCallUsage.kt @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode @@ -540,7 +541,11 @@ class KotlinFunctionCallUsage( is ExpressionReceiver -> receiver.expression is ImplicitReceiver -> { val descriptor = receiver.declarationDescriptor - val thisText = if (descriptor is ClassDescriptor) "this@" + descriptor.name.asString() else "this" + val thisText = if (descriptor is ClassDescriptor && !DescriptorUtils.isAnonymousObject(descriptor)) { + "this@" + descriptor.name.asString() + } else { + "this" + } psiFactory.createExpression(thisText) } else -> null diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThis.kt b/idea/testData/intentions/convertParameterToReceiver/explicitThis.kt new file mode 100644 index 00000000000..b389a782d73 --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThis.kt @@ -0,0 +1,8 @@ +class A + +class B { + val foo = 1 + fun test(a: A) { + this.foo + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThis.kt.after b/idea/testData/intentions/convertParameterToReceiver/explicitThis.kt.after new file mode 100644 index 00000000000..62c1decdf7c --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThis.kt.after @@ -0,0 +1,8 @@ +class A + +class B { + val foo = 1 + fun A.test() { + this@B.foo + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt b/idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt new file mode 100644 index 00000000000..c711f87b758 --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME +fun foo(p: Any) { + object : Runnable { + override fun run() { + print(this) + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt.after b/idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt.after new file mode 100644 index 00000000000..5d32f297064 --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME +fun Any.foo() { + object : Runnable { + override fun run() { + print(this) + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt new file mode 100644 index 00000000000..36b329400e3 --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt @@ -0,0 +1,17 @@ +// WITH_RUNTIME +class C(val x: Int, val y: Int, var z: Int) + +class CBuilder { + var x: Int = 0 + var y: Int = 0 + fun build() = C(x, y, 0) +} + +fun test(a: C) = + CBuilder().apply { + x = a.x + y = a.y + }.build().apply { + val b = this + z = b.x + b.y + } \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt.after b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt.after new file mode 100644 index 00000000000..62045ab0921 --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt.after @@ -0,0 +1,17 @@ +// WITH_RUNTIME +class C(val x: Int, val y: Int, var z: Int) + +class CBuilder { + var x: Int = 0 + var y: Int = 0 + fun build() = C(x, y, 0) +} + +fun C.test() = + CBuilder().apply { + x = this@test.x + y = this@test.y + }.build().apply { + val b = this + z = b.x + b.y + } \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt new file mode 100644 index 00000000000..570b6b89d3c --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt @@ -0,0 +1,10 @@ +interface I +interface J + +fun foo(a: Any, b: String) { + b.bar { + this as J + } +} + +fun String.bar(init: I.() -> Unit) {} \ No newline at end of file diff --git a/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt.after b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt.after new file mode 100644 index 00000000000..3bfc2d38d52 --- /dev/null +++ b/idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt.after @@ -0,0 +1,10 @@ +interface I +interface J + +fun Any.foo(b: String) { + b.bar { + this as J + } +} + +fun String.bar(init: I.() -> Unit) {} \ No newline at end of file diff --git a/idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt b/idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt new file mode 100644 index 00000000000..9cf40e065b4 --- /dev/null +++ b/idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun Int.add() { + run { println(this + 1) } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt.after b/idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt.after new file mode 100644 index 00000000000..b38707ab6bd --- /dev/null +++ b/idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME +fun add(i: Int) { + i.run { println(this + 1) } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt b/idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt new file mode 100644 index 00000000000..f2a1430cc6b --- /dev/null +++ b/idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt @@ -0,0 +1,11 @@ +interface A + +fun A.foo() {} + +fun test() { + object : A { + fun bar() { + foo() + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt.after b/idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt.after new file mode 100644 index 00000000000..cc733e1131c --- /dev/null +++ b/idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt.after @@ -0,0 +1,11 @@ +interface A + +fun foo(a: A) {} + +fun test() { + object : A { + fun bar() { + foo(this) + } + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index c57fb6573c1..dde93b0ec42 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -5531,6 +5531,26 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/convertParameterToReceiver/companionAsReceiver.kt"); } + @TestMetadata("explicitThis.kt") + public void testExplicitThis() throws Exception { + runTest("idea/testData/intentions/convertParameterToReceiver/explicitThis.kt"); + } + + @TestMetadata("explicitThisForAnonymousObject.kt") + public void testExplicitThisForAnonymousObject() throws Exception { + runTest("idea/testData/intentions/convertParameterToReceiver/explicitThisForAnonymousObject.kt"); + } + + @TestMetadata("explicitThisForExtension.kt") + public void testExplicitThisForExtension() throws Exception { + runTest("idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension.kt"); + } + + @TestMetadata("explicitThisForExtension2.kt") + public void testExplicitThisForExtension2() throws Exception { + runTest("idea/testData/intentions/convertParameterToReceiver/explicitThisForExtension2.kt"); + } + @TestMetadata("functionExpression.kt") public void testFunctionExpression() throws Exception { runTest("idea/testData/intentions/convertParameterToReceiver/functionExpression.kt"); @@ -6089,6 +6109,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/convertReceiverToParameter/autoSuggestedName.kt"); } + @TestMetadata("explicitThisForExtension.kt") + public void testExplicitThisForExtension() throws Exception { + runTest("idea/testData/intentions/convertReceiverToParameter/explicitThisForExtension.kt"); + } + @TestMetadata("functionExpression.kt") public void testFunctionExpression() throws Exception { runTest("idea/testData/intentions/convertReceiverToParameter/functionExpression.kt"); @@ -6129,6 +6154,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/convertReceiverToParameter/topLevelFun.kt"); } + @TestMetadata("usedInAnonymousObject.kt") + public void testUsedInAnonymousObject() throws Exception { + runTest("idea/testData/intentions/convertReceiverToParameter/usedInAnonymousObject.kt"); + } + @TestMetadata("validOverload.kt") public void testValidOverload() throws Exception { runTest("idea/testData/intentions/convertReceiverToParameter/validOverload.kt");