From c9f659e89b1de27bf53f2b1b60b34a5d4d5b90a6 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 14 Jun 2016 15:16:59 +0300 Subject: [PATCH] Rename: Implement Rename conflict analysis for classes. Qualify class references to resove rename conflicts when possible #KT-8611 Fixed #KT-8562 Fixed (cherry picked from commit 8989ccc) --- ChangeLog.md | 2 + .../CreateKotlinSubClassIntention.kt | 9 +++- .../rename/RenameKotlinClassProcessor.kt | 30 ++++++++++++ .../rename/RenameKotlinPropertyProcessor.kt | 2 +- .../refactoring/rename/renameConflictUtils.kt | 41 ++++++++++++++-- .../after/test/test.kt | 9 ++++ .../before/test/test.kt | 9 ++++ .../clashOfNestedWithOuterClass.test | 6 +++ .../clashWithInnerClass/after/test/test.kt | 9 ++++ .../clashWithInnerClass/before/test/test.kt | 9 ++++ .../clashWithInnerClass.test | 6 +++ .../clashWithNestedClass/after/test/test.kt | 9 ++++ .../clashWithNestedClass/before/test/test.kt | 9 ++++ .../clashWithNestedClass.test | 6 +++ .../clashWithOuterClass/after/test/test.kt | 9 ++++ .../clashWithOuterClass/before/test/test.kt | 9 ++++ .../clashWithOuterClass.test | 6 +++ .../before/test/test.kt | 6 +++ .../nestedClassRedeclaration.test | 7 +++ .../after/test/lib.kt | 3 ++ .../after/test/ref.kt | 8 ++++ .../before/test/lib.kt | 3 ++ .../before/test/ref.kt | 8 ++++ ...ShadowingImplicitlyImportedClassUsage.test | 6 +++ .../after/test/lib.kt | 3 ++ .../after/test/ref.kt | 8 ++++ .../before/test/lib.kt | 3 ++ .../before/test/ref.kt | 8 ++++ ...namedClassShadowingImportedClassUsage.test | 6 +++ .../before/test/test.kt | 4 ++ .../topLevelClassRedeclaration.test | 7 +++ .../rename/RenameTestGenerated.java | 48 +++++++++++++++++++ 32 files changed, 301 insertions(+), 7 deletions(-) create mode 100644 idea/testData/refactoring/rename/clashOfNestedWithOuterClass/after/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashOfNestedWithOuterClass/before/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashOfNestedWithOuterClass/clashOfNestedWithOuterClass.test create mode 100644 idea/testData/refactoring/rename/clashWithInnerClass/after/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashWithInnerClass/before/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashWithInnerClass/clashWithInnerClass.test create mode 100644 idea/testData/refactoring/rename/clashWithNestedClass/after/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashWithNestedClass/before/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashWithNestedClass/clashWithNestedClass.test create mode 100644 idea/testData/refactoring/rename/clashWithOuterClass/after/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashWithOuterClass/before/test/test.kt create mode 100644 idea/testData/refactoring/rename/clashWithOuterClass/clashWithOuterClass.test create mode 100644 idea/testData/refactoring/rename/nestedClassRedeclaration/before/test/test.kt create mode 100644 idea/testData/refactoring/rename/nestedClassRedeclaration/nestedClassRedeclaration.test create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/lib.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/ref.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/lib.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/ref.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/renamedClassShadowingImplicitlyImportedClassUsage.test create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/lib.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/ref.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/lib.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/ref.kt create mode 100644 idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/renamedClassShadowingImportedClassUsage.test create mode 100644 idea/testData/refactoring/rename/topLevelClassRedeclaration/before/test/test.kt create mode 100644 idea/testData/refactoring/rename/topLevelClassRedeclaration/topLevelClassRedeclaration.test diff --git a/ChangeLog.md b/ChangeLog.md index 814bd9535ad..e144e1df234 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -226,6 +226,8 @@ - [`KT-6363`](https://youtrack.jetbrains.com/issue/KT-6363) Do not rename ambiguous references in import directives - [`KT-8541`](https://youtrack.jetbrains.com/issue/KT-8541), [`KT-8786`](https://youtrack.jetbrains.com/issue/KT-8786) Do now show 'Rename overloads' options if target function has no overloads - [`KT-8544`](https://youtrack.jetbrains.com/issue/KT-8544) Show more detailed description in Rename dialog +- [`KT-8562`](https://youtrack.jetbrains.com/issue/KT-8562) Show conflicts dialog on attempt of redeclaration +- [`KT-8611`](https://youtrack.jetbrains.com/issue/KT-8732) Qualify class references to resove rename conflicts when possible - [`KT-8732`](https://youtrack.jetbrains.com/issue/KT-8732) Implement Rename conflict analysis and fixes for properties/parameters - [`KT-8860`](https://youtrack.jetbrains.com/issue/KT-8860) Allow renaming class by constructor delegation call referencing primary constructor - [`KT-8892`](https://youtrack.jetbrains.com/issue/KT-8892) Suggest renaming base declarations on overriding members in object literals diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/CreateKotlinSubClassIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/CreateKotlinSubClassIntention.kt index fba63e444a4..7f694695c73 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/CreateKotlinSubClassIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/CreateKotlinSubClassIntention.kt @@ -100,7 +100,7 @@ class CreateKotlinSubClassIntention : SelfTargetingRangeIntention(KtCla val classFromText = KtPsiFactory(project).createClass(builder.asString()) val body = sealedClass.getOrCreateBody() val klass = body.addBefore(classFromText, body.rBrace) as KtClass - PsiElementRenameHandler.rename(klass, project, sealedClass, editor) + runInteractiveRename(klass, project, sealedClass, editor) chooseAndImplementMethods(project, klass, editor) } @@ -142,11 +142,16 @@ class CreateKotlinSubClassIntention : SelfTargetingRangeIntention(KtCla baseClass, name, visibility) val classFromText = factory.createClass(builder.asString()) val klass = container.parent.addAfter(classFromText, container) as KtClass - PsiElementRenameHandler.rename(klass, project, container, editor) + runInteractiveRename(klass, project, container, editor) chooseAndImplementMethods(project, klass, editor) } } + private fun runInteractiveRename(klass: KtClass, project: Project, container: KtClassOrObject, editor: Editor) { + if (ApplicationManager.getApplication().isUnitTestMode) return + PsiElementRenameHandler.rename(klass, project, container, editor) + } + private fun chooseSubclassToCreate(baseClass: KtClass, baseName: String): CreateClassDialog? { val sourceDir = baseClass.containingFile.containingDirectory diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassProcessor.kt index 4ba771ba84b..c1b4abb8564 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassProcessor.kt @@ -19,16 +19,23 @@ package org.jetbrains.kotlin.idea.refactoring.rename import com.intellij.openapi.editor.Editor import com.intellij.psi.PsiElement import com.intellij.psi.PsiReference +import com.intellij.refactoring.listeners.RefactoringElementListener +import com.intellij.usageView.UsageInfo import org.jetbrains.kotlin.asJava.KtLightClass import org.jetbrains.kotlin.asJava.KtLightClassForExplicitDeclaration import org.jetbrains.kotlin.asJava.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.namedUnwrappedElement +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtConstructor +import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.KtObjectDeclaration import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.utils.SmartList class RenameKotlinClassProcessor : RenameKotlinPsiProcessor() { override fun canProcessElement(element: PsiElement): Boolean { @@ -68,6 +75,23 @@ class RenameKotlinClassProcessor : RenameKotlinPsiProcessor() { return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element] != null } + override fun findCollisions( + element: PsiElement, + newName: String?, + allRenames: MutableMap, + result: MutableList + ) { + if (newName == null) return + val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return + val descriptor = declaration.resolveToDescriptor() as ClassDescriptor + + val collisions = SmartList() + checkRedeclarations(descriptor, newName, collisions) + checkOriginalUsagesRetargeting(declaration, newName, result, collisions) + checkNewNameUsagesRetargeting(declaration, newName, collisions) + result += collisions + } + private fun getClassOrObject(element: PsiElement?): PsiElement? = when (element) { is KtLightClass -> when (element) { @@ -82,4 +106,10 @@ class RenameKotlinClassProcessor : RenameKotlinPsiProcessor() { else -> element as? KtClassOrObject } + + override fun renameElement(element: PsiElement, newName: String?, usages: Array, listener: RefactoringElementListener?) { + super.renameElement(element, newName, usages, listener) + + usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } + } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt index c4766906043..e45dee0fd26 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt @@ -311,7 +311,7 @@ class RenameKotlinPropertyProcessor : RenameKotlinPsiProcessor() { refKindUsages[UsageKind.SIMPLE_PROPERTY_USAGE]?.toTypedArray() ?: arrayOf(), null) - usages.forEach { (it as? UsageInfoWithReplacement)?.apply() } + usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } dropOverrideKeywordIfNecessary(element) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/renameConflictUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/renameConflictUtils.kt index 0bf2420261f..566fb9f6f62 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/renameConflictUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/renameConflictUtils.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.idea.search.restrictToKotlinSources import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.getAllAccessibleVariables import org.jetbrains.kotlin.idea.util.getResolutionScope +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -47,13 +48,17 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue +import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered +import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.resolve.source.getPsi +import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.utils.SmartList +import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList internal fun ResolvedCall<*>.noReceivers() = dispatchReceiver == null && extensionReceiver == null @@ -81,7 +86,12 @@ internal fun checkRedeclarations( is PackageFragmentDescriptor -> containingDescriptor.getMemberScope() else -> return } - containingScope.getDescriptorsFiltered(DescriptorKindFilter.VARIABLES) { it.asString() == newName }.firstOrNull()?.let { candidateDescriptor -> + val descriptorKindFilter = when (descriptor) { + is ClassDescriptor -> DescriptorKindFilter.CLASSIFIERS + is PropertyDescriptor -> DescriptorKindFilter.VARIABLES + else -> return + } + containingScope.getDescriptorsFiltered(descriptorKindFilter) { it.asString() == newName }.firstOrNull()?.let { candidateDescriptor -> val candidate = (candidateDescriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() as? KtNamedDeclaration ?: return val what = candidate.renderDescription().capitalize() val where = candidate.representativeContainer()?.renderDescription() ?: return @@ -97,6 +107,7 @@ private fun LexicalScope.getRelevantDescriptors( val nameAsName = Name.identifier(name) return when (declaration) { is KtProperty, is KtParameter, is PsiField -> getAllAccessibleVariables(nameAsName) + is KtClassOrObject, is PsiClass -> findClassifier(nameAsName, NoLookupLocation.FROM_IDE).singletonOrEmptyList() else -> emptyList() } } @@ -141,7 +152,28 @@ private fun checkUsagesRetargeting( val psiFactory = KtPsiFactory(declaration) - val resolvedCall = refElement.getResolvedCall(context) ?: continue + val resolvedCall = refElement.getResolvedCall(context) + if (resolvedCall == null) { + val typeReference = refElement.getStrictParentOfType() ?: continue + val referencedClass = context[BindingContext.TYPE, typeReference]?.constructor?.declarationDescriptor ?: continue + val referencedClassFqName = FqName(IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(referencedClass)) + val newFqName = if (isNewName) referencedClassFqName.parent().child(Name.identifier(name)) else referencedClassFqName + val fakeVar = psiFactory.createDeclaration("val __foo__: ${newFqName.asString()}") + val newContext = fakeVar.analyzeInContext(scope, refElement) + val referencedClassInNewContext = newContext[BindingContext.TYPE, fakeVar.typeReference!!]?.constructor?.declarationDescriptor + val candidateText = referencedClassInNewContext?.canonicalRender() + if (referencedClassInNewContext == null + || ErrorUtils.isError(referencedClassInNewContext) + || referencedClass.canonicalRender() == candidateText + || accessibleDescriptors.any { it.canonicalRender() == candidateText }) { + usageIterator.set(UsageInfoWithFqNameReplacement(refElement, declaration, newFqName)) + } + else { + reportShadowing(declaration, elementToBindUsageInfosTo, referencedClassInNewContext, refElement, newUsages) + } + continue + } + val callExpression = resolvedCall.call.callElement as? KtExpression ?: continue val fullCallExpression = callExpression.getQualifiedExpressionForSelectorOrThis() @@ -171,7 +203,8 @@ private fun checkUsagesRetargeting( it.value.type.constructor.declarationDescriptor?.getThisLabelName() == expectedLabelName } - val canQualifyThis = receiversWithExpectedName.size <= 1 + val canQualifyThis = receiversWithExpectedName.isEmpty() + || receiversWithExpectedName.size == 1 && (declaration !is KtClassOrObject || expectedLabelName != name) if (canQualifyThis) { psiFactory.createExpressionByPattern("${implicitReceiver.explicateAsText()}.$0", callExpression) } @@ -198,7 +231,7 @@ private fun checkUsagesRetargeting( val newContext = qualifiedExpression.analyzeInContext(scope, refElement) val newResolvedCall = newCallee.getResolvedCall(newContext) - val candidateText = newResolvedCall?.candidateDescriptor?.canonicalRender() + val candidateText = newResolvedCall?.candidateDescriptor?.getImportableDescriptor()?.canonicalRender() if (newResolvedCall != null && !accessibleDescriptors.any { it.canonicalRender() == candidateText } diff --git a/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/after/test/test.kt b/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/after/test/test.kt new file mode 100644 index 00000000000..fe3ad9c0603 --- /dev/null +++ b/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/after/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + class A { + class C { + val a: A = A() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/before/test/test.kt b/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/before/test/test.kt new file mode 100644 index 00000000000..7cd0458fe99 --- /dev/null +++ b/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/before/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + class /*rename*/B { + class C { + val b: B = B() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/clashOfNestedWithOuterClass.test b/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/clashOfNestedWithOuterClass.test new file mode 100644 index 00000000000..b92066d2c49 --- /dev/null +++ b/idea/testData/refactoring/rename/clashOfNestedWithOuterClass/clashOfNestedWithOuterClass.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/test.kt", + "newName": "A", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithInnerClass/after/test/test.kt b/idea/testData/refactoring/rename/clashWithInnerClass/after/test/test.kt new file mode 100644 index 00000000000..90b35af8a03 --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithInnerClass/after/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + inner class C { + inner class C { + val c: A.C = this@A.C() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithInnerClass/before/test/test.kt b/idea/testData/refactoring/rename/clashWithInnerClass/before/test/test.kt new file mode 100644 index 00000000000..0fd30987eca --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithInnerClass/before/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + inner class /*rename*/B { + inner class C { + val b: B = B() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithInnerClass/clashWithInnerClass.test b/idea/testData/refactoring/rename/clashWithInnerClass/clashWithInnerClass.test new file mode 100644 index 00000000000..1836787075b --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithInnerClass/clashWithInnerClass.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/test.kt", + "newName": "C", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithNestedClass/after/test/test.kt b/idea/testData/refactoring/rename/clashWithNestedClass/after/test/test.kt new file mode 100644 index 00000000000..15303abea2f --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithNestedClass/after/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + class C { + class C { + val c: A.C = A.C() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithNestedClass/before/test/test.kt b/idea/testData/refactoring/rename/clashWithNestedClass/before/test/test.kt new file mode 100644 index 00000000000..7cd0458fe99 --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithNestedClass/before/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + class /*rename*/B { + class C { + val b: B = B() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithNestedClass/clashWithNestedClass.test b/idea/testData/refactoring/rename/clashWithNestedClass/clashWithNestedClass.test new file mode 100644 index 00000000000..1836787075b --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithNestedClass/clashWithNestedClass.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/test.kt", + "newName": "C", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithOuterClass/after/test/test.kt b/idea/testData/refactoring/rename/clashWithOuterClass/after/test/test.kt new file mode 100644 index 00000000000..ce9e7627eb4 --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithOuterClass/after/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + inner class A { + inner class C { + val a: A = A() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithOuterClass/before/test/test.kt b/idea/testData/refactoring/rename/clashWithOuterClass/before/test/test.kt new file mode 100644 index 00000000000..0fd30987eca --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithOuterClass/before/test/test.kt @@ -0,0 +1,9 @@ +package test + +class A { + inner class /*rename*/B { + inner class C { + val b: B = B() + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/clashWithOuterClass/clashWithOuterClass.test b/idea/testData/refactoring/rename/clashWithOuterClass/clashWithOuterClass.test new file mode 100644 index 00000000000..b92066d2c49 --- /dev/null +++ b/idea/testData/refactoring/rename/clashWithOuterClass/clashWithOuterClass.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/test.kt", + "newName": "A", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/nestedClassRedeclaration/before/test/test.kt b/idea/testData/refactoring/rename/nestedClassRedeclaration/before/test/test.kt new file mode 100644 index 00000000000..57b468cb63a --- /dev/null +++ b/idea/testData/refactoring/rename/nestedClassRedeclaration/before/test/test.kt @@ -0,0 +1,6 @@ +package test + +class A { + class Foo + class /*rename*/Bar +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/nestedClassRedeclaration/nestedClassRedeclaration.test b/idea/testData/refactoring/rename/nestedClassRedeclaration/nestedClassRedeclaration.test new file mode 100644 index 00000000000..07c158eaae9 --- /dev/null +++ b/idea/testData/refactoring/rename/nestedClassRedeclaration/nestedClassRedeclaration.test @@ -0,0 +1,7 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/test.kt", + "newName": "Foo", + "withRuntime": "true", + "hint": "Class 'Foo' is already declared in class 'A'" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/lib.kt b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/lib.kt new file mode 100644 index 00000000000..a762fef004f --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/lib.kt @@ -0,0 +1,3 @@ +package lib + +class LibType \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/ref.kt b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/ref.kt new file mode 100644 index 00000000000..e1a9a537978 --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/after/test/ref.kt @@ -0,0 +1,8 @@ +package ref + +import lib.LibType + +class String {} + +class Referrer1 { fun method(p1a: String, p1b: kotlin.String) {} } +class Referrer2 { fun method(p2a: String, p2b: LibType) {} } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/lib.kt b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/lib.kt new file mode 100644 index 00000000000..a762fef004f --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/lib.kt @@ -0,0 +1,3 @@ +package lib + +class LibType \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/ref.kt b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/ref.kt new file mode 100644 index 00000000000..42898a1501c --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/before/test/ref.kt @@ -0,0 +1,8 @@ +package ref + +import lib.LibType + +class /*rename*/CustomType {} + +class Referrer1 { fun method(p1a: CustomType, p1b: String) {} } +class Referrer2 { fun method(p2a: CustomType, p2b: LibType) {} } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/renamedClassShadowingImplicitlyImportedClassUsage.test b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/renamedClassShadowingImplicitlyImportedClassUsage.test new file mode 100644 index 00000000000..a87ac35f27f --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/renamedClassShadowingImplicitlyImportedClassUsage.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/ref.kt", + "newName": "String", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/lib.kt b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/lib.kt new file mode 100644 index 00000000000..a762fef004f --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/lib.kt @@ -0,0 +1,3 @@ +package lib + +class LibType \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/ref.kt b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/ref.kt new file mode 100644 index 00000000000..0172df966c1 --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/after/test/ref.kt @@ -0,0 +1,8 @@ +package ref + +import lib.LibType + +class LibType {} + +class Referrer1 { fun method(p1a: ref.LibType, p1b: String) {} } +class Referrer2 { fun method(p2a: ref.LibType, p2b: LibType) {} } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/lib.kt b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/lib.kt new file mode 100644 index 00000000000..a762fef004f --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/lib.kt @@ -0,0 +1,3 @@ +package lib + +class LibType \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/ref.kt b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/ref.kt new file mode 100644 index 00000000000..42898a1501c --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/before/test/ref.kt @@ -0,0 +1,8 @@ +package ref + +import lib.LibType + +class /*rename*/CustomType {} + +class Referrer1 { fun method(p1a: CustomType, p1b: String) {} } +class Referrer2 { fun method(p2a: CustomType, p2b: LibType) {} } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/renamedClassShadowingImportedClassUsage.test b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/renamedClassShadowingImportedClassUsage.test new file mode 100644 index 00000000000..a0d5dbcfb63 --- /dev/null +++ b/idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/renamedClassShadowingImportedClassUsage.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/ref.kt", + "newName": "LibType", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/topLevelClassRedeclaration/before/test/test.kt b/idea/testData/refactoring/rename/topLevelClassRedeclaration/before/test/test.kt new file mode 100644 index 00000000000..a943844fb54 --- /dev/null +++ b/idea/testData/refactoring/rename/topLevelClassRedeclaration/before/test/test.kt @@ -0,0 +1,4 @@ +package test + +class Foo +class /*rename*/Bar \ No newline at end of file diff --git a/idea/testData/refactoring/rename/topLevelClassRedeclaration/topLevelClassRedeclaration.test b/idea/testData/refactoring/rename/topLevelClassRedeclaration/topLevelClassRedeclaration.test new file mode 100644 index 00000000000..575b1e99e9c --- /dev/null +++ b/idea/testData/refactoring/rename/topLevelClassRedeclaration/topLevelClassRedeclaration.test @@ -0,0 +1,7 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test/test.kt", + "newName": "Foo", + "withRuntime": "true", + "hint": "Class 'Foo' is already declared in package 'test'" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java index 6504528a288..a1c4e1f6ade 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -113,6 +113,30 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("clashOfNestedWithOuterClass/clashOfNestedWithOuterClass.test") + public void testClashOfNestedWithOuterClass_ClashOfNestedWithOuterClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/clashOfNestedWithOuterClass/clashOfNestedWithOuterClass.test"); + doTest(fileName); + } + + @TestMetadata("clashWithInnerClass/clashWithInnerClass.test") + public void testClashWithInnerClass_ClashWithInnerClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/clashWithInnerClass/clashWithInnerClass.test"); + doTest(fileName); + } + + @TestMetadata("clashWithNestedClass/clashWithNestedClass.test") + public void testClashWithNestedClass_ClashWithNestedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/clashWithNestedClass/clashWithNestedClass.test"); + doTest(fileName); + } + + @TestMetadata("clashWithOuterClass/clashWithOuterClass.test") + public void testClashWithOuterClass_ClashWithOuterClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/clashWithOuterClass/clashWithOuterClass.test"); + doTest(fileName); + } + @TestMetadata("companionObject/companionObject.test") public void testCompanionObject_CompanionObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/companionObject/companionObject.test"); @@ -155,6 +179,12 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("nestedClassRedeclaration/nestedClassRedeclaration.test") + public void testNestedClassRedeclaration_NestedClassRedeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/nestedClassRedeclaration/nestedClassRedeclaration.test"); + doTest(fileName); + } + @TestMetadata("propertyAccidentalOverrideSubclass/propertyAccidentalOverrideSubclass.test") public void testPropertyAccidentalOverrideSubclass_PropertyAccidentalOverrideSubclass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/propertyAccidentalOverrideSubclass/propertyAccidentalOverrideSubclass.test"); @@ -239,6 +269,18 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("renamedClassShadowingImplicitlyImportedClassUsage/renamedClassShadowingImplicitlyImportedClassUsage.test") + public void testRenamedClassShadowingImplicitlyImportedClassUsage_RenamedClassShadowingImplicitlyImportedClassUsage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renamedClassShadowingImplicitlyImportedClassUsage/renamedClassShadowingImplicitlyImportedClassUsage.test"); + doTest(fileName); + } + + @TestMetadata("renamedClassShadowingImportedClassUsage/renamedClassShadowingImportedClassUsage.test") + public void testRenamedClassShadowingImportedClassUsage_RenamedClassShadowingImportedClassUsage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renamedClassShadowingImportedClassUsage/renamedClassShadowingImportedClassUsage.test"); + doTest(fileName); + } + @TestMetadata("renameEmptyKotlinFile/renameFile.test") public void testRenameEmptyKotlinFile_RenameFile() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameEmptyKotlinFile/renameFile.test"); @@ -845,6 +887,12 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("topLevelClassRedeclaration/topLevelClassRedeclaration.test") + public void testTopLevelClassRedeclaration_TopLevelClassRedeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/topLevelClassRedeclaration/topLevelClassRedeclaration.test"); + doTest(fileName); + } + @TestMetadata("topLevelPropertyRedeclaration/topLevelPropertyRedeclaration.test") public void testTopLevelPropertyRedeclaration_TopLevelPropertyRedeclaration() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/topLevelPropertyRedeclaration/topLevelPropertyRedeclaration.test");