Move Declarations: Fix processing of self-references
#KT-5847 Fixed
This commit is contained in:
@@ -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<JetImportDirective>() == 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<JetImportDirective>() == null
|
||||
}
|
||||
|
||||
public fun guessNewFileName(declarationsToMove: Collection<JetNamedDeclaration>): String? {
|
||||
if (declarationsToMove.isEmpty()) return null
|
||||
|
||||
@@ -246,6 +269,10 @@ fun postProcessMoveUsages(usages: List<UsageInfo>,
|
||||
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
|
||||
|
||||
idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/selfReferences/after/target/A.kt
Vendored
+3
-1
@@ -1,6 +1,8 @@
|
||||
package target
|
||||
|
||||
class A(val a: A) {
|
||||
class A(val a: A, val a2: A) {
|
||||
val klass = javaClass<A>()
|
||||
val klass2 = javaClass<A>()
|
||||
val aa = A(a)
|
||||
val aa2 = A(a)
|
||||
}
|
||||
+3
-1
@@ -1,8 +1,10 @@
|
||||
package source
|
||||
|
||||
class <caret>A(val a: A) {
|
||||
class <caret>A(val a: A, val a2: source.A) {
|
||||
val klass = javaClass<A>()
|
||||
val klass2 = javaClass<source.A>()
|
||||
val aa = A(a)
|
||||
val aa2 = source.A(a)
|
||||
}
|
||||
|
||||
class B {
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"mainFile": "source/A.kt",
|
||||
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
|
||||
"targetPackage": "target"
|
||||
"targetPackage": "target",
|
||||
"withRuntime": "true"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user