Minor: clean up copy refactoring
This commit is contained in:
+23
-32
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package org.jetbrains.kotlin.idea.refactoring.copy
|
||||
|
||||
@@ -53,9 +42,9 @@ import kotlin.math.max
|
||||
|
||||
// Based on com.intellij.refactoring.copy.CopyClassDialog
|
||||
class CopyKotlinDeclarationDialog(
|
||||
declaration: KtNamedDeclaration,
|
||||
private val defaultTargetDirectory: PsiDirectory?,
|
||||
private val project: Project
|
||||
declaration: KtNamedDeclaration,
|
||||
private val defaultTargetDirectory: PsiDirectory?,
|
||||
private val project: Project
|
||||
) : DialogWrapper(project, true) {
|
||||
private val informationLabel = JLabel()
|
||||
private val classNameField = EditorTextField("")
|
||||
@@ -76,18 +65,19 @@ class CopyKotlinDeclarationDialog(
|
||||
get() = ((destinationComboBox.comboBox.selectedItem as? DirectoryChooser.ItemWrapper)?.directory ?: originalFile).sourceRoot
|
||||
|
||||
init {
|
||||
informationLabel.text = RefactoringBundle.message("copy.class.copy.0.1", UsageViewUtil.getType(declaration), UsageViewUtil.getLongName(declaration))
|
||||
informationLabel.text =
|
||||
RefactoringBundle.message("copy.class.copy.0.1", UsageViewUtil.getType(declaration), UsageViewUtil.getLongName(declaration))
|
||||
informationLabel.font = informationLabel.font.deriveFont(Font.BOLD)
|
||||
|
||||
init()
|
||||
|
||||
destinationComboBox.setData(
|
||||
project,
|
||||
defaultTargetDirectory,
|
||||
Pass { setErrorText(it, destinationComboBox) },
|
||||
packageNameField.childComponent
|
||||
project,
|
||||
defaultTargetDirectory,
|
||||
Pass { setErrorText(it, destinationComboBox) },
|
||||
packageNameField.childComponent
|
||||
)
|
||||
classNameField.setText(UsageViewUtil.getShortName(declaration))
|
||||
classNameField.text = UsageViewUtil.getShortName(declaration)
|
||||
classNameField.selectAll()
|
||||
}
|
||||
|
||||
@@ -97,7 +87,8 @@ class CopyKotlinDeclarationDialog(
|
||||
|
||||
override fun createNorthPanel(): JComponent? {
|
||||
val qualifiedName = qualifiedName
|
||||
packageNameField = PackageNameReferenceEditorCombo(qualifiedName, project, RECENTS_KEY, RefactoringBundle.message("choose.destination.package"))
|
||||
packageNameField =
|
||||
PackageNameReferenceEditorCombo(qualifiedName, project, RECENTS_KEY, RefactoringBundle.message("choose.destination.package"))
|
||||
packageNameField.setTextFieldPreferredWidth(max(qualifiedName.length + 5, 40))
|
||||
packageLabel.text = RefactoringBundle.message("destination.package")
|
||||
packageLabel.labelFor = packageNameField
|
||||
@@ -111,12 +102,12 @@ class CopyKotlinDeclarationDialog(
|
||||
val panel = JPanel(BorderLayout())
|
||||
panel.add(openInEditorCheckBox, BorderLayout.EAST)
|
||||
return FormBuilder.createFormBuilder()
|
||||
.addComponent(informationLabel)
|
||||
.addLabeledComponent(RefactoringBundle.message("copy.files.new.name.label"), classNameField, UIUtil.LARGE_VGAP)
|
||||
.addLabeledComponent(packageLabel, packageNameField)
|
||||
.addLabeledComponent(label, destinationComboBox)
|
||||
.addComponent(panel)
|
||||
.panel
|
||||
.addComponent(informationLabel)
|
||||
.addLabeledComponent(RefactoringBundle.message("copy.files.new.name.label"), classNameField, UIUtil.LARGE_VGAP)
|
||||
.addLabeledComponent(packageLabel, packageNameField)
|
||||
.addLabeledComponent(label, destinationComboBox)
|
||||
.addComponent(panel)
|
||||
.panel
|
||||
}
|
||||
|
||||
private val qualifiedName: String
|
||||
@@ -144,8 +135,7 @@ class CopyKotlinDeclarationDialog(
|
||||
|
||||
try {
|
||||
targetDirectory = destinationComboBox.selectDirectory(PackageWrapper(manager, packageName), false)
|
||||
}
|
||||
catch (e: IncorrectOperationException) {
|
||||
} catch (e: IncorrectOperationException) {
|
||||
return e.message
|
||||
}
|
||||
|
||||
@@ -180,6 +170,7 @@ class CopyKotlinDeclarationDialog(
|
||||
override fun getHelpId() = HelpID.COPY_CLASS
|
||||
|
||||
companion object {
|
||||
@NonNls private val RECENTS_KEY = "CopyKotlinDeclarationDialog.RECENTS_KEY"
|
||||
@NonNls
|
||||
private val RECENTS_KEY = "CopyKotlinDeclarationDialog.RECENTS_KEY"
|
||||
}
|
||||
}
|
||||
|
||||
+55
-74
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.copy
|
||||
@@ -66,15 +55,12 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
var Project.newName: String? by UserDataProperty(Key.create("NEW_NAME"))
|
||||
|
||||
private fun PsiElement.getCopyableElement() =
|
||||
parentsWithSelf.firstOrNull { it is KtFile || (it is KtNamedDeclaration && it.parent is KtFile) } as? KtElement
|
||||
parentsWithSelf.firstOrNull { it is KtFile || (it is KtNamedDeclaration && it.parent is KtFile) } as? KtElement
|
||||
|
||||
private fun PsiElement.getDeclarationsToCopy(): List<KtElement> {
|
||||
val declarationOrFile = getCopyableElement()
|
||||
return when (declarationOrFile) {
|
||||
is KtFile -> declarationOrFile.declarations.filterIsInstance<KtNamedDeclaration>().ifEmpty { listOf(declarationOrFile) }
|
||||
is KtNamedDeclaration -> listOf(declarationOrFile)
|
||||
else -> emptyList()
|
||||
}
|
||||
private fun PsiElement.getDeclarationsToCopy(): List<KtElement> = when (val declarationOrFile = getCopyableElement()) {
|
||||
is KtFile -> declarationOrFile.declarations.filterIsInstance<KtNamedDeclaration>().ifEmpty { listOf(declarationOrFile) }
|
||||
is KtNamedDeclaration -> listOf(declarationOrFile)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +68,8 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
|
||||
private fun getSourceFiles(elements: Array<out PsiElement>): Array<PsiElement>? {
|
||||
return elements
|
||||
.map { it.containingFile ?: it as? PsiFileSystemItem ?: return null }
|
||||
.toTypedArray()
|
||||
.map { it.containingFile ?: it as? PsiFileSystemItem ?: return null }
|
||||
.toTypedArray()
|
||||
}
|
||||
|
||||
private fun canCopyFiles(elements: Array<out PsiElement>, fromUpdate: Boolean): Boolean {
|
||||
@@ -94,11 +80,11 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
|
||||
private fun canCopyDeclarations(elements: Array<out PsiElement>): Boolean {
|
||||
val containingFile =
|
||||
elements
|
||||
.flatMap { it.getDeclarationsToCopy().ifEmpty { return false } }
|
||||
.distinctBy { it.containingFile }
|
||||
.singleOrNull()
|
||||
?.containingFile ?: return false
|
||||
elements
|
||||
.flatMap { it.getDeclarationsToCopy().ifEmpty { return false } }
|
||||
.distinctBy { it.containingFile }
|
||||
.singleOrNull()
|
||||
?.containingFile ?: return false
|
||||
return containingFile.sourceRoot != null
|
||||
}
|
||||
|
||||
@@ -111,20 +97,18 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
}
|
||||
|
||||
private fun getOrCreateTargetFile(
|
||||
originalFile: KtFile,
|
||||
targetDirectory: PsiDirectory,
|
||||
targetFileName: String,
|
||||
commandName: String
|
||||
originalFile: KtFile,
|
||||
targetDirectory: PsiDirectory,
|
||||
targetFileName: String,
|
||||
commandName: String
|
||||
): KtFile? {
|
||||
val existingFile = targetDirectory.findFile(targetFileName)
|
||||
if (existingFile == originalFile) return null
|
||||
if (existingFile != null) {
|
||||
val policy = getFilePolicy(existingFile, targetFileName, targetDirectory, commandName)
|
||||
when (policy) {
|
||||
ExistingFilePolicy.APPEND -> {}
|
||||
ExistingFilePolicy.OVERWRITE -> runWriteAction { existingFile.delete() }
|
||||
ExistingFilePolicy.SKIP -> return null
|
||||
if (existingFile != null) when (getFilePolicy(existingFile, targetFileName, targetDirectory, commandName)) {
|
||||
ExistingFilePolicy.APPEND -> {
|
||||
}
|
||||
ExistingFilePolicy.OVERWRITE -> runWriteAction { existingFile.delete() }
|
||||
ExistingFilePolicy.SKIP -> return null
|
||||
}
|
||||
return runWriteAction {
|
||||
if (existingFile != null && existingFile.isValid) {
|
||||
@@ -136,34 +120,33 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
}
|
||||
|
||||
private fun getFilePolicy(
|
||||
existingFile: PsiFile?,
|
||||
targetFileName: String,
|
||||
targetDirectory: PsiDirectory,
|
||||
commandName: String
|
||||
existingFile: PsiFile?,
|
||||
targetFileName: String,
|
||||
targetDirectory: PsiDirectory,
|
||||
commandName: String
|
||||
): ExistingFilePolicy {
|
||||
val isUnitTestMode = ApplicationManager.getApplication().isUnitTestMode
|
||||
return if (existingFile !is KtFile) {
|
||||
if (isUnitTestMode) return ExistingFilePolicy.OVERWRITE
|
||||
|
||||
val answer = Messages.showOkCancelDialog(
|
||||
"File $targetFileName already exists in ${targetDirectory.virtualFile.path}",
|
||||
commandName,
|
||||
"Overwrite",
|
||||
"Cancel",
|
||||
Messages.getQuestionIcon()
|
||||
"File $targetFileName already exists in ${targetDirectory.virtualFile.path}",
|
||||
commandName,
|
||||
"Overwrite",
|
||||
"Cancel",
|
||||
Messages.getQuestionIcon()
|
||||
)
|
||||
if (answer == Messages.OK) ExistingFilePolicy.OVERWRITE else ExistingFilePolicy.SKIP
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (isUnitTestMode) return ExistingFilePolicy.APPEND
|
||||
|
||||
val answer = Messages.showYesNoCancelDialog(
|
||||
"File $targetFileName already exists in ${targetDirectory.virtualFile.path}",
|
||||
commandName,
|
||||
"Append",
|
||||
"Overwrite",
|
||||
"Cancel",
|
||||
Messages.getQuestionIcon()
|
||||
"File $targetFileName already exists in ${targetDirectory.virtualFile.path}",
|
||||
commandName,
|
||||
"Append",
|
||||
"Overwrite",
|
||||
"Cancel",
|
||||
Messages.getQuestionIcon()
|
||||
)
|
||||
when (answer) {
|
||||
Messages.YES -> ExistingFilePolicy.APPEND
|
||||
@@ -187,7 +170,8 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
val originalFile = elementsToCopy.first().containingFile as KtFile
|
||||
val initialTargetDirectory = defaultTargetDirectory ?: originalFile.containingDirectory ?: return
|
||||
|
||||
val isSingleDeclarationInFile = singleElementToCopy is KtNamedDeclaration && originalFile.declarations.singleOrNull() == singleElementToCopy
|
||||
val isSingleDeclarationInFile =
|
||||
singleElementToCopy is KtNamedDeclaration && originalFile.declarations.singleOrNull() == singleElementToCopy
|
||||
|
||||
val project = initialTargetDirectory.project
|
||||
|
||||
@@ -210,8 +194,7 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
newName = dialog.newName ?: singleElementToCopy.name
|
||||
targetDirWrapper = dialog.targetDirectory?.toDirectoryWrapper() ?: return
|
||||
targetSourceRoot = dialog.targetSourceRoot
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val dialog = CopyFilesOrDirectoriesDialog(arrayOf(originalFile), initialTargetDirectory, project, false)
|
||||
if (!dialog.showAndGet()) return
|
||||
openInEditor = dialog.openInEditor()
|
||||
@@ -219,8 +202,7 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
targetDirWrapper = dialog.targetDirectory?.toDirectoryWrapper() ?: return
|
||||
targetSourceRoot = dialog.targetDirectory?.sourceRoot
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
project.newName?.let { newName = it }
|
||||
}
|
||||
|
||||
@@ -229,8 +211,8 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
val internalUsages = runReadAction {
|
||||
val targetPackageName = targetDirWrapper.getPackageName()
|
||||
val changeInfo = ContainerChangeInfo(
|
||||
ContainerInfo.Package(originalFile.packageFqName),
|
||||
ContainerInfo.Package(FqName(targetPackageName))
|
||||
ContainerInfo.Package(originalFile.packageFqName),
|
||||
ContainerInfo.Package(FqName(targetPackageName))
|
||||
)
|
||||
elementsToCopy.flatMapTo(LinkedHashSet()) { elementToCopy ->
|
||||
elementToCopy.getInternalReferencesToUpdateOnPackageNameChange(changeInfo).filter {
|
||||
@@ -247,7 +229,8 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
project.executeCommand(commandName) {
|
||||
try {
|
||||
val targetDirectory = runWriteAction { targetDirWrapper.getOrCreateDirectory(initialTargetDirectory) }
|
||||
val targetFileName = if (newName?.contains(".") ?: false) newName!! else newName + "." + originalFile.virtualFile.extension
|
||||
val targetFileName =
|
||||
if (newName?.contains(".") == true) newName!! else newName + "." + originalFile.virtualFile.extension
|
||||
|
||||
val oldToNewElementsMapping = HashMap<PsiElement, PsiElement>()
|
||||
|
||||
@@ -271,9 +254,9 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
copiedDeclaration = if (isSingleDeclarationInFile && targetFile is KtFile) {
|
||||
targetFile.declarations.singleOrNull() as? KtNamedDeclaration
|
||||
} else null
|
||||
}
|
||||
else {
|
||||
targetFile = getOrCreateTargetFile(originalFile, targetDirectory, targetFileName, commandName) ?: return@executeCommand
|
||||
} else {
|
||||
targetFile =
|
||||
getOrCreateTargetFile(originalFile, targetDirectory, targetFileName, commandName) ?: return@executeCommand
|
||||
runWriteAction {
|
||||
val newElements = elementsToCopy.map { targetFile.add(it.copy()) as KtNamedDeclaration }
|
||||
elementsToCopy.zip(newElements).toMap(oldToNewElementsMapping)
|
||||
@@ -301,11 +284,9 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
if (openInEditor) {
|
||||
EditorHelper.openFilesInEditor(arrayOf(targetFile))
|
||||
}
|
||||
}
|
||||
catch (e: IncorrectOperationException) {
|
||||
} catch (e: IncorrectOperationException) {
|
||||
Messages.showMessageDialog(project, e.message, RefactoringBundle.message("error.title"), Messages.getErrorIcon())
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
cleanUpInternalUsages(internalUsages + restoredInternalUsages)
|
||||
}
|
||||
}
|
||||
@@ -317,10 +298,10 @@ class CopyKotlinDeclarationsHandler : CopyHandlerDelegateBase() {
|
||||
val targetSourceRootPsi = targetSourceRoot?.toPsiDirectory(project)
|
||||
if (targetSourceRootPsi != null && project == originalFile.project) {
|
||||
val conflictChecker = MoveConflictChecker(
|
||||
project,
|
||||
elementsToCopy,
|
||||
KotlinDirectoryMoveTarget(FqName.ROOT, targetSourceRootPsi),
|
||||
originalFile
|
||||
project,
|
||||
elementsToCopy,
|
||||
KotlinDirectoryMoveTarget(FqName.ROOT, targetSourceRootPsi),
|
||||
originalFile
|
||||
)
|
||||
conflictChecker.checkModuleConflictsInDeclarations(internalUsages, conflicts)
|
||||
conflictChecker.checkVisibilityInDeclarations(conflicts)
|
||||
|
||||
Reference in New Issue
Block a user