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
This commit is contained in:
Toshiaki Kameyama
2020-03-19 16:01:00 +09:00
committed by Ilya Kirillov
parent 34e9e899f8
commit c344b85d4e
15 changed files with 157 additions and 2 deletions
@@ -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))
}
}
@@ -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
@@ -0,0 +1,8 @@
class A
class B {
val foo = 1
fun test(<caret>a: A) {
this.foo
}
}
@@ -0,0 +1,8 @@
class A
class B {
val foo = 1
fun A.test() {
this@B.foo
}
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(<caret>p: Any) {
object : Runnable {
override fun run() {
print(this)
}
}
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun Any.foo() {
object : Runnable {
override fun run() {
print(this)
}
}
}
@@ -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(<caret>a: C) =
CBuilder().apply {
x = a.x
y = a.y
}.build().apply {
val b = this
z = b.x + b.y
}
@@ -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
}
@@ -0,0 +1,10 @@
interface I
interface J
fun foo(<caret>a: Any, b: String) {
b.bar {
this as J
}
}
fun String.bar(init: I.() -> Unit) {}
@@ -0,0 +1,10 @@
interface I
interface J
fun Any.foo(b: String) {
b.bar {
this as J
}
}
fun String.bar(init: I.() -> Unit) {}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun <caret>Int.add() {
run { println(this + 1) }
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun add(i: Int) {
i.run { println(this + 1) }
}
@@ -0,0 +1,11 @@
interface A
fun <caret>A.foo() {}
fun test() {
object : A {
fun bar() {
foo()
}
}
}
@@ -0,0 +1,11 @@
interface A
fun foo(a: A) {}
fun test() {
object : A {
fun bar() {
foo(this)
}
}
}
@@ -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");