Automatic renaming parameter in hierarchy.
This commit is contained in:
@@ -312,6 +312,9 @@
|
|||||||
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinPropertyProcessor"
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinPropertyProcessor"
|
||||||
id="KotlinProperty"
|
id="KotlinProperty"
|
||||||
order="first"/>
|
order="first"/>
|
||||||
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinParameterProcessor"
|
||||||
|
id="KotlinParameter"
|
||||||
|
order="first"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameDynamicMemberHandler"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameDynamicMemberHandler"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameOnSecondaryConstructorHandler"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameOnSecondaryConstructorHandler"/>
|
||||||
|
|||||||
+9
-3
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.idea.core.refactoring.RefactoringPackage;
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference;
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference;
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchPackage;
|
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchPackage;
|
||||||
|
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
@@ -73,7 +74,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
|||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
|
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
|
||||||
@Override
|
@Override
|
||||||
@@ -172,11 +176,11 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
|
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
|
||||||
PsiElement element = reference.getElement();
|
PsiElement element = reference.getElement();
|
||||||
|
|
||||||
if (element instanceof JetSimpleNameExpression &&
|
if ((element instanceof JetSimpleNameExpression || element instanceof KDocName) &&
|
||||||
!(element.getParent() instanceof JetValueArgumentName)) // Usages in named arguments of the calls usage will be changed when the function call is changed
|
!(element.getParent() instanceof JetValueArgumentName)) // Usages in named arguments of the calls usage will be changed when the function call is changed
|
||||||
{
|
{
|
||||||
JetParameterUsage parameterUsage =
|
JetParameterUsage parameterUsage =
|
||||||
new JetParameterUsage((JetSimpleNameExpression) element, parameterInfo, functionUsageInfo);
|
new JetParameterUsage((JetElement) element, parameterInfo, functionUsageInfo);
|
||||||
result.add(parameterUsage);
|
result.add(parameterUsage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,6 +450,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
String newExprText = ((JetParameterUsage) usageInfo).getReplacementText(changeInfo);
|
String newExprText = ((JetParameterUsage) usageInfo).getReplacementText(changeInfo);
|
||||||
if (!newExprText.startsWith("this@")) continue;
|
if (!newExprText.startsWith("this@")) continue;
|
||||||
|
|
||||||
|
if (usageInfo.getElement() instanceof KDocName) continue; // TODO support converting parameter to receiver in KDoc
|
||||||
|
|
||||||
JetExpression originalExpr = (JetExpression) usageInfo.getElement();
|
JetExpression originalExpr = (JetExpression) usageInfo.getElement();
|
||||||
JetScope scope = ResolvePackage.analyze(originalExpr, BodyResolveMode.FULL)
|
JetScope scope = ResolvePackage.analyze(originalExpr, BodyResolveMode.FULL)
|
||||||
.get(BindingContext.RESOLUTION_SCOPE, originalExpr);
|
.get(BindingContext.RESOLUTION_SCOPE, originalExpr);
|
||||||
|
|||||||
+4
@@ -37,6 +37,10 @@ public class JetMutableMethodDescriptor(val original: JetMethodDescriptor): JetM
|
|||||||
parameters.remove(index)
|
parameters.remove(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun renameParameter(index: Int, newName: String) {
|
||||||
|
parameters[index].setName(newName)
|
||||||
|
}
|
||||||
|
|
||||||
public fun clearParameters() {
|
public fun clearParameters() {
|
||||||
parameters.clear()
|
parameters.clear()
|
||||||
receiver = null
|
receiver = null
|
||||||
|
|||||||
+2
-2
@@ -43,10 +43,10 @@ public abstract class JetExplicitReferenceUsage<T: JetElement>(element: T) : Jet
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class JetParameterUsage(
|
public class JetParameterUsage(
|
||||||
element: JetSimpleNameExpression,
|
element: JetElement,
|
||||||
private val parameterInfo: JetParameterInfo,
|
private val parameterInfo: JetParameterInfo,
|
||||||
val containingFunction: JetFunctionDefinitionUsage<*>
|
val containingFunction: JetFunctionDefinitionUsage<*>
|
||||||
) : JetExplicitReferenceUsage<JetSimpleNameExpression>(element) {
|
) : JetExplicitReferenceUsage<JetElement>(element) {
|
||||||
override fun processReplacedElement(element: JetElement) {
|
override fun processReplacedElement(element: JetElement) {
|
||||||
val qualifiedExpression = element.getParent() as? JetQualifiedExpression
|
val qualifiedExpression = element.getParent() as? JetQualifiedExpression
|
||||||
val elementToShorten = if (qualifiedExpression?.getReceiverExpression() == element) qualifiedExpression!! else element
|
val elementToShorten = if (qualifiedExpression?.getReceiverExpression() == element) qualifiedExpression!! else element
|
||||||
|
|||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.psi.PsiElement
|
||||||
|
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||||
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.modify
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature
|
||||||
|
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.JetParameter
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
|
public class RenameKotlinParameterProcessor : RenameKotlinPsiProcessor() {
|
||||||
|
override fun canProcessElement(element: PsiElement): Boolean {
|
||||||
|
return element is JetParameter && element.getParent().getParent() is JetNamedFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renameElement(element: PsiElement, newName: String, usages: Array<out UsageInfo>, listener: RefactoringElementListener?) {
|
||||||
|
val function = (element as JetParameter).getParent().getParent() as JetNamedFunction
|
||||||
|
val paramIndex = function.getValueParameters().indexOf(element)
|
||||||
|
assert(paramIndex != -1, { "couldn't find parameter in parent ${element.getElementTextWithContext()}" })
|
||||||
|
|
||||||
|
val context = function.analyze()
|
||||||
|
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor ?: return
|
||||||
|
|
||||||
|
val changeSignatureConfiguration = object : JetChangeSignatureConfiguration {
|
||||||
|
override fun configure(originalDescriptor: JetMethodDescriptor, bindingContext: BindingContext): JetMethodDescriptor {
|
||||||
|
return originalDescriptor.modify { renameParameter(paramIndex, newName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performSilently(affectedFunctions: Collection<PsiElement>) = true
|
||||||
|
}
|
||||||
|
|
||||||
|
runChangeSignature(element.getProject(), descriptor, changeSignatureConfiguration, context, element, "Rename parameter")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class JavaSub extends testing.Middle {
|
||||||
|
void foo(int aa, String b) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package testing
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
open fun foo(aa: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Super {
|
||||||
|
open fun foo(aa: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Middle : Super(), Trait {
|
||||||
|
override fun foo(/*rename*/aa: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub : Middle() {
|
||||||
|
override fun foo(aa: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class JavaSub extends testing.Middle {
|
||||||
|
void foo(int a, String b) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package testing
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
open fun foo(a: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Super {
|
||||||
|
open fun foo(a: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Middle : Super(), Trait {
|
||||||
|
override fun foo(/*rename*/a: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub : Middle() {
|
||||||
|
override fun foo(a: Int, b: String) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"type": "MARKED_ELEMENT",
|
||||||
|
"newName": "aa",
|
||||||
|
"mainFile": "main.kt"
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.idea.kdoc;
|
package org.jetbrains.kotlin.idea.kdoc;
|
||||||
|
|
||||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||||
|
import com.intellij.ide.startup.impl.StartupManagerImpl;
|
||||||
|
import com.intellij.openapi.startup.StartupManager;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.refactoring.rename.RenameProcessor;
|
import com.intellij.refactoring.rename.RenameProcessor;
|
||||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||||
@@ -38,6 +40,12 @@ public class KdocRenameTest extends LightCodeInsightTestCase {
|
|||||||
doTest("xyzzy");
|
doTest("xyzzy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities();
|
||||||
|
}
|
||||||
|
|
||||||
private void doTest(String newName) throws Exception {
|
private void doTest(String newName) throws Exception {
|
||||||
configureByFile(getTestName(false) + ".kt");
|
configureByFile(getTestName(false) + ".kt");
|
||||||
PsiElement element = TargetElementUtilBase
|
PsiElement element = TargetElementUtilBase
|
||||||
|
|||||||
@@ -24,10 +24,9 @@ import com.intellij.openapi.module.Module
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.PsiDocumentManager
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
||||||
import com.intellij.refactoring.rename.RenameProcessor
|
import com.intellij.refactoring.rename.RenameProcessor
|
||||||
@@ -44,6 +43,9 @@ import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase
|
|||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
import org.jetbrains.kotlin.name.*
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||||
@@ -57,6 +59,7 @@ private enum class RenameType {
|
|||||||
KOTLIN_FUNCTION,
|
KOTLIN_FUNCTION,
|
||||||
KOTLIN_PROPERTY,
|
KOTLIN_PROPERTY,
|
||||||
KOTLIN_PACKAGE
|
KOTLIN_PACKAGE
|
||||||
|
MARKED_ELEMENT
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
||||||
@@ -85,6 +88,7 @@ public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
|||||||
RenameType.KOTLIN_FUNCTION -> renameKotlinFunctionTest(renameObject, context)
|
RenameType.KOTLIN_FUNCTION -> renameKotlinFunctionTest(renameObject, context)
|
||||||
RenameType.KOTLIN_PROPERTY -> renameKotlinPropertyTest(renameObject, context)
|
RenameType.KOTLIN_PROPERTY -> renameKotlinPropertyTest(renameObject, context)
|
||||||
RenameType.KOTLIN_PACKAGE -> renameKotlinPackageTest(renameObject, context)
|
RenameType.KOTLIN_PACKAGE -> renameKotlinPackageTest(renameObject, context)
|
||||||
|
RenameType.MARKED_ELEMENT -> renameMarkedElement(renameObject, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hintDirective != null) {
|
if (hintDirective != null) {
|
||||||
@@ -104,6 +108,25 @@ public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renameMarkedElement(renameParamsObject: JsonObject, context: TestContext) {
|
||||||
|
val mainFilePath = renameParamsObject.getString("mainFile")
|
||||||
|
val newName = renameParamsObject.getString("newName")
|
||||||
|
|
||||||
|
doTestCommittingDocuments { rootDir, rootAfter ->
|
||||||
|
val mainFile = rootDir.findChild(mainFilePath)!!
|
||||||
|
val psiFile = PsiManager.getInstance(context.project).findFile(mainFile)!!
|
||||||
|
|
||||||
|
val MARKER_TEXT = "/*rename*/"
|
||||||
|
val marker = psiFile.getText().indexOf(MARKER_TEXT)
|
||||||
|
assert(marker != -1)
|
||||||
|
|
||||||
|
val toRename = psiFile.findElementAt(marker + MARKER_TEXT.length())!!.getNonStrictParentOfType<PsiNamedElement>()!!
|
||||||
|
val substitution = RenamePsiElementProcessor.forElement(toRename).substituteElementToRename(toRename, null)
|
||||||
|
|
||||||
|
runRenameProcessor(context, newName, substitution, true, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun renameJavaClassTest(renameParamsObject: JsonObject, context: TestContext) {
|
private fun renameJavaClassTest(renameParamsObject: JsonObject, context: TestContext) {
|
||||||
val classFQN = renameParamsObject.getString("classId").toClassId().asSingleFqName().asString()
|
val classFQN = renameParamsObject.getString("classId").toClassId().asSingleFqName().asString()
|
||||||
val newName = renameParamsObject.getString("newName")
|
val newName = renameParamsObject.getString("newName")
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("automaticRenamerParameter/parameter.test")
|
||||||
|
public void testAutomaticRenamerParameter_Parameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/automaticRenamerParameter/parameter.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("defaultObject/defaultObject.test")
|
@TestMetadata("defaultObject/defaultObject.test")
|
||||||
public void testDefaultObject_DefaultObject() throws Exception {
|
public void testDefaultObject_DefaultObject() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/defaultObject/defaultObject.test");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/defaultObject/defaultObject.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user