Move: Add conflict checking for "Move directory with classes" case
This commit is contained in:
+1
-13
@@ -43,19 +43,7 @@ class KotlinChangePackageRefactoring(val file: KtFile) {
|
||||
MoveDeclarationsDescriptor(
|
||||
project = project,
|
||||
elementsToMove = file.declarations.filterIsInstance<KtNamedDeclaration>(),
|
||||
moveTarget = object: KotlinDirectoryBasedMoveTarget {
|
||||
override val targetContainerFqName = newFqName
|
||||
|
||||
override val directory: PsiDirectory = file.containingDirectory!!
|
||||
|
||||
override val targetFile: VirtualFile? = directory.virtualFile
|
||||
|
||||
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = originalPsi.containingFile as? KtFile
|
||||
|
||||
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
||||
|
||||
override fun verify(file: PsiFile) = null
|
||||
},
|
||||
moveTarget = KotlinDirectoryMoveTarget(newFqName, file.containingDirectory!!),
|
||||
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||
scanEntireFile = true
|
||||
),
|
||||
|
||||
+13
@@ -98,3 +98,16 @@ class KotlinMoveTargetForDeferredFile(
|
||||
// No additional verification is needed
|
||||
override fun verify(file: PsiFile): String? = null
|
||||
}
|
||||
|
||||
class KotlinDirectoryMoveTarget(
|
||||
override val targetContainerFqName: FqName,
|
||||
override val directory: PsiDirectory
|
||||
) : KotlinDirectoryBasedMoveTarget {
|
||||
override val targetFile: VirtualFile? = directory.virtualFile
|
||||
|
||||
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = originalPsi.containingFile as? KtFile
|
||||
|
||||
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
||||
|
||||
override fun verify(file: PsiFile) = null
|
||||
}
|
||||
+43
-7
@@ -25,18 +25,21 @@ import com.intellij.refactoring.move.moveClassesOrPackages.MoveDirectoryWithClas
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.Function
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.idea.core.getPackage
|
||||
import org.jetbrains.kotlin.idea.refactoring.invokeOnceOnCommandFinish
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsProcessor
|
||||
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.refactoring.invokeOnceOnCommandFinish
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.KotlinMoveUsage
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.KotlinDirectoryMoveTarget
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveConflictChecker
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsProcessor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.*
|
||||
|
||||
class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() {
|
||||
private class FileUsagesWrapper(
|
||||
val psiFile: PsiFile,
|
||||
private data class FileUsagesWrapper(
|
||||
val psiFile: KtFile,
|
||||
val usages: List<UsageInfo>,
|
||||
val moveDeclarationsProcessor: MoveKotlinDeclarationsProcessor?
|
||||
) : UsageInfo(psiFile)
|
||||
@@ -69,6 +72,39 @@ class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() {
|
||||
.mapTo(result) { FileUsagesWrapper(it, fileHandler.findUsages(it, null, searchInComments, searchInNonJavaFiles), null) }
|
||||
}
|
||||
|
||||
override fun preprocessUsages(
|
||||
project: Project,
|
||||
files: MutableSet<PsiFile>,
|
||||
infos: Array<UsageInfo>,
|
||||
directory: PsiDirectory,
|
||||
conflicts: MultiMap<PsiElement, String>
|
||||
) {
|
||||
val psiPackage = directory.getPackage() ?: return
|
||||
val moveTarget = KotlinDirectoryMoveTarget(FqName(psiPackage.qualifiedName), directory)
|
||||
for ((index, usageInfo) in infos.withIndex()) {
|
||||
if (usageInfo !is FileUsagesWrapper) continue
|
||||
|
||||
val elementsToMove = usageInfo.psiFile.declarations
|
||||
if (elementsToMove.isEmpty()) continue
|
||||
|
||||
val (internalUsages, externalUsages) = usageInfo.usages.partition { it is KotlinMoveUsage && it.isInternal }
|
||||
val internalUsageSet = internalUsages.toMutableSet()
|
||||
val externalUsageSet = externalUsages.toMutableSet()
|
||||
|
||||
val conflictChecker = MoveConflictChecker(
|
||||
project,
|
||||
elementsToMove,
|
||||
moveTarget,
|
||||
elementsToMove.first(),
|
||||
allElementsToMove = files
|
||||
)
|
||||
conflictChecker.checkAllConflicts(externalUsageSet, internalUsageSet, conflicts)
|
||||
if (externalUsageSet.size != externalUsages.size || internalUsageSet.size != internalUsages.size) {
|
||||
infos[index] = usageInfo.copy(usages = (externalUsageSet + internalUsageSet).toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeMove(psiFile: PsiFile) {
|
||||
|
||||
}
|
||||
@@ -113,7 +149,7 @@ class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() {
|
||||
val moveDeclarationsProcessor = moveContext.moveDeclarationsProcessor ?: return@body
|
||||
val movedFile = moveContext.newParent.findFile(file.name) ?: return@body
|
||||
|
||||
usagesToProcess += FileUsagesWrapper(movedFile, it.usages, moveDeclarationsProcessor)
|
||||
usagesToProcess += FileUsagesWrapper(movedFile as KtFile, it.usages, moveDeclarationsProcessor)
|
||||
}
|
||||
usagesToProcess.forEach { fileHandler.retargetUsages(it.usages, it.moveDeclarationsProcessor!!) }
|
||||
}
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test.pack
|
||||
|
||||
import test2.J
|
||||
|
||||
class Bar {
|
||||
internal val foo = Foo()
|
||||
val j = J()
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test.pack
|
||||
|
||||
import test2.J
|
||||
|
||||
internal class Foo {
|
||||
val j = J()
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test2;
|
||||
|
||||
import test2.pack.Foo;
|
||||
|
||||
public class J {
|
||||
Foo foo = new Foo();
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test2;
|
||||
|
||||
import test2.pack.Foo;
|
||||
|
||||
public class J {
|
||||
Foo foo = new Foo();
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test2.pack
|
||||
|
||||
import test2.J
|
||||
|
||||
class Bar {
|
||||
internal val foo = Foo()
|
||||
val j = J()
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test2.pack
|
||||
|
||||
import test2.J
|
||||
|
||||
internal class Foo {
|
||||
val j = J()
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
Class test2.J, referenced in property test2.pack.Bar.j, will not be accessible in module A
|
||||
Class test2.J, referenced in property test2.pack.Foo.j, will not be accessible in module A
|
||||
Class test2.pack.Foo, referenced in field J.foo, will not be accessible from module B
|
||||
Class test2.pack.Foo, referenced in field J.foo, will not be accessible from module B
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"mainFile": "B/src/test2/pack/Bar.kt",
|
||||
"type": "MOVE_DIRECTORY_WITH_CLASSES",
|
||||
"sourceDir": "B/src/test2/pack",
|
||||
"targetDir": "A/src/test"
|
||||
}
|
||||
+6
@@ -42,6 +42,12 @@ public class MultiModuleMoveTestGenerated extends AbstractMultiModuleMoveTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveDirectoryToUnrelatedModuleConflict/moveDirectoryToUnrelatedModuleConflict.test")
|
||||
public void testMoveDirectoryToUnrelatedModuleConflict_MoveDirectoryToUnrelatedModuleConflict() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/moveMultiModule/moveDirectoryToUnrelatedModuleConflict/moveDirectoryToUnrelatedModuleConflict.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileWithDeclarationsToUnrelatedModuleConflict/moveFileWithDeclarationsToUnrelatedModuleConflict.test")
|
||||
public void testMoveFileWithDeclarationsToUnrelatedModuleConflict_MoveFileWithDeclarationsToUnrelatedModuleConflict() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/moveMultiModule/moveFileWithDeclarationsToUnrelatedModuleConflict/moveFileWithDeclarationsToUnrelatedModuleConflict.test");
|
||||
|
||||
Reference in New Issue
Block a user