From b29c704a922dff06175d2b6848d2478292a69680 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 22 Nov 2016 15:30:29 +0300 Subject: [PATCH] Rename: Do not report redeclaration conflict for private top-level declarations located in different files #KT-14361 Fixed --- ChangeLog.md | 1 + .../refactoring/rename/renameConflictUtils.kt | 23 +++++++++++++++---- .../before/test1.kt | 3 +++ .../before/test2.kt | 3 +++ ...PrivateTopLevelDeclarationsNoConflict.test | 6 +++++ .../after/test1.kt | 3 +++ .../after/test2.kt | 3 +++ .../before/test1.kt | 3 +++ .../before/test2.kt | 3 +++ ...PrivateTopLevelDeclarationsNoConflict.test | 5 ++++ .../after/test1.kt | 3 +++ .../after/test2.kt | 3 +++ .../before/test1.kt | 3 +++ .../before/test2.kt | 3 +++ ...privateTopLevelDeclarationsNoConflict.test | 5 ++++ .../rename/RenameTestGenerated.java | 18 +++++++++++++++ 16 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test1.kt create mode 100644 idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test2.kt create mode 100644 idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/nonPrivateTopLevelDeclarationsNoConflict.test create mode 100644 idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test1.kt create mode 100644 idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test2.kt create mode 100644 idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test1.kt create mode 100644 idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test2.kt create mode 100644 idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/privateAndNonPrivateTopLevelDeclarationsNoConflict.test create mode 100644 idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test1.kt create mode 100644 idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test2.kt create mode 100644 idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test1.kt create mode 100644 idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test2.kt create mode 100644 idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test diff --git a/ChangeLog.md b/ChangeLog.md index b3340a88b93..7eb8cd7c847 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -340,6 +340,7 @@ These artifacts include extensions for the types available in the latter JDKs, s - [`KT-14583`](https://youtrack.jetbrains.com/issue/KT-14583) Change Signature: Use new signature when looking for redeclaration conflicts - [`KT-14854`](https://youtrack.jetbrains.com/issue/KT-14854) Extract Interface: Fix NPE on dialog opening - [`KT-14814`](https://youtrack.jetbrains.com/issue/KT-14814) Rename: Fix renaming of .kts file to .kt and vice versa +- [`KT-14361`](https://youtrack.jetbrains.com/issue/KT-14361) Rename: Do not report redeclaration conflict for private top-level declarations located in different files ## 1.0.5 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 b3c83bb88ca..6764139d03b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/renameConflictUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/renameConflictUtils.kt @@ -86,14 +86,24 @@ internal fun checkRedeclarations( newName: String, result: MutableList ) { - fun MemberScope.findSiblingByName(): DeclarationDescriptor? { + fun DeclarationDescriptor.isTopLevelPrivate(): Boolean { + return this is DeclarationDescriptorWithVisibility + && visibility == Visibilities.PRIVATE + && containingDeclaration is PackageFragmentDescriptor + } + + fun isInSameFile(d1: DeclarationDescriptor, d2: DeclarationDescriptor): Boolean { + return (d1 as? DeclarationDescriptorWithSource)?.source?.getPsi()?.containingFile == (d2 as? DeclarationDescriptorWithSource)?.source?.getPsi()?.containingFile + } + + fun MemberScope.findSiblingsByName(): List { val descriptorKindFilter = when (descriptor) { is ClassDescriptor -> DescriptorKindFilter.CLASSIFIERS is PropertyDescriptor -> DescriptorKindFilter.VARIABLES is FunctionDescriptor -> DescriptorKindFilter.FUNCTIONS - else -> return null + else -> return emptyList() } - return getDescriptorsFiltered(descriptorKindFilter) { it.asString() == newName }.firstOrNull { it != descriptor } + return getDescriptorsFiltered(descriptorKindFilter) { it.asString() == newName }.filter { it != descriptor } } fun getSiblingWithNewName(): DeclarationDescriptor? { @@ -120,8 +130,11 @@ internal fun checkRedeclarations( } return when (containingDescriptor) { - is ClassDescriptor -> containingDescriptor.unsubstitutedMemberScope.findSiblingByName() - is PackageFragmentDescriptor -> containingDescriptor.getMemberScope().findSiblingByName() + is ClassDescriptor -> containingDescriptor.unsubstitutedMemberScope.findSiblingsByName().firstOrNull() + is PackageFragmentDescriptor -> containingDescriptor.getMemberScope().findSiblingsByName().firstOrNull { + it != descriptor + && (!(descriptor.isTopLevelPrivate() || it.isTopLevelPrivate()) || isInSameFile(descriptor, it)) + } else -> { val block = (descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi()?.parent as? KtBlockExpression ?: return null diff --git a/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test1.kt b/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test1.kt new file mode 100644 index 00000000000..1091105aad3 --- /dev/null +++ b/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test1.kt @@ -0,0 +1,3 @@ +package p + +val /*rename*/foo = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test2.kt b/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test2.kt new file mode 100644 index 00000000000..fa35a311e03 --- /dev/null +++ b/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/before/test2.kt @@ -0,0 +1,3 @@ +package p + +val bar = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/nonPrivateTopLevelDeclarationsNoConflict.test b/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/nonPrivateTopLevelDeclarationsNoConflict.test new file mode 100644 index 00000000000..6e66dd6fcbf --- /dev/null +++ b/idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/nonPrivateTopLevelDeclarationsNoConflict.test @@ -0,0 +1,6 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test1.kt", + "newName": "bar", + "hint": "Property 'bar' is already declared in package 'p'" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test1.kt b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test1.kt new file mode 100644 index 00000000000..14743cc01ad --- /dev/null +++ b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test1.kt @@ -0,0 +1,3 @@ +package p + +val bar = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test2.kt b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test2.kt new file mode 100644 index 00000000000..da574bc6da6 --- /dev/null +++ b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/after/test2.kt @@ -0,0 +1,3 @@ +package p + +private val bar = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test1.kt b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test1.kt new file mode 100644 index 00000000000..1091105aad3 --- /dev/null +++ b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test1.kt @@ -0,0 +1,3 @@ +package p + +val /*rename*/foo = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test2.kt b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test2.kt new file mode 100644 index 00000000000..da574bc6da6 --- /dev/null +++ b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/before/test2.kt @@ -0,0 +1,3 @@ +package p + +private val bar = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/privateAndNonPrivateTopLevelDeclarationsNoConflict.test b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/privateAndNonPrivateTopLevelDeclarationsNoConflict.test new file mode 100644 index 00000000000..95502bab88a --- /dev/null +++ b/idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/privateAndNonPrivateTopLevelDeclarationsNoConflict.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test1.kt", + "newName": "bar" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test1.kt b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test1.kt new file mode 100644 index 00000000000..ed857bfe2cd --- /dev/null +++ b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test1.kt @@ -0,0 +1,3 @@ +package p + +private val bar = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test2.kt b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test2.kt new file mode 100644 index 00000000000..da574bc6da6 --- /dev/null +++ b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/after/test2.kt @@ -0,0 +1,3 @@ +package p + +private val bar = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test1.kt b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test1.kt new file mode 100644 index 00000000000..7c060fe2a30 --- /dev/null +++ b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test1.kt @@ -0,0 +1,3 @@ +package p + +private val /*rename*/foo = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test2.kt b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test2.kt new file mode 100644 index 00000000000..da574bc6da6 --- /dev/null +++ b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/before/test2.kt @@ -0,0 +1,3 @@ +package p + +private val bar = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test new file mode 100644 index 00000000000..95502bab88a --- /dev/null +++ b/idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test1.kt", + "newName": "bar" +} \ 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 d9a57e5784e..e8683305cf4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -246,6 +246,12 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("nonPrivateTopLevelDeclarationsConflict/nonPrivateTopLevelDeclarationsNoConflict.test") + public void testNonPrivateTopLevelDeclarationsConflict_NonPrivateTopLevelDeclarationsNoConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/nonPrivateTopLevelDeclarationsConflict/nonPrivateTopLevelDeclarationsNoConflict.test"); + doTest(fileName); + } + @TestMetadata("noShadowingConflictForSiblingDeclarations/noShadowingConflictForSiblingDeclarations.test") public void testNoShadowingConflictForSiblingDeclarations_NoShadowingConflictForSiblingDeclarations() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/noShadowingConflictForSiblingDeclarations/noShadowingConflictForSiblingDeclarations.test"); @@ -294,6 +300,18 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("privateAndNonPrivateTopLevelDeclarationsNoConflict/privateAndNonPrivateTopLevelDeclarationsNoConflict.test") + public void testPrivateAndNonPrivateTopLevelDeclarationsNoConflict_PrivateAndNonPrivateTopLevelDeclarationsNoConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/privateAndNonPrivateTopLevelDeclarationsNoConflict/privateAndNonPrivateTopLevelDeclarationsNoConflict.test"); + doTest(fileName); + } + + @TestMetadata("privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test") + public void testPrivateTopLevelDeclarationsNoConflict_PrivateTopLevelDeclarationsNoConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test"); + doTest(fileName); + } + @TestMetadata("propertyAccidentalOverrideSubclass/propertyAccidentalOverrideSubclass.test") public void testPropertyAccidentalOverrideSubclass_PropertyAccidentalOverrideSubclass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/propertyAccidentalOverrideSubclass/propertyAccidentalOverrideSubclass.test");