Rename: Fix renaming of function by label reference inside of lambda argument
#KT-7520 Fixed
This commit is contained in:
@@ -474,6 +474,7 @@
|
||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.KotlinDirectoryAsPackageRenameHandler"/>
|
||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameBackingFieldReferenceHandler"/>
|
||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameClassByCompanionObjectShortReferenceHandler"/>
|
||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameFunctionByLabeledReferenceInLambdaArgumentHandler"/>
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableRenamerFactory"/>
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableRenamerFactoryForJavaClass"/>
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableInJavaRenamerFactory"/>
|
||||
|
||||
+7
-1
@@ -23,9 +23,11 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.refactoring.rename.PsiElementRenameHandler
|
||||
import com.intellij.refactoring.rename.inplace.MemberInplaceRenameHandler
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
@@ -37,7 +39,11 @@ abstract class AbstractReferenceSubstitutionRenameHandler<D : DeclarationDescrip
|
||||
protected fun getReferenceExpression(dataContext: DataContext): KtSimpleNameExpression? {
|
||||
val caret = CommonDataKeys.CARET.getData(dataContext) ?: return null
|
||||
val ktFile = CommonDataKeys.PSI_FILE.getData(dataContext) as? KtFile ?: return null
|
||||
return ktFile.findElementAt(caret.offset)?.getNonStrictParentOfType<KtSimpleNameExpression>() ?: return null
|
||||
var elementAtCaret = ktFile.findElementAt(caret.offset)
|
||||
if (elementAtCaret is PsiWhiteSpace) {
|
||||
elementAtCaret = CodeInsightUtils.getElementAtOffsetIgnoreWhitespaceAfter(ktFile, caret.offset)
|
||||
}
|
||||
return elementAtCaret?.getNonStrictParentOfType<KtSimpleNameExpression>()
|
||||
}
|
||||
|
||||
protected abstract fun getTargetDescriptor(dataContext: DataContext): D?
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.references.getCalleeByLambdaArgument
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtLabelReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class RenameFunctionByLabeledReferenceInLambdaArgumentHandler : AbstractReferenceSubstitutionRenameHandler<FunctionDescriptor>() {
|
||||
override fun getTargetDescriptor(dataContext: DataContext): FunctionDescriptor? {
|
||||
val refExpr = getReferenceExpression(dataContext) as? KtLabelReferenceExpression ?: return null
|
||||
val context = refExpr.analyze(BodyResolveMode.PARTIAL)
|
||||
val lambda = context[BindingContext.LABEL_TARGET, refExpr] as? KtFunction ?: return null
|
||||
val calleeExpression = lambda.getCalleeByLambdaArgument() ?: return null
|
||||
return context[BindingContext.REFERENCE_TARGET, calleeExpression] as? FunctionDescriptor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun <R> bar(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
bar { return@bar false }
|
||||
|
||||
bar(fun(): Boolean { return@bar false })
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun <R> /*rename*/foo(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
foo { return@foo false }
|
||||
|
||||
foo(fun(): Boolean { return@foo false })
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "MARKED_ELEMENT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "bar"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun <R> bar(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
bar(fun(): Boolean { return@bar false })
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun <R> foo(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
foo(fun(): Boolean { return@/*rename*/foo false })
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "AUTO_DETECT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "bar"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun <R> bar(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
bar(fun(): Boolean { return@bar false })
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
fun <R> foo(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
foo(fun(): Boolean { return@foo/*rename*/ false })
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "AUTO_DETECT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "bar"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun <R> bar(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
bar {
|
||||
return@bar false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun <R> foo(f: () -> R) = f()
|
||||
|
||||
fun test() {
|
||||
foo {
|
||||
return@/*rename*/foo false
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "AUTO_DETECT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "bar"
|
||||
}
|
||||
@@ -204,6 +204,30 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funWithLabeledReturns/funWithLabeledReturns.test")
|
||||
public void testFunWithLabeledReturns_FunWithLabeledReturns() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/funWithLabeledReturns/funWithLabeledReturns.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("labeledReturnInAnonymousFun/labeledReturnInAnonymousFun.test")
|
||||
public void testLabeledReturnInAnonymousFun_LabeledReturnInAnonymousFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledReturnInAnonymousFun/labeledReturnInAnonymousFun.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("labeledReturnInAnonymousFunBeforeWhitespace/labeledReturnInAnonymousFunBeforeWhitespace.test")
|
||||
public void testLabeledReturnInAnonymousFunBeforeWhitespace_LabeledReturnInAnonymousFunBeforeWhitespace() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledReturnInAnonymousFunBeforeWhitespace/labeledReturnInAnonymousFunBeforeWhitespace.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("labeledReturnInLambda/labeledReturnInLambda.test")
|
||||
public void testLabeledReturnInLambda_LabeledReturnInLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledReturnInLambda/labeledReturnInLambda.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaParameterRedeclaration/lambdaParameterRedeclaration.test")
|
||||
public void testLambdaParameterRedeclaration_LambdaParameterRedeclaration() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/lambdaParameterRedeclaration/lambdaParameterRedeclaration.test");
|
||||
|
||||
Reference in New Issue
Block a user