mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-12 00:21:30 +00:00
Move: Convert implicit receiver to this when moving class member to companion object
#KT-11483 Fixed
This commit is contained in:
@@ -38,6 +38,7 @@ Issues fixed:
|
||||
- [KT-11282](https://youtrack.jetbrains.com/issue/KT-11282) Delete interface reference from super-type list when applying Safe Delete to Java interface
|
||||
- [KT-11967](https://youtrack.jetbrains.com/issue/KT-11967) Fix Find Usages/Rename for parameter references in XML files
|
||||
- [KT-11482](https://youtrack.jetbrains.com/issue/KT-11482) Fixed exception in "Move to companion object" intention
|
||||
- [KT-11483](https://youtrack.jetbrains.com/issue/KT-11483) Pass implicit receiver as argument when moving member function to companion object
|
||||
|
||||
#### Debugger
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
||||
) {
|
||||
companion object {
|
||||
val DEFAULT = Options()
|
||||
val ALL_ENABLED = Options(true, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
@@ -115,7 +116,7 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveReceiverToArgumentList(refElement: PsiElement) {
|
||||
private fun moveReceiverToArgumentList(refElement: PsiElement, classFqName: FqName) {
|
||||
when (refElement) {
|
||||
is PsiReferenceExpression -> {
|
||||
val qualifier = refElement.qualifier
|
||||
@@ -127,15 +128,15 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
||||
}
|
||||
|
||||
is KtSimpleNameExpression -> {
|
||||
val call = refElement.parent as? KtCallExpression
|
||||
val receiver = call?.getQualifiedExpressionForSelector()?.receiverExpression
|
||||
if (call != null && receiver != null) {
|
||||
val psiFactory = KtPsiFactory(refElement)
|
||||
val argumentList = call.valueArgumentList
|
||||
?: call.addAfter(psiFactory.createCallArguments("()"), call.typeArgumentList ?: refElement) as KtValueArgumentList
|
||||
argumentList.addArgumentBefore(psiFactory.createArgument(receiver),
|
||||
argumentList.arguments.firstOrNull())
|
||||
}
|
||||
val call = refElement.parent as? KtCallExpression ?: return
|
||||
val psiFactory = KtPsiFactory(refElement)
|
||||
val argumentList = call.valueArgumentList
|
||||
?: call.addAfter(psiFactory.createCallArguments("()"), call.typeArgumentList ?: refElement) as KtValueArgumentList
|
||||
|
||||
val receiver = call.getQualifiedExpressionForSelector()?.receiverExpression
|
||||
val receiverArg = receiver?.let { psiFactory.createArgument(it) }
|
||||
?: psiFactory.createArgument(psiFactory.createExpression("this@${classFqName.asString()}"))
|
||||
argumentList.addArgumentBefore(receiverArg, argumentList.arguments.firstOrNull())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,6 +191,8 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
||||
nameSuggestions = emptyList()
|
||||
}
|
||||
|
||||
val hasInstanceArg = nameSuggestions.isNotEmpty()
|
||||
|
||||
element.removeModifier(KtTokens.OPEN_KEYWORD)
|
||||
element.removeModifier(KtTokens.FINAL_KEYWORD)
|
||||
|
||||
@@ -198,8 +201,8 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
||||
for (usage in externalUsages) {
|
||||
val usageElement = usage.element ?: continue
|
||||
|
||||
if (nameSuggestions.isNotEmpty()) {
|
||||
moveReceiverToArgumentList(usageElement)
|
||||
if (hasInstanceArg) {
|
||||
moveReceiverToArgumentList(usageElement, containingClass.fqName!!)
|
||||
}
|
||||
|
||||
when (usage) {
|
||||
@@ -217,12 +220,18 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
||||
is ImplicitReceiverUsageInfo -> {
|
||||
usage.callExpression
|
||||
.let { it.replaced(ktPsiFactory.createExpressionByPattern("$0.$1", ktCompanionRef, it)) }
|
||||
.let { elementsToShorten += (it as KtQualifiedExpression).receiverExpression }
|
||||
.let {
|
||||
val qualifiedCall = it as KtQualifiedExpression
|
||||
elementsToShorten += qualifiedCall.receiverExpression
|
||||
if (hasInstanceArg) {
|
||||
elementsToShorten += (qualifiedCall.selectorExpression as KtCallExpression).valueArguments.first()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShortenReferences.DEFAULT.process(elementsToShorten)
|
||||
ShortenReferences { ShortenReferences.Options.ALL_ENABLED }.process(elementsToShorten)
|
||||
|
||||
runTemplateForInstanceParam(newDeclaration, nameSuggestions, editor)
|
||||
}
|
||||
|
||||
9
idea/testData/intentions/moveToCompanion/implicitDispatchReceiver.kt
vendored
Normal file
9
idea/testData/intentions/moveToCompanion/implicitDispatchReceiver.kt
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
fun println(a: Any) {}
|
||||
|
||||
class InsertThis {
|
||||
val v1 = 1
|
||||
fun <caret>f() {
|
||||
println(v1)
|
||||
}
|
||||
fun use() { f() }
|
||||
}
|
||||
14
idea/testData/intentions/moveToCompanion/implicitDispatchReceiver.kt.after
vendored
Normal file
14
idea/testData/intentions/moveToCompanion/implicitDispatchReceiver.kt.after
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
fun println(a: Any) {}
|
||||
|
||||
class InsertThis {
|
||||
val v1 = 1
|
||||
fun use() {
|
||||
Companion.f(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun f(insertThis: InsertThis) {
|
||||
println(insertThis.v1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6886,6 +6886,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implicitDispatchReceiver.kt")
|
||||
public void testImplicitDispatchReceiver() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/moveToCompanion/implicitDispatchReceiver.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inInnerClass.kt")
|
||||
public void testInInnerClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/moveToCompanion/inInnerClass.kt");
|
||||
|
||||
Reference in New Issue
Block a user