From 61210d6ba22c785983b923acead371af730aa999 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 24 Nov 2016 15:22:22 +0300 Subject: [PATCH] Move: Fix callable reference processing when moving to another package #KT-14197 Fixed --- ChangeLog.md | 1 + .../MoveKotlinDeclarationsProcessor.kt | 4 ++-- .../kotlin/idea/refactoring/move/moveUtils.kt | 22 ++++++++++++------- .../callableReferences/after/a/util.kt | 3 +++ .../callableReferences/after/b/test.kt | 14 ++++++++++++ .../callableReferences/after/b/util.kt | 3 +++ .../callableReferences/after/c/util.kt | 3 +++ .../callableReferences/before/a/test.kt | 13 +++++++++++ .../callableReferences/before/a/util.kt | 3 +++ .../callableReferences/before/b/util.kt | 3 +++ .../callableReferences/before/c/util.kt | 3 +++ .../callableReferences.test | 5 +++++ .../refactoring/move/MoveTestGenerated.java | 6 +++++ 13 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/a/util.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/test.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/util.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/c/util.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/test.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/util.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/b/util.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/c/util.kt create mode 100644 idea/testData/refactoring/move/kotlin/moveFile/callableReferences/callableReferences.test diff --git a/ChangeLog.md b/ChangeLog.md index 3e8e6b2272b..a932b644433 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -345,6 +345,7 @@ These artifacts include extensions for the types available in the latter JDKs, s - [`KT-14361`](https://youtrack.jetbrains.com/issue/KT-14361) Rename: Do not report redeclaration conflict for private top-level declarations located in different files - [`KT-14596`](https://youtrack.jetbrains.com/issue/KT-14596) Safe Delete: Fix exception on deleting Java class used in Kotlin import directive(s) - [`KT-14325`](https://youtrack.jetbrains.com/issue/KT-14325) Rename: Fix exceptions on moving file with facade class to another package +- [`KT-14197`](https://youtrack.jetbrains.com/issue/KT-14197) Move: Fix callable reference processing when moving to another package ## 1.0.5 diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt index 70cfb0e46e2..1bf076a017c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt @@ -47,7 +47,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet import org.jetbrains.kotlin.idea.core.deleteSingle import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName -import org.jetbrains.kotlin.idea.refactoring.move.MoveRenameUsageInfoForExtension +import org.jetbrains.kotlin.idea.refactoring.move.UnqualifiableMoveRenameUsageInfo import org.jetbrains.kotlin.idea.refactoring.move.createMoveUsageInfoIfPossible import org.jetbrains.kotlin.idea.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler @@ -177,7 +177,7 @@ class MoveKotlinDeclarationsProcessor( val packageNameInfo = descriptor.delegate.getContainerChangeInfo(it, descriptor.moveTarget) val (usagesToProcessLater, usagesToProcessEarly) = it .getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) - .partition { it is MoveRenameUsageInfoForExtension } + .partition { it is UnqualifiableMoveRenameUsageInfo } usages.addAll(usagesToProcessLater) usagesToProcessBeforeMove.addAll(usagesToProcessEarly) } 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 ccd68be9fd3..55816b09059 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt @@ -23,7 +23,6 @@ import com.intellij.openapi.util.Comparing import com.intellij.openapi.util.Key import com.intellij.psi.* import com.intellij.refactoring.RefactoringBundle -import com.intellij.refactoring.RefactoringSettings import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler import com.intellij.refactoring.move.MoveHandler import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor @@ -59,7 +58,6 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.application.executeCommand import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext @@ -133,8 +131,9 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange( val isCallable = descriptor is CallableDescriptor val isExtension = isCallable && declaration.isExtensionDeclaration() + val isCallableReference = isCallableReference(refExpr.mainReference) - if (isCallable) { + if (isCallable && !isCallableReference) { val containingDescriptor = descriptor.containingDeclaration if (isExtension && containingDescriptor is ClassDescriptor) { val implicitClass = (refExpr.getResolvedCall(bindingContext)?.dispatchReceiver as? ImplicitClassReceiver)?.classDescriptor @@ -143,6 +142,7 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange( } return null } + if (!isExtension) { if (refExpr.getReceiverExpression() != null) { return fun(refExpr: KtSimpleNameExpression): UsageInfo? { @@ -177,6 +177,7 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange( if (isAncestor(declaration, false)) { if (descriptor.importableFqName == null) return null if (isUnqualifiedExtensionReference(refExpr.mainReference, declaration)) return null + if (isCallableReference(refExpr.mainReference)) return null if (containerFqName == null || newContainer is ContainerInfo.UnknownPackage) return null return fqName.asString().let { val prefix = containerFqName.asString() @@ -194,7 +195,7 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange( return createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false) } - if (isExtension || containerFqName != null || isImported(descriptor)) return ::doCreateUsageInfo + if (isExtension || isCallableReference || containerFqName != null || isImported(descriptor)) return ::doCreateUsageInfo return null } @@ -210,7 +211,7 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange( class ImplicitCompanionAsDispatchReceiverUsageInfo(callee: KtSimpleNameExpression) : UsageInfo(callee) -class MoveRenameUsageInfoForExtension( +class UnqualifiableMoveRenameUsageInfo( element: PsiElement, reference: PsiReference, startOffset: Int, @@ -237,8 +238,8 @@ fun createMoveUsageInfoIfPossible( val startOffset = range.startOffset val endOffset = range.endOffset - if (isUnqualifiedExtensionReference(reference, referencedElement)) { - return MoveRenameUsageInfoForExtension( + if (isUnqualifiedExtensionReference(reference, referencedElement) || isCallableReference(reference)) { + return UnqualifiableMoveRenameUsageInfo( element, reference, startOffset, endOffset, referencedElement, element.containingFile!!, addImportToOriginalFile ) } @@ -251,6 +252,11 @@ private fun isUnqualifiedExtensionReference(reference: PsiReference, referencedE && reference.element.getNonStrictParentOfType() == null } +private fun isCallableReference(reference: PsiReference): Boolean { + return reference is KtSimpleNameReference + && reference.element.getParentOfTypeAndBranch { callableReference } != null +} + fun guessNewFileName(declarationsToMove: Collection): String? { if (declarationsToMove.isEmpty()) return null @@ -333,7 +339,7 @@ fun postProcessMoveUsages(usages: List, usage.reference?.bindToFqName(usage.newFqName, shorteningMode) } - is MoveRenameUsageInfoForExtension -> { + is UnqualifiableMoveRenameUsageInfo -> { val file = with(usage) { if (addImportToOriginalFile) originalFile else counterpart(originalFile) } as KtFile val declaration = counterpart(usage.referencedElement!!).unwrapped as KtDeclaration ImportInsertHelper.getInstance(usage.project).importDescriptor(file, declaration.resolveToDescriptor()) diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/a/util.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/a/util.kt new file mode 100644 index 00000000000..9466a1261a7 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/a/util.kt @@ -0,0 +1,3 @@ +package a + +fun f2() = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/test.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/test.kt new file mode 100644 index 00000000000..42fe0350373 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/test.kt @@ -0,0 +1,14 @@ +package b + +import a.f2 +import b.f3 +import c.f4 + +fun test() { + val ref1 = ::f1 + val ref2 = ::f2 + val ref3 = ::f3 + val ref4 = ::f4 +} + +fun f1() = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/util.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/util.kt new file mode 100644 index 00000000000..0c0b48f4ed9 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/b/util.kt @@ -0,0 +1,3 @@ +package b + +fun f3() = 3 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/c/util.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/c/util.kt new file mode 100644 index 00000000000..9cadc988011 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/after/c/util.kt @@ -0,0 +1,3 @@ +package c + +fun f4() = 4 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/test.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/test.kt new file mode 100644 index 00000000000..ffd73c17acd --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/test.kt @@ -0,0 +1,13 @@ +package a + +import b.f3 +import c.f4 + +fun test() { + val ref1 = ::f1 + val ref2 = ::f2 + val ref3 = ::f3 + val ref4 = ::f4 +} + +fun f1() = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/util.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/util.kt new file mode 100644 index 00000000000..9466a1261a7 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/a/util.kt @@ -0,0 +1,3 @@ +package a + +fun f2() = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/b/util.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/b/util.kt new file mode 100644 index 00000000000..0c0b48f4ed9 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/b/util.kt @@ -0,0 +1,3 @@ +package b + +fun f3() = 3 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/c/util.kt b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/c/util.kt new file mode 100644 index 00000000000..9cadc988011 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/before/c/util.kt @@ -0,0 +1,3 @@ +package c + +fun f4() = 4 \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/callableReferences.test b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/callableReferences.test new file mode 100644 index 00000000000..07a9c0794bb --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveFile/callableReferences/callableReferences.test @@ -0,0 +1,5 @@ +{ + "mainFile": "a/test.kt", + "type": "MOVE_FILES", + "targetPackage": "b" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java index 8aa92c94691..331ed7649d9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java @@ -246,6 +246,12 @@ public class MoveTestGenerated extends AbstractMoveTest { doTest(fileName); } + @TestMetadata("kotlin/moveFile/callableReferences/callableReferences.test") + public void testKotlin_moveFile_callableReferences_CallableReferences() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveFile/callableReferences/callableReferences.test"); + doTest(fileName); + } + @TestMetadata("kotlin/moveFile/internalReferences/internalReferences.test") public void testKotlin_moveFile_internalReferences_InternalReferences() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveFile/internalReferences/internalReferences.test");