Move: Convert implicit receiver to this when moving class member to companion object

#KT-11483 Fixed
This commit is contained in:
Alexey Sedunov
2016-04-25 12:30:35 +03:00
parent 6faedc1adc
commit aaa873f227
6 changed files with 54 additions and 14 deletions

View File

@@ -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

View File

@@ -57,6 +57,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
) {
companion object {
val DEFAULT = Options()
val ALL_ENABLED = Options(true, true)
}
}

View File

@@ -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)
}

View File

@@ -0,0 +1,9 @@
fun println(a: Any) {}
class InsertThis {
val v1 = 1
fun <caret>f() {
println(v1)
}
fun use() { f() }
}

View 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)
}
}
}

View File

@@ -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");