[kotlin] Allow for Kotlin move refactoring to create files not matching the package

By default move refactoring would always try to create a directory structure that matches the package structure, but in some use cases this is not convenient. #KTIJ-22984

GitOrigin-RevId: fdd08c37237efd4eafc03cc663455efd6e56a4a1
This commit is contained in:
Bart van Helvert
2024-07-10 23:56:51 +00:00
committed by intellij-monorepo-bot
parent 5443a398d9
commit a8c764bc9c
8 changed files with 20 additions and 27 deletions
@@ -193,7 +193,7 @@ class CopyKotlinDeclarationsHandler : AbstractCopyKotlinDeclarationsHandler() {
try {
val targetDirectory = runWriteAction {
targetData.targetDirWrapper.getOrCreateTarget() as PsiDirectory
targetData.targetDirWrapper.getOrCreateTarget(dirStructureMatchesPkg = true) as PsiDirectory
}
val targetFileName =
@@ -16,6 +16,7 @@ sealed class K2MoveOperationDescriptor<T : K2MoveDescriptor>(
val searchForText: Boolean,
val searchInComments: Boolean,
val searchReferences: Boolean,
val dirStructureMatchesPkg: Boolean,
val moveCallBack: MoveCallback? = null
) {
init {
@@ -32,6 +33,7 @@ sealed class K2MoveOperationDescriptor<T : K2MoveDescriptor>(
searchForText: Boolean,
searchInComments: Boolean,
searchReferences: Boolean,
dirStructureMatchesPkg: Boolean,
moveCallBack: MoveCallback? = null
) : K2MoveOperationDescriptor<K2MoveDescriptor.Files>(
project,
@@ -39,6 +41,7 @@ sealed class K2MoveOperationDescriptor<T : K2MoveDescriptor>(
searchForText,
searchInComments,
searchReferences,
dirStructureMatchesPkg,
moveCallBack
) {
override val sourceElements: List<PsiFileSystemItem> get() = moveDescriptors.flatMap { it.source.elements }
@@ -54,6 +57,7 @@ sealed class K2MoveOperationDescriptor<T : K2MoveDescriptor>(
searchForText: Boolean,
searchInComments: Boolean,
searchReferences: Boolean,
dirStructureMatchesPkg: Boolean,
moveCallBack: MoveCallback? = null
) : K2MoveOperationDescriptor<K2MoveDescriptor.Declarations>(
project,
@@ -61,6 +65,7 @@ sealed class K2MoveOperationDescriptor<T : K2MoveDescriptor>(
searchForText,
searchInComments,
searchReferences,
dirStructureMatchesPkg,
moveCallBack
) {
override val sourceElements: List<KtNamedDeclaration> get() = moveDescriptors.flatMap { it.source.elements }
@@ -21,35 +21,19 @@ sealed interface K2MoveTargetDescriptor {
val pkgName: FqName
/**
* Gets or creates the target location, like a file or directory. It might be the case that the target directory or target file doesn't
* exist yet. In this case this method will create the file or directory based on the [baseDirectory] and [pkgName]. The creation of
* the target is thus package aware, example:
* ```
* src/
* Foo.kt <--- root pkg
* a/Bar.kt
* ```
* If we move `Bar.kt` to `src/b` and change the pkg to `b``the [baseDirectory] will be `src` but because the package is `b` we will
* and `Foo.kt` is in the root package we will create `src/b`.
*
* This also works when the project structure doesn't match the directory structure:
* ```
* src/
* Foo.kt <--- package c.d
* a/Bar.kt
* ```
* If we move `Bar.kt` to `src/b` and change the pkg to `c.d.b``the [baseDirectory] will be `src` but because the package is `c.d.b`
* and `Foo.kt` has package c.d we won't create directory `src/c/d/b` but instead create src/d.
* Gets or creates the target
*/
@RequiresWriteLock
fun getOrCreateTarget(): PsiFileSystemItem
fun getOrCreateTarget(dirStructureMatchesPkg: Boolean): PsiFileSystemItem
open class Directory(
override val pkgName: FqName,
override val baseDirectory: PsiDirectory
) : K2MoveTargetDescriptor {
override fun getOrCreateTarget(): PsiFileSystemItem {
override fun getOrCreateTarget(dirStructureMatchesPkg: Boolean): PsiFileSystemItem {
if (!dirStructureMatchesPkg) return baseDirectory
val implicitPkgPrefix = baseDirectory.getFqNameWithImplicitPrefixOrRoot()
val pkgSuffix = pkgName.asString().removePrefix(implicitPkgPrefix.asString()).removePrefix(".")
val file = VfsUtilCore.findRelativeFile(pkgSuffix.replace('.', java.io.File.separatorChar), baseDirectory.virtualFile)
@@ -63,8 +47,8 @@ sealed interface K2MoveTargetDescriptor {
pkgName: FqName,
baseDirectory: PsiDirectory
) : Directory(pkgName, baseDirectory) {
override fun getOrCreateTarget(): KtFile {
val directory = super.getOrCreateTarget() as PsiDirectory
override fun getOrCreateTarget(dirStructureMatchesPkg: Boolean): KtFile {
val directory = super.getOrCreateTarget(dirStructureMatchesPkg) as PsiDirectory
return getOrCreateKotlinFile(fileName, directory, pkgName.asString())
}
}
@@ -70,7 +70,7 @@ class K2MoveDeclarationsRefactoringProcessor(
allowAnalysisOnEdt {
operationDescriptor.moveDescriptors.forEach { moveDescriptor ->
val elementsToMove = moveDescriptor.source.elements
val targetFile = moveDescriptor.target.getOrCreateTarget()
val targetFile = moveDescriptor.target.getOrCreateTarget(operationDescriptor.dirStructureMatchesPkg)
val sourceFiles = elementsToMove.map { it.containingKtFile }.distinct()
val oldToNewMap = elementsToMove.moveInto(targetFile)
moveDescriptor.source.elements.forEach(PsiElement::deleteSingle)
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.KtNamedDeclaration
class K2MoveFilesOrDirectoriesRefactoringProcessor(descriptor: K2MoveOperationDescriptor.Files) : MoveFilesOrDirectoriesProcessor(
descriptor.project,
descriptor.sourceElements.toTypedArray(),
runWriteAction { descriptor.moveDescriptors.first().target.getOrCreateTarget() as PsiDirectory }, // TODO how to do multi target move?
runWriteAction { descriptor.moveDescriptors.first().target.getOrCreateTarget(descriptor.dirStructureMatchesPkg) as PsiDirectory }, // TODO how to do multi target move?
descriptor.searchReferences,
descriptor.searchInComments,
descriptor.searchForText,
@@ -143,6 +143,7 @@ sealed class K2MoveModel {
searchForText.state,
searchReferences,
searchInComments.state,
dirStructureMatchesPkg = true,
moveCallBack
)
return operationDescriptor
@@ -174,6 +175,7 @@ sealed class K2MoveModel {
searchForText.state,
searchReferences,
searchInComments.state,
dirStructureMatchesPkg = true,
moveCallBack
)
}
@@ -79,7 +79,8 @@ internal object K2MoveFileOrDirectoriesRefactoringAction : KotlinMoveRefactoring
listOf(moveDescriptor),
shouldUpdateReferences(config, sourceDescriptor.elements.first(), targetDescriptor.baseDirectory),
config.searchInComments(),
config.searchReferences()
config.searchReferences(),
dirStructureMatchesPkg = true
)
K2MoveFilesOrDirectoriesRefactoringProcessor(moveOperationDescriptor).run()
}
@@ -73,6 +73,7 @@ internal object K2MoveTopLevelRefactoringAction : KotlinMoveRefactoringAction {
config.searchForText(),
config.searchInComments(),
config.searchReferences(),
dirStructureMatchesPkg = true
)
K2MoveDeclarationsRefactoringProcessor(moveOperationDescriptor).run()
}