Move: Search Java usages when top-level declaration moves to new facade
#KT-22747 Fixed
This commit is contained in:
+29
-9
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
|
import com.intellij.ide.highlighter.JavaFileType
|
||||||
import com.intellij.ide.util.EditorHelper
|
import com.intellij.ide.util.EditorHelper
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Ref
|
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.PsiElement
|
||||||
import com.intellij.psi.PsiNamedElement
|
import com.intellij.psi.PsiNamedElement
|
||||||
import com.intellij.psi.PsiReference
|
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.psi.search.searches.ReferencesSearch
|
||||||
import com.intellij.refactoring.BaseRefactoringProcessor
|
import com.intellij.refactoring.BaseRefactoringProcessor
|
||||||
import com.intellij.refactoring.move.MoveCallback
|
import com.intellij.refactoring.move.MoveCallback
|
||||||
@@ -41,6 +44,7 @@ import com.intellij.util.containers.MultiMap
|
|||||||
import gnu.trove.THashMap
|
import gnu.trove.THashMap
|
||||||
import gnu.trove.TObjectHashingStrategy
|
import gnu.trove.TObjectHashingStrategy
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
||||||
|
import org.jetbrains.kotlin.asJava.findFacadeClass
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
import org.jetbrains.kotlin.asJava.toLightElements
|
import org.jetbrains.kotlin.asJava.toLightElements
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet
|
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.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
||||||
import org.jetbrains.kotlin.idea.search.projectScope
|
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.idea.util.projectStructure.module
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -153,24 +158,39 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
|
|
||||||
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
|
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
|
||||||
|
|
||||||
fun canSkipUsages(element: PsiElement): Boolean {
|
fun getSearchScope(element: PsiElement): GlobalSearchScope? {
|
||||||
val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return false
|
val projectScope = project.projectScope()
|
||||||
if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return false
|
val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return projectScope
|
||||||
val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, descriptor.moveTarget)
|
if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return projectScope
|
||||||
val targetModule = descriptor.moveTarget.getTargetModule(project) ?: return false
|
val moveTarget = descriptor.moveTarget
|
||||||
return oldContainer == newContainer && ktDeclaration.module == targetModule
|
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<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
|
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
|
||||||
kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
|
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 newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
|
||||||
|
|
||||||
val foundReferences = HashSet<PsiReference>()
|
val foundReferences = HashSet<PsiReference>()
|
||||||
val projectScope = project.projectScope()
|
|
||||||
val results = ReferencesSearch
|
val results = ReferencesSearch
|
||||||
.search(lightElement, projectScope)
|
.search(lightElement, searchScope)
|
||||||
.mapNotNullTo(ArrayList()) { ref ->
|
.mapNotNullTo(ArrayList()) { ref ->
|
||||||
if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) {
|
if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) {
|
||||||
createMoveUsageInfoIfPossible(ref, lightElement, true, false)
|
createMoveUsageInfoIfPossible(ref, lightElement, true, false)
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BarKt.foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
FooKt.foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
fun <caret>foo() {}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "source/foo.kt",
|
||||||
|
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
|
||||||
|
"targetFile": "source/bar.kt"
|
||||||
|
}
|
||||||
@@ -601,6 +601,12 @@ public class MoveTestGenerated extends AbstractMoveTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/fakeOverrideInObject/fakeOverrideInObject.test")
|
||||||
public void testKotlin_moveTopLevelDeclarations_misc_fakeOverrideInObject_FakeOverrideInObject() throws Exception {
|
public void testKotlin_moveTopLevelDeclarations_misc_fakeOverrideInObject_FakeOverrideInObject() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/fakeOverrideInObject/fakeOverrideInObject.test");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/fakeOverrideInObject/fakeOverrideInObject.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user