Move: Extract MoveToKotlinFileProcessor class

This commit is contained in:
Alexey Sedunov
2017-04-10 17:39:09 +03:00
parent cb4d2994a3
commit bdaf73411a
5 changed files with 117 additions and 44 deletions
@@ -28,16 +28,14 @@ import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectori
import com.intellij.usageView.UsageInfo
import com.intellij.usageView.UsageViewDescriptor
import com.intellij.util.containers.MultiMap
import com.intellij.util.text.UniqueNameGenerator
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.allElementsToMove
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.shouldFixFqName
import org.jetbrains.kotlin.psi.KtFile
class MoveFilesWithDeclarationsProcessor @JvmOverloads constructor (
class KotlinAwareMoveFilesOrDirectoriesProcessor @JvmOverloads constructor (
project: Project,
private val elementsToMove: List<PsiElement>,
private val targetDirectory: PsiDirectory,
private val targetFileName: String?,
searchInComments: Boolean,
searchInNonJavaFiles: Boolean,
moveCallback: MoveCallback?,
@@ -50,10 +48,6 @@ class MoveFilesWithDeclarationsProcessor @JvmOverloads constructor (
searchInNonJavaFiles,
moveCallback,
prepareSuccessfulCallback) {
override fun getCommandName(): String {
return if (targetFileName != null) "Move " + (elementsToMove.single() as PsiFile).name else "Move"
}
override fun createUsageViewDescriptor(usages: Array<out UsageInfo>): UsageViewDescriptor {
return MoveFilesWithDeclarationsViewDescriptor(elementsToMove.toTypedArray<PsiElement>(), targetDirectory)
}
@@ -83,17 +77,6 @@ class MoveFilesWithDeclarationsProcessor @JvmOverloads constructor (
return showConflicts(conflicts, usages)
}
// Assign a temporary name to file-under-move to avoid naming conflict during the refactoring
private fun renameFileTemporarily() {
if (targetFileName == null || targetDirectory.findFile(targetFileName) == null) return
val sourceFile = elementsToMove.single() as PsiFile
val temporaryName = UniqueNameGenerator.generateUniqueName("temp", "", ".kt") {
sourceFile.containingDirectory!!.findFile(it) == null
}
sourceFile.name = temporaryName
}
private fun markPsiFiles(mark: PsiFile.() -> Unit) {
fun PsiElement.doMark(mark: PsiFile.() -> Unit) {
when (this) {
@@ -114,20 +97,12 @@ class MoveFilesWithDeclarationsProcessor @JvmOverloads constructor (
}
override fun performRefactoring(usages: Array<UsageInfo>) {
val needTemporaryRename = targetFileName != null && targetDirectory.findFile(targetFileName) != null
if (needTemporaryRename) {
renameFileTemporarily()
}
try {
markShouldFixFqName(true)
super.performRefactoring(usages)
}
finally {
markShouldFixFqName(false)
if (needTemporaryRename) {
(elementsToMove.single() as PsiFile).name = targetFileName!!
}
}
}
}
@@ -0,0 +1,95 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.EmptyRunnable
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor
import com.intellij.usageView.UsageInfo
import com.intellij.usageView.UsageViewDescriptor
import com.intellij.util.containers.MultiMap
import com.intellij.util.text.UniqueNameGenerator
import org.jetbrains.kotlin.psi.KtFile
class MoveToKotlinFileProcessor @JvmOverloads constructor (
project: Project,
private val sourceFile: KtFile,
private val targetDirectory: PsiDirectory,
private val targetFileName: String,
searchInComments: Boolean,
searchInNonJavaFiles: Boolean,
moveCallback: MoveCallback?,
prepareSuccessfulCallback: Runnable = EmptyRunnable.INSTANCE
) : MoveFilesOrDirectoriesProcessor(project,
arrayOf(sourceFile),
targetDirectory,
true,
searchInComments,
searchInNonJavaFiles,
moveCallback,
prepareSuccessfulCallback) {
override fun getCommandName() = "Move ${sourceFile.name}"
override fun createUsageViewDescriptor(usages: Array<out UsageInfo>): UsageViewDescriptor {
return MoveFilesWithDeclarationsViewDescriptor(arrayOf(sourceFile), targetDirectory)
}
override fun preprocessUsages(refUsages: Ref<Array<UsageInfo>>): Boolean {
val usages = refUsages.get()
val (conflictUsages, usagesToProcess) = usages.partition { it is ConflictUsageInfo }
val conflicts = MultiMap<PsiElement, String>()
for (conflictUsage in conflictUsages) {
conflicts.putValues(conflictUsage.element, (conflictUsage as ConflictUsageInfo).messages)
}
refUsages.set(usagesToProcess.toTypedArray())
return showConflicts(conflicts, usages)
}
// Assign a temporary name to file-under-move to avoid naming conflict during the refactoring
private fun renameFileTemporarily() {
if (targetDirectory.findFile(targetFileName) == null) return
val temporaryName = UniqueNameGenerator.generateUniqueName("temp", "", ".kt") {
sourceFile.containingDirectory!!.findFile(it) == null
}
sourceFile.name = temporaryName
}
override fun performRefactoring(usages: Array<UsageInfo>) {
val needTemporaryRename = targetDirectory.findFile(targetFileName) != null
if (needTemporaryRename) {
renameFileTemporarily()
}
try {
super.performRefactoring(usages)
}
finally {
if (needTemporaryRename) {
sourceFile.name = targetFileName
}
}
}
}
@@ -31,10 +31,7 @@ import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.MoveDestination;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.*;
import com.intellij.refactoring.classMembers.AbstractMemberInfoModel;
import com.intellij.refactoring.classMembers.MemberInfoChange;
import com.intellij.refactoring.classMembers.MemberInfoChangeListener;
@@ -738,15 +735,23 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
MoveUtilsKt.setUpdatePackageDirective(sourceFile, cbUpdatePackageDirective.isSelected());
}
invokeRefactoring(
new MoveFilesWithDeclarationsProcessor(myProject,
sourceFiles,
targetDirectory,
targetFileName,
isSearchInComments(),
isSearchInNonJavaFiles(),
moveCallback)
);
BaseRefactoringProcessor processor;
processor = sourceFiles.size() == 1 && targetFileName != null
? new MoveToKotlinFileProcessor(myProject,
CollectionsKt.single(sourceFiles),
targetDirectory,
targetFileName,
isSearchInComments(),
isSearchInNonJavaFiles(),
moveCallback)
: new KotlinAwareMoveFilesOrDirectoriesProcessor(myProject,
sourceFiles,
targetDirectory,
isSearchInComments(),
isSearchInNonJavaFiles(),
moveCallback);
invokeRefactoring(processor);
return;
}
@@ -30,7 +30,7 @@ import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectori
import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveFilesWithDeclarationsProcessor
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.KotlinAwareMoveFilesOrDirectoriesProcessor
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
import org.jetbrains.kotlin.idea.util.application.executeCommand
import org.jetbrains.kotlin.idea.util.application.runWriteAction
@@ -78,11 +78,10 @@ fun invokeMoveFilesOrDirectoriesRefactoring(
if (elementsToMove.isNotEmpty()) {
@Suppress("UNCHECKED_CAST")
val processor = MoveFilesWithDeclarationsProcessor(
val processor = KotlinAwareMoveFilesOrDirectoriesProcessor(
project,
elementsToMove as List<KtFile>,
selectedDir,
null,
false,
false,
moveCallback,
@@ -296,11 +296,10 @@ enum class MoveAction {
}
val targetDirPath = config.getString("targetDirectory")
val targetDir = rootDir.findFileByRelativePath(targetDirPath)!!.toPsiDirectory(project)!!
MoveFilesWithDeclarationsProcessor(
KotlinAwareMoveFilesOrDirectoriesProcessor(
project,
elementsToMove,
targetDir,
(elementsToMove.singleOrNull() as? KtFile)?.name,
searchInComments = true,
searchInNonJavaFiles = true,
moveCallback = null