Rename: Fix qualified expression replacement for the case 'invoke' <-> 'get'
#KT-22705 Fixed
This commit is contained in:
@@ -156,6 +156,9 @@ fun KtExpression.getQualifiedExpressionForReceiverOrThis(): KtExpression {
|
|||||||
fun KtExpression.isDotReceiver(): Boolean =
|
fun KtExpression.isDotReceiver(): Boolean =
|
||||||
(parent as? KtDotQualifiedExpression)?.receiverExpression == this
|
(parent as? KtDotQualifiedExpression)?.receiverExpression == this
|
||||||
|
|
||||||
|
fun KtExpression.getPossiblyQualifiedCallExpression(): KtCallExpression? =
|
||||||
|
((this as? KtQualifiedExpression)?.selectorExpression ?: this) as? KtCallExpression
|
||||||
|
|
||||||
// ---------- Block expression -------------------------------------------------------------------------------------------------------------
|
// ---------- Block expression -------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
fun KtElement.blockExpressionsOrSingle(): Sequence<KtElement> =
|
fun KtElement.blockExpressionsOrSingle(): Sequence<KtElement> =
|
||||||
|
|||||||
+22
-6
@@ -20,12 +20,14 @@ import com.google.common.collect.Lists
|
|||||||
import com.intellij.psi.MultiRangeReference
|
import com.intellij.psi.MultiRangeReference
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses
|
||||||
|
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
|
||||||
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
import org.jetbrains.kotlin.lexer.KtToken
|
import org.jetbrains.kotlin.lexer.KtToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression
|
||||||
import org.jetbrains.kotlin.psi.buildExpression
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET
|
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET
|
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET
|
||||||
@@ -55,13 +57,27 @@ class KtArrayAccessReference(
|
|||||||
override fun handleElementRename(newElementName: String?): PsiElement? {
|
override fun handleElementRename(newElementName: String?): PsiElement? {
|
||||||
val arrayAccessExpression = expression
|
val arrayAccessExpression = expression
|
||||||
if (OperatorNameConventions.INVOKE.asString() == newElementName) {
|
if (OperatorNameConventions.INVOKE.asString() == newElementName) {
|
||||||
val callExpression = KtPsiFactory(arrayAccessExpression.project).buildExpression {
|
val replacement = KtPsiFactory(arrayAccessExpression.project).buildExpression {
|
||||||
appendExpression(arrayAccessExpression.arrayExpression)
|
val arrayExpression = arrayAccessExpression.arrayExpression
|
||||||
|
if (arrayExpression is KtQualifiedExpression) {
|
||||||
|
appendExpression(arrayExpression.receiverExpression)
|
||||||
|
appendFixedText(arrayExpression.operationSign.value)
|
||||||
|
appendExpression(arrayExpression.selectorExpression)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendExpression(arrayExpression)
|
||||||
|
}
|
||||||
|
|
||||||
appendFixedText("(")
|
appendFixedText("(")
|
||||||
appendExpressions(arrayAccessExpression.indexExpressions, ",")
|
appendExpressions(arrayAccessExpression.indexExpressions, ",")
|
||||||
appendFixedText(")")
|
appendFixedText(")")
|
||||||
}
|
}
|
||||||
return arrayAccessExpression.replace(callExpression)
|
val fullCallExpression = arrayAccessExpression.replaced(replacement)
|
||||||
|
val callExpression = fullCallExpression.getPossiblyQualifiedCallExpression()
|
||||||
|
if (callExpression != null && callExpression.canMoveLambdaOutsideParentheses()) {
|
||||||
|
callExpression.moveFunctionLiteralOutsideParentheses()
|
||||||
|
}
|
||||||
|
return fullCallExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.renameImplicitConventionalCall(newElementName)
|
return this.renameImplicitConventionalCall(newElementName)
|
||||||
|
|||||||
+7
-1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
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.getQualifiedExpressionForSelectorOrThis
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
@@ -95,14 +96,19 @@ class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReferenc
|
|||||||
|
|
||||||
override fun handleElementRename(newElementName: String?): PsiElement? {
|
override fun handleElementRename(newElementName: String?): PsiElement? {
|
||||||
val callExpression = expression
|
val callExpression = expression
|
||||||
|
val fullCallExpression = callExpression.getQualifiedExpressionForSelectorOrThis()
|
||||||
if (newElementName == OperatorNameConventions.GET.asString() && callExpression.typeArguments.isEmpty()) {
|
if (newElementName == OperatorNameConventions.GET.asString() && callExpression.typeArguments.isEmpty()) {
|
||||||
val arrayAccessExpression = KtPsiFactory(callExpression).buildExpression {
|
val arrayAccessExpression = KtPsiFactory(callExpression).buildExpression {
|
||||||
|
if (fullCallExpression is KtQualifiedExpression) {
|
||||||
|
appendExpression(fullCallExpression.receiverExpression)
|
||||||
|
appendFixedText(fullCallExpression.operationSign.value)
|
||||||
|
}
|
||||||
appendExpression(callExpression.calleeExpression)
|
appendExpression(callExpression.calleeExpression)
|
||||||
appendFixedText("[")
|
appendFixedText("[")
|
||||||
appendExpressions(callExpression.valueArguments.map { it.getArgumentExpression() })
|
appendExpressions(callExpression.valueArguments.map { it.getArgumentExpression() })
|
||||||
appendFixedText("]")
|
appendFixedText("]")
|
||||||
}
|
}
|
||||||
return callExpression.replace(arrayAccessExpression)
|
return fullCallExpression.replace(arrayAccessExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
return renameImplicitConventionalCall(newElementName)
|
return renameImplicitConventionalCall(newElementName)
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun <caret>get(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second) {
|
||||||
|
boo(s) {
|
||||||
|
s.testInvoke[{
|
||||||
|
"Hello"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun invoke(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second) {
|
||||||
|
boo(s) {
|
||||||
|
s.testInvoke {
|
||||||
|
"Hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun <caret>get(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second?, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second?) {
|
||||||
|
boo(s) {
|
||||||
|
s?.testInvoke[{
|
||||||
|
"Hello"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun invoke(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second?, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second?) {
|
||||||
|
boo(s) {
|
||||||
|
s?.testInvoke {
|
||||||
|
"Hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun <caret>invoke(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second) {
|
||||||
|
boo(s) {
|
||||||
|
s.testInvoke {
|
||||||
|
"Hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun get(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second) {
|
||||||
|
boo(s) {
|
||||||
|
s.testInvoke[{
|
||||||
|
"Hello"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun <caret>invoke(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second?, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second?) {
|
||||||
|
boo(s) {
|
||||||
|
s?.testInvoke {
|
||||||
|
"Hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
class WInvoke {
|
||||||
|
operator fun get(body: () -> Unit) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Second {
|
||||||
|
val testInvoke = WInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun boo(s: Second?, body: () -> Unit) { }
|
||||||
|
|
||||||
|
fun foo(s: Second?) {
|
||||||
|
boo(s) {
|
||||||
|
s?.testInvoke[{
|
||||||
|
"Hello"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -94,6 +94,14 @@ class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
|||||||
doTestMemberInplaceRename("get")
|
doTestMemberInplaceRename("get")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testInvokeToGetWithQualifiedExpr() {
|
||||||
|
doTestMemberInplaceRename("get")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInvokeToGetWithSafeQualifiedExpr() {
|
||||||
|
doTestMemberInplaceRename("get")
|
||||||
|
}
|
||||||
|
|
||||||
fun testInvokeToPlus() {
|
fun testInvokeToPlus() {
|
||||||
doTestMemberInplaceRename("plus")
|
doTestMemberInplaceRename("plus")
|
||||||
}
|
}
|
||||||
@@ -106,6 +114,14 @@ class InplaceRenameTest : LightPlatformCodeInsightTestCase() {
|
|||||||
doTestMemberInplaceRename("invoke")
|
doTestMemberInplaceRename("invoke")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testGetToInvokeWithQualifiedExpr() {
|
||||||
|
doTestMemberInplaceRename("invoke")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testGetToInvokeWithSafeQualifiedExpr() {
|
||||||
|
doTestMemberInplaceRename("invoke")
|
||||||
|
}
|
||||||
|
|
||||||
fun testGetToPlus() {
|
fun testGetToPlus() {
|
||||||
doTestMemberInplaceRename("plus")
|
doTestMemberInplaceRename("plus")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user