From 605802847a9f6705e5f68349058ff585cca3223f Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 29 Sep 2015 15:33:05 +0300 Subject: [PATCH] Move Declarations: Fix processing of self-references #KT-5847 Fixed --- .../kotlin/idea/refactoring/move/moveUtils.kt | 39 ++++++++++++++++--- .../misc/selfReferences/after/target/A.kt | 4 +- .../misc/selfReferences/before/source/A.kt | 4 +- .../misc/selfReferences/selfReferences.test | 3 +- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt index ca07b175186..4bbbe4ce74f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver import org.jetbrains.kotlin.idea.core.refactoring.isInJavaSourceRoot +import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.refactoring.fqName.isImported import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.MoveFilesOrDirectoriesDialogWithKotlinOptions import org.jetbrains.kotlin.idea.references.JetReference @@ -90,7 +91,6 @@ public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNa val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.getImportableDescriptor() ?: return null val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(getProject(), descriptor) ?: return null - if (isAncestor(declaration, false)) return null val isCallable = descriptor is CallableDescriptor val isExtension = isCallable && (descriptor as CallableDescriptor).getExtensionReceiverParameter() != null @@ -113,11 +113,25 @@ public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNa DescriptorUtils.getFqName(it).toSafe() } + val oldPackageName = packageNameInfo.oldPackageName + val newPackageName = packageNameInfo.newPackageName return when { isExtension, - packageName == packageNameInfo.oldPackageName, - packageName?.asString() == packageNameInfo.newPackageName.asString(), + packageName == oldPackageName, + packageName?.asString() == newPackageName.asString(), isImported(descriptor) -> { + if (isAncestor(declaration, false)) { + if (descriptor.importableFqName == null) return null + if (isUnqualifiedExtensionReference(refExpr.mainReference, declaration)) return null + if (packageName == null || !newPackageName.isSafe) return null + fqName.asString().let { + val prefix = packageName.asString() + val prefixOffset = it.indexOf(prefix) + val newFqName = FqName(it.replaceRange(prefixOffset..prefixOffset + prefix.length() - 1, newPackageName.asString())) + return MoveRenameSelfUsageInfo(refExpr.mainReference, declaration, newFqName) + } + } + createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false) } @@ -148,6 +162,11 @@ class MoveRenameUsageInfoForExtension( val addImportToOriginalFile: Boolean ): MoveRenameUsageInfo(element, reference, startOffset, endOffset, referencedElement, false) +class MoveRenameSelfUsageInfo(ref: JetSimpleNameReference, refTarget: PsiElement, val newFqName: FqName): + MoveRenameUsageInfo(ref.element, ref, ref.rangeInElement.startOffset, ref.rangeInElement.endOffset, refTarget, false) { + override fun getReference() = super.getReference() as? JetSimpleNameReference +} + fun createMoveUsageInfoIfPossible( reference: PsiReference, referencedElement: PsiElement, @@ -160,9 +179,7 @@ fun createMoveUsageInfoIfPossible( val startOffset = range.getStartOffset() val endOffset = range.getEndOffset() - if (reference is JetReference - && (referencedElement.namedUnwrappedElement as? JetDeclaration)?.isExtensionDeclaration() ?: false - && element.getNonStrictParentOfType() == null) { + if (isUnqualifiedExtensionReference(reference, referencedElement)) { return MoveRenameUsageInfoForExtension( element, reference, startOffset, endOffset, referencedElement, element.getContainingFile()!!, addImportToOriginalFile ) @@ -170,6 +187,12 @@ fun createMoveUsageInfoIfPossible( return MoveRenameUsageInfo(element, reference, startOffset, endOffset, referencedElement, false) } +private fun isUnqualifiedExtensionReference(reference: PsiReference, referencedElement: PsiElement): Boolean { + return reference is JetReference + && (referencedElement.namedUnwrappedElement as? JetDeclaration)?.isExtensionDeclaration() ?: false + && reference.element.getNonStrictParentOfType() == null +} + public fun guessNewFileName(declarationsToMove: Collection): String? { if (declarationsToMove.isEmpty()) return null @@ -246,6 +269,10 @@ fun postProcessMoveUsages(usages: List, nonCodeUsages.add(usage) } + is MoveRenameSelfUsageInfo -> { + usage.reference?.bindToFqName(usage.newFqName, shorteningMode) + } + is MoveRenameUsageInfoForExtension -> { val file = with(usage) { if (addImportToOriginalFile) originalFile else counterpart(originalFile) } as JetFile val declaration = counterpart(usage.getReferencedElement()!!).unwrapped as JetDeclaration diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/after/target/A.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/after/target/A.kt index 9878c2bcbaf..f15b6633d7d 100644 --- a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/after/target/A.kt +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/after/target/A.kt @@ -1,6 +1,8 @@ package target -class A(val a: A) { +class A(val a: A, val a2: A) { val klass = javaClass() + val klass2 = javaClass() val aa = A(a) + val aa2 = A(a) } \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/before/source/A.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/before/source/A.kt index 10121bc8708..0b3774446a4 100644 --- a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/before/source/A.kt +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/before/source/A.kt @@ -1,8 +1,10 @@ package source -class A(val a: A) { +class A(val a: A, val a2: source.A) { val klass = javaClass() + val klass2 = javaClass() val aa = A(a) + val aa2 = source.A(a) } class B { diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/selfReferences.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/selfReferences.test index 69190fd7e7f..04e0582cf93 100644 --- a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/selfReferences.test +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/selfReferences.test @@ -1,5 +1,6 @@ { "mainFile": "source/A.kt", "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", - "targetPackage": "target" + "targetPackage": "target", + "withRuntime": "true" }