Automatic renaming parameter in hierarchy.
This commit is contained in:
@@ -312,6 +312,9 @@
|
||||
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinPropertyProcessor"
|
||||
id="KotlinProperty"
|
||||
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.RenameDynamicMemberHandler"/>
|
||||
<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.references.JetSimpleNameReference;
|
||||
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.name.Name;
|
||||
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.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 {
|
||||
@Override
|
||||
@@ -172,11 +176,11 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
|
||||
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
|
||||
{
|
||||
JetParameterUsage parameterUsage =
|
||||
new JetParameterUsage((JetSimpleNameExpression) element, parameterInfo, functionUsageInfo);
|
||||
new JetParameterUsage((JetElement) element, parameterInfo, functionUsageInfo);
|
||||
result.add(parameterUsage);
|
||||
}
|
||||
}
|
||||
@@ -446,6 +450,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
String newExprText = ((JetParameterUsage) usageInfo).getReplacementText(changeInfo);
|
||||
if (!newExprText.startsWith("this@")) continue;
|
||||
|
||||
if (usageInfo.getElement() instanceof KDocName) continue; // TODO support converting parameter to receiver in KDoc
|
||||
|
||||
JetExpression originalExpr = (JetExpression) usageInfo.getElement();
|
||||
JetScope scope = ResolvePackage.analyze(originalExpr, BodyResolveMode.FULL)
|
||||
.get(BindingContext.RESOLUTION_SCOPE, originalExpr);
|
||||
|
||||
+4
@@ -37,6 +37,10 @@ public class JetMutableMethodDescriptor(val original: JetMethodDescriptor): JetM
|
||||
parameters.remove(index)
|
||||
}
|
||||
|
||||
public fun renameParameter(index: Int, newName: String) {
|
||||
parameters[index].setName(newName)
|
||||
}
|
||||
|
||||
public fun clearParameters() {
|
||||
parameters.clear()
|
||||
receiver = null
|
||||
|
||||
+2
-2
@@ -43,10 +43,10 @@ public abstract class JetExplicitReferenceUsage<T: JetElement>(element: T) : Jet
|
||||
}
|
||||
|
||||
public class JetParameterUsage(
|
||||
element: JetSimpleNameExpression,
|
||||
element: JetElement,
|
||||
private val parameterInfo: JetParameterInfo,
|
||||
val containingFunction: JetFunctionDefinitionUsage<*>
|
||||
) : JetExplicitReferenceUsage<JetSimpleNameExpression>(element) {
|
||||
) : JetExplicitReferenceUsage<JetElement>(element) {
|
||||
override fun processReplacedElement(element: JetElement) {
|
||||
val qualifiedExpression = element.getParent() as? JetQualifiedExpression
|
||||
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;
|
||||
|
||||
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.refactoring.rename.RenameProcessor;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
@@ -38,6 +40,12 @@ public class KdocRenameTest extends LightCodeInsightTestCase {
|
||||
doTest("xyzzy");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities();
|
||||
}
|
||||
|
||||
private void doTest(String newName) throws Exception {
|
||||
configureByFile(getTestName(false) + ".kt");
|
||||
PsiElement element = TargetElementUtilBase
|
||||
|
||||
@@ -24,10 +24,9 @@ import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
||||
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.name.*
|
||||
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.scopes.JetScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||
@@ -57,6 +59,7 @@ private enum class RenameType {
|
||||
KOTLIN_FUNCTION,
|
||||
KOTLIN_PROPERTY,
|
||||
KOTLIN_PACKAGE
|
||||
MARKED_ELEMENT
|
||||
}
|
||||
|
||||
public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
||||
@@ -85,6 +88,7 @@ public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
||||
RenameType.KOTLIN_FUNCTION -> renameKotlinFunctionTest(renameObject, context)
|
||||
RenameType.KOTLIN_PROPERTY -> renameKotlinPropertyTest(renameObject, context)
|
||||
RenameType.KOTLIN_PACKAGE -> renameKotlinPackageTest(renameObject, context)
|
||||
RenameType.MARKED_ELEMENT -> renameMarkedElement(renameObject, context)
|
||||
}
|
||||
|
||||
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) {
|
||||
val classFQN = renameParamsObject.getString("classId").toClassId().asSingleFqName().asString()
|
||||
val newName = renameParamsObject.getString("newName")
|
||||
|
||||
@@ -71,6 +71,12 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
||||
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")
|
||||
public void testDefaultObject_DefaultObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/defaultObject/defaultObject.test");
|
||||
|
||||
Reference in New Issue
Block a user