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-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-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-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
|
#### Debugger
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT = Options()
|
val DEFAULT = Options()
|
||||||
|
val ALL_ENABLED = Options(true, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-14
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.idea.core.ShortenReferences
|
|||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
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) {
|
when (refElement) {
|
||||||
is PsiReferenceExpression -> {
|
is PsiReferenceExpression -> {
|
||||||
val qualifier = refElement.qualifier
|
val qualifier = refElement.qualifier
|
||||||
@@ -127,15 +128,15 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
|||||||
}
|
}
|
||||||
|
|
||||||
is KtSimpleNameExpression -> {
|
is KtSimpleNameExpression -> {
|
||||||
val call = refElement.parent as? KtCallExpression
|
val call = refElement.parent as? KtCallExpression ?: return
|
||||||
val receiver = call?.getQualifiedExpressionForSelector()?.receiverExpression
|
val psiFactory = KtPsiFactory(refElement)
|
||||||
if (call != null && receiver != null) {
|
val argumentList = call.valueArgumentList
|
||||||
val psiFactory = KtPsiFactory(refElement)
|
?: call.addAfter(psiFactory.createCallArguments("()"), call.typeArgumentList ?: refElement) as KtValueArgumentList
|
||||||
val argumentList = call.valueArgumentList
|
|
||||||
?: call.addAfter(psiFactory.createCallArguments("()"), call.typeArgumentList ?: refElement) as KtValueArgumentList
|
val receiver = call.getQualifiedExpressionForSelector()?.receiverExpression
|
||||||
argumentList.addArgumentBefore(psiFactory.createArgument(receiver),
|
val receiverArg = receiver?.let { psiFactory.createArgument(it) }
|
||||||
argumentList.arguments.firstOrNull())
|
?: psiFactory.createArgument(psiFactory.createExpression("this@${classFqName.asString()}"))
|
||||||
}
|
argumentList.addArgumentBefore(receiverArg, argumentList.arguments.firstOrNull())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,6 +191,8 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
|||||||
nameSuggestions = emptyList()
|
nameSuggestions = emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hasInstanceArg = nameSuggestions.isNotEmpty()
|
||||||
|
|
||||||
element.removeModifier(KtTokens.OPEN_KEYWORD)
|
element.removeModifier(KtTokens.OPEN_KEYWORD)
|
||||||
element.removeModifier(KtTokens.FINAL_KEYWORD)
|
element.removeModifier(KtTokens.FINAL_KEYWORD)
|
||||||
|
|
||||||
@@ -198,8 +201,8 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
|||||||
for (usage in externalUsages) {
|
for (usage in externalUsages) {
|
||||||
val usageElement = usage.element ?: continue
|
val usageElement = usage.element ?: continue
|
||||||
|
|
||||||
if (nameSuggestions.isNotEmpty()) {
|
if (hasInstanceArg) {
|
||||||
moveReceiverToArgumentList(usageElement)
|
moveReceiverToArgumentList(usageElement, containingClass.fqName!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (usage) {
|
when (usage) {
|
||||||
@@ -217,12 +220,18 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
|
|||||||
is ImplicitReceiverUsageInfo -> {
|
is ImplicitReceiverUsageInfo -> {
|
||||||
usage.callExpression
|
usage.callExpression
|
||||||
.let { it.replaced(ktPsiFactory.createExpressionByPattern("$0.$1", ktCompanionRef, it)) }
|
.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)
|
runTemplateForInstanceParam(newDeclaration, nameSuggestions, editor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun println(a: Any) {}
|
||||||
|
|
||||||
|
class InsertThis {
|
||||||
|
val v1 = 1
|
||||||
|
fun <caret>f() {
|
||||||
|
println(v1)
|
||||||
|
}
|
||||||
|
fun use() { f() }
|
||||||
|
}
|
||||||
@@ -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);
|
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")
|
@TestMetadata("inInnerClass.kt")
|
||||||
public void testInInnerClass() throws Exception {
|
public void testInInnerClass() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/moveToCompanion/inInnerClass.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/moveToCompanion/inInnerClass.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user