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 608bdf88ec4..40018e6f836 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 @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations +import com.intellij.ide.highlighter.JavaFileType import com.intellij.ide.util.EditorHelper import com.intellij.openapi.project.Project import com.intellij.openapi.util.Ref @@ -23,6 +24,8 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiElement import com.intellij.psi.PsiNamedElement import com.intellij.psi.PsiReference +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.SearchScope import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.refactoring.BaseRefactoringProcessor import com.intellij.refactoring.move.MoveCallback @@ -41,6 +44,7 @@ import com.intellij.util.containers.MultiMap import gnu.trove.THashMap import gnu.trove.TObjectHashingStrategy import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration +import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.asJava.namedUnwrappedElement import org.jetbrains.kotlin.asJava.toLightElements import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet @@ -49,6 +53,7 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.idea.refactoring.move.* import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler import org.jetbrains.kotlin.idea.search.projectScope +import org.jetbrains.kotlin.idea.search.restrictByFileType import org.jetbrains.kotlin.idea.util.projectStructure.module import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -153,24 +158,39 @@ class MoveKotlinDeclarationsProcessor( val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: "" - fun canSkipUsages(element: PsiElement): Boolean { - val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return false - if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return false - val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, descriptor.moveTarget) - val targetModule = descriptor.moveTarget.getTargetModule(project) ?: return false - return oldContainer == newContainer && ktDeclaration.module == targetModule + fun getSearchScope(element: PsiElement): GlobalSearchScope? { + val projectScope = project.projectScope() + val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return projectScope + if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return projectScope + val moveTarget = descriptor.moveTarget + val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, moveTarget) + val targetModule = moveTarget.getTargetModule(project) ?: return projectScope + if (oldContainer != newContainer || ktDeclaration.module != targetModule) return projectScope + // Check if facade class may change + if (newContainer is ContainerInfo.Package) { + val javaScope = projectScope.restrictByFileType(JavaFileType.INSTANCE) + val currentFile = ktDeclaration.containingKtFile + val newFile = when (moveTarget) { + is KotlinMoveTargetForExistingElement -> moveTarget.targetElement as? KtFile ?: return null + is KotlinMoveTargetForDeferredFile -> return javaScope + else -> return null + } + val currentFacade = currentFile.findFacadeClass() + val newFacade = newFile.findFacadeClass() + return if (currentFacade?.qualifiedName != newFacade?.qualifiedName) javaScope else null + } + return null } fun collectUsages(kotlinToLightElements: Map>, result: MutableCollection) { kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement -> - if (canSkipUsages(lightElement)) return@flatMapTo emptyList() + val searchScope = getSearchScope(lightElement) ?: return@flatMapTo emptyList() val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name) val foundReferences = HashSet() - val projectScope = project.projectScope() val results = ReferencesSearch - .search(lightElement, projectScope) + .search(lightElement, searchScope) .mapNotNullTo(ArrayList()) { ref -> if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) { createMoveUsageInfoIfPossible(ref, lightElement, true, false) diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/Test.java b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/Test.java new file mode 100644 index 00000000000..4effe06b296 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/Test.java @@ -0,0 +1,7 @@ +package test; + +public class Test { + public static void main(String[] args) { + BarKt.foo(); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/bar.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/bar.kt new file mode 100644 index 00000000000..91215d70ff6 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/bar.kt @@ -0,0 +1,3 @@ +package test + +fun foo() {} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/foo.kt new file mode 100644 index 00000000000..a6bea40cf77 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/after/source/foo.kt @@ -0,0 +1,2 @@ +package test + diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/Test.java b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/Test.java new file mode 100644 index 00000000000..f61e218fc93 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/Test.java @@ -0,0 +1,7 @@ +package test; + +public class Test { + public static void main(String[] args) { + FooKt.foo(); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/bar.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/bar.kt new file mode 100644 index 00000000000..a6bea40cf77 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/bar.kt @@ -0,0 +1,2 @@ +package test + diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/foo.kt new file mode 100644 index 00000000000..ebde488ac75 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/before/source/foo.kt @@ -0,0 +1,3 @@ +package test + +fun foo() {} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/facadeClassChangeInTheSamePackage.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/facadeClassChangeInTheSamePackage.test new file mode 100644 index 00000000000..ac5dfab0111 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/facadeClassChangeInTheSamePackage.test @@ -0,0 +1,5 @@ +{ + "mainFile": "source/foo.kt", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetFile": "source/bar.kt" +} 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 01a550850c3..96f98d3e490 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java @@ -601,6 +601,12 @@ public class MoveTestGenerated extends AbstractMoveTest { doTest(fileName); } + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/facadeClassChangeInTheSamePackage.test") + public void testKotlin_moveTopLevelDeclarations_misc_facadeClassChangeInTheSamePackage_FacadeClassChangeInTheSamePackage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/facadeClassChangeInTheSamePackage/facadeClassChangeInTheSamePackage.test"); + doTest(fileName); + } + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/fakeOverrideInObject/fakeOverrideInObject.test") public void testKotlin_moveTopLevelDeclarations_misc_fakeOverrideInObject_FakeOverrideInObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/fakeOverrideInObject/fakeOverrideInObject.test");