Rename: Do not silently rename all parameters in function hierarchy
#KT-18325 Fixed
This commit is contained in:
@@ -519,6 +519,7 @@
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticInheritorRenamerFactory"/>
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticOverloadsRenamerFactory"/>
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.KotlinAutomaticTestRenamerFactory"/>
|
||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticParameterRenamerFactory"/>
|
||||
<vetoRenameCondition implementation="org.jetbrains.kotlin.idea.refactoring.KotlinVetoRenameCondition"/>
|
||||
<renameInputValidator implementation="org.jetbrains.kotlin.idea.refactoring.rename.KotlinDeclarationRenameInputValidator"/>
|
||||
<rename.inplace.resolveSnapshotProvider
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.refactoring.JavaRefactoringSettings
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.rename.naming.AutomaticRenamer
|
||||
import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
|
||||
class AutomaticParameterRenamer(element: KtParameter, newName: String) : AutomaticRenamer() {
|
||||
init {
|
||||
processHierarchy(element, newName)
|
||||
}
|
||||
|
||||
private fun processHierarchy(element: KtParameter, newName: String) {
|
||||
val function = element.ownerFunction ?: return
|
||||
for (overrider in HierarchySearchRequest(function, function.useScope).searchOverriders()) {
|
||||
val callable = overrider.namedUnwrappedElement ?: continue
|
||||
if (!callable.canRefactor()) continue
|
||||
val parameter: PsiNamedElement? =
|
||||
when (callable) {
|
||||
is KtCallableDeclaration -> callable.valueParameters.firstOrNull { it.name == element.name }
|
||||
is PsiMethod -> callable.parameterList.parameters.firstOrNull { it.name == element.name }
|
||||
else -> null
|
||||
}
|
||||
if (parameter == null) continue
|
||||
myElements += parameter
|
||||
}
|
||||
suggestAllNames(element.name, newName.quoteIfNeeded())
|
||||
}
|
||||
|
||||
override fun getDialogTitle() = "Rename Parameters"
|
||||
|
||||
override fun getDialogDescription() = "Rename parameter in hierarchy to:"
|
||||
|
||||
override fun entityName() = "Parameter"
|
||||
|
||||
override fun isSelectedByDefault() = true
|
||||
}
|
||||
|
||||
class AutomaticParameterRenamerFactory : AutomaticRenamerFactory {
|
||||
override fun isApplicable(element: PsiElement) = element is KtParameter && element.ownerFunction is KtNamedFunction
|
||||
|
||||
override fun getOptionName() = RefactoringBundle.message("rename.parameters.hierarchy")!!
|
||||
|
||||
override fun isEnabled() = JavaRefactoringSettings.getInstance().isRenameParameterInHierarchy
|
||||
|
||||
override fun setEnabled(enabled: Boolean) {
|
||||
JavaRefactoringSettings.getInstance().isRenameParameterInHierarchy = enabled
|
||||
}
|
||||
|
||||
override fun createRenamer(element: PsiElement, newName: String, usages: Collection<UsageInfo>): AutomaticRenamer {
|
||||
return AutomaticParameterRenamer(element as KtParameter, newName)
|
||||
}
|
||||
}
|
||||
-29
@@ -17,21 +17,12 @@
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.refactoring.JavaRefactoringSettings
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
||||
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.refactoring.getAffectedCallables
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
@@ -63,26 +54,6 @@ class RenameKotlinParameterProcessor : RenameKotlinPsiProcessor() {
|
||||
result += collisions
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
super.prepareRenaming(element, newName, allRenames, scope)
|
||||
|
||||
if (element !is KtParameter || newName == null) return
|
||||
|
||||
val function = element.ownerFunction ?: return
|
||||
val originalDescriptor = function.resolveToDescriptor() as FunctionDescriptor
|
||||
val affectedCallables = getAffectedCallables(element.project, originalDescriptor.getDeepestSuperDeclarations())
|
||||
for (callable in affectedCallables) {
|
||||
if (!callable.canRefactor()) continue
|
||||
val parameter: PsiNamedElement? = when (callable) {
|
||||
is KtCallableDeclaration -> callable.valueParameters.firstOrNull { it.name == element.name }
|
||||
is PsiMethod -> callable.parameterList.parameters.firstOrNull { it.name == element.name }
|
||||
else -> null
|
||||
}
|
||||
if (parameter == null) continue
|
||||
allRenames[parameter] = newName.quoteIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
override fun renameElement(element: PsiElement, newName: String?, usages: Array<out UsageInfo>, listener: RefactoringElementListener?) {
|
||||
super.renameElement(element, newName, usages, listener)
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package testing
|
||||
|
||||
interface Trait {
|
||||
open fun foo(aa: Int, b: String) {
|
||||
open fun foo(a: Int, b: String) {
|
||||
}
|
||||
}
|
||||
|
||||
open class Super {
|
||||
open fun foo(aa: Int, b: String) {
|
||||
open fun foo(a: Int, b: String) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
package testing
|
||||
|
||||
interface Trait {
|
||||
open fun Int.foo(aa: Int, b: String) {
|
||||
open fun Int.foo(a: Int, b: String) {
|
||||
}
|
||||
}
|
||||
|
||||
open class Super {
|
||||
open fun Int.foo(aa: Int, b: String) {
|
||||
open fun Int.foo(a: Int, b: String) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
class J1 implements Foo {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J2 extends J1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J3 extends Foo1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface Foo {
|
||||
fun foo(s: String)
|
||||
}
|
||||
|
||||
open class Foo1 : Foo {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
|
||||
class Foo2 : Foo {
|
||||
override fun foo(x: String) { }
|
||||
}
|
||||
|
||||
class Foo3 : Foo1() {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class J1 implements Foo {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J2 extends J1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J3 extends Foo1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface Foo {
|
||||
fun foo(s: String)
|
||||
}
|
||||
|
||||
open class Foo1 : Foo {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
|
||||
class Foo2 : Foo {
|
||||
override fun foo(/*rename*/s: String) { }
|
||||
}
|
||||
|
||||
class Foo3 : Foo1() {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "MARKED_ELEMENT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "x"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class J1 implements Foo {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J2 extends J1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J3 extends Foo1 {
|
||||
public void foo(String x) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface Foo {
|
||||
fun foo(s: String)
|
||||
}
|
||||
|
||||
open class Foo1 : Foo {
|
||||
override fun foo(x: String) { }
|
||||
}
|
||||
|
||||
class Foo2 : Foo {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
|
||||
class Foo3 : Foo1() {
|
||||
override fun foo(x: String) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class J1 implements Foo {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J2 extends J1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J3 extends Foo1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface Foo {
|
||||
fun foo(s: String)
|
||||
}
|
||||
|
||||
open class Foo1 : Foo {
|
||||
override fun foo(/*rename*/s: String) { }
|
||||
}
|
||||
|
||||
class Foo2 : Foo {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
|
||||
class Foo3 : Foo1() {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "MARKED_ELEMENT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "x"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class J1 implements Foo {
|
||||
public void foo(String x) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J2 extends J1 {
|
||||
public void foo(String x) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J3 extends Foo1 {
|
||||
public void foo(String x) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface Foo {
|
||||
fun foo(x: String)
|
||||
}
|
||||
|
||||
open class Foo1 : Foo {
|
||||
override fun foo(x: String) { }
|
||||
}
|
||||
|
||||
class Foo2 : Foo {
|
||||
override fun foo(x: String) { }
|
||||
}
|
||||
|
||||
class Foo3 : Foo1() {
|
||||
override fun foo(x: String) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class J1 implements Foo {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J2 extends J1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class J3 extends Foo1 {
|
||||
public void foo(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
interface Foo {
|
||||
fun foo(/*rename*/s: String)
|
||||
}
|
||||
|
||||
open class Foo1 : Foo {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
|
||||
class Foo2 : Foo {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
|
||||
class Foo3 : Foo1() {
|
||||
override fun foo(s: String) { }
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "MARKED_ELEMENT",
|
||||
"mainFile": "test.kt",
|
||||
"newName": "x"
|
||||
}
|
||||
@@ -414,6 +414,24 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterHierarchyLeaf/parameterHierarchyLeaf.test")
|
||||
public void testParameterHierarchyLeaf_ParameterHierarchyLeaf() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/parameterHierarchyLeaf/parameterHierarchyLeaf.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterHierarchyMiddle/parameterHierarchyMiddle.test")
|
||||
public void testParameterHierarchyMiddle_ParameterHierarchyMiddle() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/parameterHierarchyMiddle/parameterHierarchyMiddle.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterHierarchyRoot/parameterHierarchyRoot.test")
|
||||
public void testParameterHierarchyRoot_ParameterHierarchyRoot() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/parameterHierarchyRoot/parameterHierarchyRoot.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterRedeclaration/parameterRedeclaration.test")
|
||||
public void testParameterRedeclaration_ParameterRedeclaration() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/parameterRedeclaration/parameterRedeclaration.test");
|
||||
|
||||
Reference in New Issue
Block a user