From 691322e4064061820c7ed8d16a3188b272370d20 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 30 Mar 2017 20:47:10 +0300 Subject: [PATCH] Move: Show file dialog if all elements to be moved are KtFile --- .../MoveFilesWithDeclarationsProcessor.kt | 7 +- .../MoveKotlinDeclarationsHandler.kt | 19 +++ .../KotlinMoveFilesOrDirectoriesHandler.kt | 9 +- .../kotlin/idea/refactoring/move/moveUtils.kt | 118 +++++++++++------- 4 files changed, 102 insertions(+), 51 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveFilesWithDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveFilesWithDeclarationsProcessor.kt index b3fa85b7c11..2153ab5d089 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveFilesWithDeclarationsProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveFilesWithDeclarationsProcessor.kt @@ -30,14 +30,15 @@ import com.intellij.util.containers.MultiMap import com.intellij.util.text.UniqueNameGenerator import org.jetbrains.kotlin.psi.KtFile -class MoveFilesWithDeclarationsProcessor( +class MoveFilesWithDeclarationsProcessor @JvmOverloads constructor ( project: Project, private val sourceFiles: List, private val targetDirectory: PsiDirectory, private val targetFileName: String?, searchInComments: Boolean, searchInNonJavaFiles: Boolean, - moveCallback: MoveCallback? + moveCallback: MoveCallback?, + prepareSuccessfulCallback: Runnable = EmptyRunnable.INSTANCE ) : MoveFilesOrDirectoriesProcessor(project, sourceFiles.toTypedArray(), targetDirectory, @@ -45,7 +46,7 @@ class MoveFilesWithDeclarationsProcessor( searchInComments, searchInNonJavaFiles, moveCallback, - EmptyRunnable.INSTANCE) { + prepareSuccessfulCallback) { override fun getCommandName(): String { return if (targetFileName != null) "Move " + sourceFiles.single().name else "Move" } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt index ece33932ec4..d0874d11c1e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt @@ -29,10 +29,13 @@ import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.move.MoveCallback import com.intellij.refactoring.move.MoveHandlerDelegate import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesImpl +import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil import com.intellij.refactoring.util.CommonRefactoringUtil import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.idea.core.getPackage import org.jetbrains.kotlin.idea.refactoring.canRefactor +import org.jetbrains.kotlin.idea.refactoring.move.invokeMoveFilesOrDirectoriesRefactoring +import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinSelectNestedClassRefactoringDialog import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinNestedClassesDialog import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog @@ -100,6 +103,22 @@ class MoveKotlinDeclarationsHandler : MoveHandlerDelegate() { return true } + if (elements.all { it is KtFile }) { + val initialTargetElement = when { + targetContainer is PsiPackage || targetContainer is PsiDirectory -> targetContainer + container is PsiPackage || container is PsiDirectory -> container + else -> null + } + val initialTargetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, initialTargetElement) + val dialog = KotlinAwareMoveFilesOrDirectoriesDialog(project) { + invokeMoveFilesOrDirectoriesRefactoring(it, project, elements, initialTargetDirectory, callback) + } + dialog.setData(elements, initialTargetDirectory, "refactoring.moveFile") + dialog.show() + + return true + } + when (container) { is PsiDirectory, is PsiPackage, is KtFile -> { val targetPackageName = MoveClassesOrPackagesImpl.getInitialTargetPackageName(targetContainer, elements) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveFilesOrDirectoriesHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveFilesOrDirectoriesHandler.kt index a2a6b29d94e..51ccf83d796 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveFilesOrDirectoriesHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveFilesOrDirectoriesHandler.kt @@ -54,9 +54,12 @@ class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() { override fun doMove(project: Project, elements: Array, targetContainer: PsiElement?, callback: MoveCallback?) { if (!(targetContainer == null || targetContainer is PsiDirectory || targetContainer is PsiDirectoryContainer)) return - moveFilesOrDirectories(project, adjustForMove(project, elements, targetContainer) ?: return, targetContainer) { - callback?.refactoringCompleted() - } + moveFilesOrDirectories( + project, + adjustForMove(project, elements, targetContainer) ?: return, + targetContainer, + callback?.let { MoveCallback { it.refactoringCompleted() } } + ) } override fun tryToMove(element: PsiElement, project: Project, dataContext: DataContext?, reference: PsiReference?, editor: Editor?): Boolean { 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 8443bf4d1ef..70111fed644 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt @@ -24,6 +24,7 @@ import com.intellij.openapi.util.Key import com.intellij.psi.* import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler +import com.intellij.refactoring.move.MoveCallback import com.intellij.refactoring.move.MoveHandler import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil @@ -48,6 +49,7 @@ import org.jetbrains.kotlin.idea.codeInsight.shorten.addDelayedImportRequest import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.refactoring.fqName.isImported import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot +import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveFilesWithDeclarationsProcessor import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode @@ -406,12 +408,81 @@ fun postProcessMoveUsages(usages: Collection, var KtFile.updatePackageDirective: Boolean? by UserDataProperty(Key.create("UPDATE_PACKAGE_DIRECTIVE")) +fun invokeMoveFilesOrDirectoriesRefactoring( + moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?, + project: Project, + elements: Array, + initialTargetDirectory: PsiDirectory?, + moveCallback: MoveCallback? +) { + fun closeDialog() { + moveDialog?.close(DialogWrapper.CANCEL_EXIT_CODE) + } + + project.executeCommand(MoveHandler.REFACTORING_NAME) { + val selectedDir = if (moveDialog != null) moveDialog.targetDirectory else initialTargetDirectory + val updatePackageDirective = (moveDialog as? KotlinAwareMoveFilesOrDirectoriesDialog)?.updatePackageDirective + + try { + val choice = if (elements.size > 1 || elements[0] is PsiDirectory) intArrayOf(-1) else null + val elementsToMove = elements.filterNot { + it is PsiFile + && runWriteAction { CopyFilesOrDirectoriesHandler.checkFileExist(selectedDir, choice, it, it.name, "Move") } + } + + elementsToMove.forEach { + MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir!!) + if (it is KtFile && it.isInJavaSourceRoot()) { + it.updatePackageDirective = updatePackageDirective + } + } + + val enableSearchReferences = elements.any { ProjectRootsUtil.isInProjectSource(it) } + + if (elementsToMove.isNotEmpty()) { + @Suppress("UNCHECKED_CAST") + val processor = if (elementsToMove.all { it is KtFile } && selectedDir != null) { + MoveFilesWithDeclarationsProcessor( + project, + elementsToMove as List, + selectedDir, + null, + false, + false, + moveCallback, + Runnable(::closeDialog) + ) + } + else { + MoveFilesOrDirectoriesProcessor( + project, + elementsToMove.toTypedArray(), + selectedDir, + enableSearchReferences, + false, + false, + moveCallback, + Runnable(::closeDialog) + ) + } + processor.run() + } + else { + closeDialog() + } + } + catch (e: IncorrectOperationException) { + CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.message, "refactoring.moveFile", project) + } + } +} + // Mostly copied from MoveFilesOrDirectoriesUtil.doMove() fun moveFilesOrDirectories( project: Project, elements: Array, targetElement: PsiElement?, - moveCallback: (() -> Unit)? = null + moveCallback: MoveCallback? = null ) { elements.forEach { if (it !is PsiFile && it !is PsiDirectory) throw IllegalArgumentException("unexpected element type: " + it) } @@ -421,50 +492,7 @@ fun moveFilesOrDirectories( val initialTargetDirectory = MoveFilesOrDirectoriesUtil.getInitialTargetDirectory(targetDirectory, elements) fun doRun(moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?) { - fun closeDialog() { - moveDialog?.close(DialogWrapper.CANCEL_EXIT_CODE) - } - - project.executeCommand(MoveHandler.REFACTORING_NAME) { - val selectedDir = if (moveDialog != null) moveDialog.targetDirectory else initialTargetDirectory - val updatePackageDirective = (moveDialog as? KotlinAwareMoveFilesOrDirectoriesDialog)?.updatePackageDirective - - try { - val choice = if (elements.size > 1 || elements[0] is PsiDirectory) intArrayOf(-1) else null - val elementsToMove = elements.filterNot { - it is PsiFile - && runWriteAction { CopyFilesOrDirectoriesHandler.checkFileExist(selectedDir, choice, it, it.name, "Move") } - } - - elementsToMove.forEach { - MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir!!) - if (it is KtFile && it.isInJavaSourceRoot()) { - it.updatePackageDirective = updatePackageDirective - } - } - - val enableSearchReferences = elements.any { ProjectRootsUtil.isInProjectSource(it) } - - if (elementsToMove.isNotEmpty()) { - MoveFilesOrDirectoriesProcessor( - project, - elementsToMove.toTypedArray(), - selectedDir, - enableSearchReferences, - false, - false, - moveCallback, - ::closeDialog - ).run() - } - else { - closeDialog() - } - } - catch (e: IncorrectOperationException) { - CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.message, "refactoring.moveFile", project) - } - } + invokeMoveFilesOrDirectoriesRefactoring(moveDialog, project, elements, initialTargetDirectory, moveCallback) } if (ApplicationManager.getApplication().isUnitTestMode) {