Rename: Conflict detection for type parameters
#KT-13254 Fixed
This commit is contained in:
@@ -261,6 +261,7 @@ Using 'this' as function argument in constructor of non-final class
|
|||||||
- [`KT-13128`](https://youtrack.jetbrains.com/issue/KT-13128) Introduce Variable: Retain entered name after changing "Specify type explicitly" option
|
- [`KT-13128`](https://youtrack.jetbrains.com/issue/KT-13128) Introduce Variable: Retain entered name after changing "Specify type explicitly" option
|
||||||
- [`KT-13054`](https://youtrack.jetbrains.com/issue/KT-13054) Introduce Variable: Skip leading/trailing comments inside selection
|
- [`KT-13054`](https://youtrack.jetbrains.com/issue/KT-13054) Introduce Variable: Skip leading/trailing comments inside selection
|
||||||
- [`KT-13277`](https://youtrack.jetbrains.com/issue/KT-13277) Change Signature: Fix usage processing to prevent interfering with Python support plugin
|
- [`KT-13277`](https://youtrack.jetbrains.com/issue/KT-13277) Change Signature: Fix usage processing to prevent interfering with Python support plugin
|
||||||
|
- [`KT-13254`](https://youtrack.jetbrains.com/issue/KT-13254) Rename: Conflict detection for type parameters
|
||||||
|
|
||||||
##### New features
|
##### New features
|
||||||
|
|
||||||
|
|||||||
@@ -440,6 +440,8 @@
|
|||||||
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinFileProcessor"
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinFileProcessor"
|
||||||
id="KotlinFile"
|
id="KotlinFile"
|
||||||
order="first"/>
|
order="first"/>
|
||||||
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinTypeParameterProcessor"
|
||||||
|
id="KotlinTypeParameter"/>
|
||||||
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler$Processor"
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler$Processor"
|
||||||
id="JavaSyntheticPropertyFromKotlin"/>
|
id="JavaSyntheticPropertyFromKotlin"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter"/>
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.usageView.UsageInfo
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||||
|
|
||||||
|
class RenameKotlinTypeParameterProcessor : RenameKotlinPsiProcessor() {
|
||||||
|
override fun canProcessElement(element: PsiElement) = element is KtTypeParameter
|
||||||
|
|
||||||
|
override fun findCollisions(
|
||||||
|
element: PsiElement,
|
||||||
|
newName: String?,
|
||||||
|
allRenames: MutableMap<out PsiElement, String>,
|
||||||
|
result: MutableList<UsageInfo>
|
||||||
|
) {
|
||||||
|
if (newName == null) return
|
||||||
|
val declaration = element as? KtTypeParameter ?: return
|
||||||
|
val descriptor = declaration.resolveToDescriptor()
|
||||||
|
checkRedeclarations(descriptor, newName, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
|
|||||||
import org.jetbrains.kotlin.idea.core.copied
|
import org.jetbrains.kotlin.idea.core.copied
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.refactoring.explicateAsText
|
import org.jetbrains.kotlin.idea.refactoring.explicateAsText
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.getThisLabelName
|
import org.jetbrains.kotlin.idea.refactoring.getThisLabelName
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.search.and
|
import org.jetbrains.kotlin.idea.search.and
|
||||||
@@ -83,11 +82,28 @@ internal fun checkRedeclarations(
|
|||||||
result: MutableList<UsageInfo>
|
result: MutableList<UsageInfo>
|
||||||
) {
|
) {
|
||||||
fun getSiblingWithNewName(): DeclarationDescriptor? {
|
fun getSiblingWithNewName(): DeclarationDescriptor? {
|
||||||
|
val containingDescriptor = descriptor.containingDeclaration
|
||||||
|
|
||||||
if (descriptor is ValueParameterDescriptor) {
|
if (descriptor is ValueParameterDescriptor) {
|
||||||
return descriptor.containingDeclaration.valueParameters.firstOrNull { it.name.asString() == newName }
|
return (containingDescriptor as CallableDescriptor).valueParameters.firstOrNull { it.name.asString() == newName }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor is TypeParameterDescriptor) {
|
||||||
|
val typeParameters = when (containingDescriptor) {
|
||||||
|
is ClassDescriptor -> containingDescriptor.declaredTypeParameters
|
||||||
|
is CallableDescriptor -> containingDescriptor.typeParameters
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
typeParameters.firstOrNull { it.name.asString() == newName }?.let { return it }
|
||||||
|
|
||||||
|
val containingDeclaration = (containingDescriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() as? KtDeclaration
|
||||||
|
?: return null
|
||||||
|
val dummyVar = KtPsiFactory(containingDeclaration).createProperty("val foo: $newName")
|
||||||
|
val outerScope = containingDeclaration.getResolutionScope()
|
||||||
|
val context = dummyVar.analyzeInContext(outerScope, containingDeclaration)
|
||||||
|
return context[BindingContext.VARIABLE, dummyVar]?.type?.constructor?.declarationDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
val containingDescriptor = descriptor.containingDeclaration
|
|
||||||
val containingScope = when (containingDescriptor) {
|
val containingScope = when (containingDescriptor) {
|
||||||
is ClassDescriptor -> containingDescriptor.unsubstitutedMemberScope
|
is ClassDescriptor -> containingDescriptor.unsubstitutedMemberScope
|
||||||
is PackageFragmentDescriptor -> containingDescriptor.getMemberScope()
|
is PackageFragmentDescriptor -> containingDescriptor.getMemberScope()
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
class A</*rename*/U, V>
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"type": "MARKED_ELEMENT",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "V",
|
||||||
|
"hint": "Type parameter 'V' is already declared in class 'A'"
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class A<T> {
|
||||||
|
inner class B</*rename*/U, V>
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"type": "MARKED_ELEMENT",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "T",
|
||||||
|
"hint": "Type parameter 'T' is already declared in class 'A'"
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun </*rename*/U, V> foo() {
|
||||||
|
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"type": "MARKED_ELEMENT",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "V",
|
||||||
|
"hint": "Type parameter 'V' is already declared in function 'foo'"
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class A<T> {
|
||||||
|
fun </*rename*/U, V> foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"type": "MARKED_ELEMENT",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "T",
|
||||||
|
"hint": "Type parameter 'T' is already declared in class 'A'"
|
||||||
|
}
|
||||||
@@ -281,6 +281,18 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameClassTypeParameterRedeclaration/renameClassTypeParameterRedeclaration.test")
|
||||||
|
public void testRenameClassTypeParameterRedeclaration_RenameClassTypeParameterRedeclaration() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameClassTypeParameterRedeclaration/renameClassTypeParameterRedeclaration.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameClassTypeParameterRedeclarationWithOuterScope/renameClassTypeParameterRedeclarationWithOuterScope.test")
|
||||||
|
public void testRenameClassTypeParameterRedeclarationWithOuterScope_RenameClassTypeParameterRedeclarationWithOuterScope() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameClassTypeParameterRedeclarationWithOuterScope/renameClassTypeParameterRedeclarationWithOuterScope.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("renameClassWithAutoVarConventions/renameClassWithAutoVarConventions.test")
|
@TestMetadata("renameClassWithAutoVarConventions/renameClassWithAutoVarConventions.test")
|
||||||
public void testRenameClassWithAutoVarConventions_RenameClassWithAutoVarConventions() throws Exception {
|
public void testRenameClassWithAutoVarConventions_RenameClassWithAutoVarConventions() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameClassWithAutoVarConventions/renameClassWithAutoVarConventions.test");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameClassWithAutoVarConventions/renameClassWithAutoVarConventions.test");
|
||||||
@@ -353,6 +365,18 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameFunctionTypeParameterRedeclaration/renameFunctionTypeParameterRedeclaration.test")
|
||||||
|
public void testRenameFunctionTypeParameterRedeclaration_RenameFunctionTypeParameterRedeclaration() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameFunctionTypeParameterRedeclaration/renameFunctionTypeParameterRedeclaration.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameFunctionTypeParameterRedeclarationWithOuterScope/renameFunctionTypeParameterRedeclarationWithOuterScope.test")
|
||||||
|
public void testRenameFunctionTypeParameterRedeclarationWithOuterScope_RenameFunctionTypeParameterRedeclarationWithOuterScope() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameFunctionTypeParameterRedeclarationWithOuterScope/renameFunctionTypeParameterRedeclarationWithOuterScope.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("renameGet/get.test")
|
@TestMetadata("renameGet/get.test")
|
||||||
public void testRenameGet_Get() throws Exception {
|
public void testRenameGet_Get() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameGet/get.test");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameGet/get.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user