Move: Implement "Update package directive" option
This commit is contained in:
@@ -251,7 +251,8 @@
|
||||
<refactoring.helper implementation="org.jetbrains.kotlin.idea.codeInsight.KotlinShortenReferencesRefactoringHelper"/>
|
||||
<refactoring.moveHandler
|
||||
id="kotlin.moveFilesOrDirectories"
|
||||
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.KotlinMoveFilesOrDirectoriesHandler"/>
|
||||
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.KotlinMoveFilesOrDirectoriesHandler"
|
||||
order="before moveJavaFileOrDir"/>
|
||||
<refactoring.moveHandler
|
||||
id="kotlin.moveTopLevelDeclarations"
|
||||
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsHandler"
|
||||
|
||||
+12
-1
@@ -18,9 +18,12 @@ package org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiDirectoryContainer
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.refactoring.move.MoveCallback
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesHandler
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
|
||||
@@ -36,10 +39,18 @@ public class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler
|
||||
return super.canMove(adjustedElements.toTypedArray(), targetContainer)
|
||||
}
|
||||
|
||||
override fun adjustForMove(project: Project, sourceElements: Array<PsiElement>, targetElement: PsiElement?): Array<PsiElement> {
|
||||
override fun adjustForMove(project: Project, sourceElements: Array<out PsiElement>, targetElement: PsiElement?): Array<PsiElement> {
|
||||
return sourceElements.map { if (it is JetClassOrObject) it.getContainingFile() else it }.toTypedArray()
|
||||
}
|
||||
|
||||
override fun doMove(project: Project, elements: Array<out PsiElement>, targetContainer: PsiElement?, callback: MoveCallback?) {
|
||||
if (!(targetContainer == null || targetContainer is PsiDirectory || targetContainer is PsiDirectoryContainer)) return
|
||||
|
||||
moveFilesOrDirectories(project, adjustForMove(project, elements, targetContainer), targetContainer) {
|
||||
callback?.refactoringCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
public fun isMovableClass(clazz: JetClassOrObject): Boolean {
|
||||
return clazz.isTopLevel() && clazz.getContainingJetFile().getDeclarations().all { it !is JetClassOrObject || it == clazz }
|
||||
|
||||
+5
-1
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveK
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsProcessor
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.Mover
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.updatePackageDirective
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||
@@ -60,11 +61,12 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
|
||||
): List<UsageInfo>? {
|
||||
clearState()
|
||||
|
||||
if (psiFile !is JetFile || !psiFile.packageMatchesDirectory()) return null
|
||||
if (psiFile !is JetFile || !(psiFile.updatePackageDirective ?: psiFile.packageMatchesDirectory())) return null
|
||||
|
||||
val newPackage = newParent.getPackage() ?: return null
|
||||
|
||||
val packageNameInfo = PackageNameInfo(psiFile.getPackageFqName(), FqName(newPackage.getQualifiedName()))
|
||||
if (packageNameInfo.oldPackageName == packageNameInfo.newPackageName) return null
|
||||
val project = psiFile.getProject()
|
||||
|
||||
val declarationMoveProcessor = MoveKotlinTopLevelDeclarationsProcessor(
|
||||
@@ -93,6 +95,8 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
|
||||
|
||||
override fun updateMovedFile(file: PsiFile) {
|
||||
if (file !is JetFile) return
|
||||
|
||||
file.updatePackageDirective = null
|
||||
val packageNameInfo = packageNameInfo ?: return
|
||||
|
||||
val internalUsages = file.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
||||
|
||||
+2
-5
@@ -32,6 +32,7 @@ import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackages
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.isInJavaSourceRoot
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getPackage
|
||||
@@ -51,11 +52,7 @@ public class MoveKotlinTopLevelDeclarationsHandler : MoveHandlerDelegate() {
|
||||
val sourceFile = sourceFiles.singleOrNull()
|
||||
if (sourceFile == null) {
|
||||
if (sourceFiles.all { it.getDeclarations().size() == 1 }) {
|
||||
MoveFilesOrDirectoriesUtil.doMove(project,
|
||||
sourceFiles.toTypedArray(),
|
||||
arrayOf(targetContainer),
|
||||
null)
|
||||
|
||||
moveFilesOrDirectories(project, sourceFiles.toTypedArray(), targetContainer)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.moveTopLevelDeclarations.ui
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesDialog
|
||||
import com.intellij.ui.NonFocusableCheckBox
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.packageMatchesDirectory
|
||||
import java.awt.GridBagConstraints
|
||||
import java.awt.Insets
|
||||
import javax.swing.JCheckBox
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JLabel
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
public class MoveFilesOrDirectoriesDialogWithKotlinOptions(
|
||||
project: Project,
|
||||
callback: (MoveFilesOrDirectoriesDialog?) -> Unit): MoveFilesOrDirectoriesDialog(project, callback) {
|
||||
private var cbUpdatePackageDirective: JCheckBox? = null
|
||||
|
||||
public val updatePackageDirective: Boolean
|
||||
get() = cbUpdatePackageDirective!!.isSelected()
|
||||
|
||||
override fun createNorthPanel(): JComponent {
|
||||
val panel = super.createNorthPanel()
|
||||
|
||||
val gbc = GridBagConstraints()
|
||||
|
||||
gbc.gridwidth = 1
|
||||
gbc.gridx = 0
|
||||
gbc.gridy = GridBagConstraints.RELATIVE
|
||||
gbc.weightx = 0.0
|
||||
gbc.weighty = 0.0
|
||||
gbc.fill = GridBagConstraints.NONE
|
||||
gbc.anchor = GridBagConstraints.WEST
|
||||
gbc.insets = Insets(UIUtil.LARGE_VGAP, 0, 0, UIUtil.DEFAULT_HGAP)
|
||||
panel.add(JLabel(), gbc)
|
||||
|
||||
cbUpdatePackageDirective = NonFocusableCheckBox()
|
||||
gbc.gridx = 1
|
||||
gbc.weightx = 1.0
|
||||
gbc.weighty = 0.0
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL
|
||||
gbc.anchor = GridBagConstraints.WEST
|
||||
gbc.insets = Insets(UIUtil.LARGE_VGAP, 0, 0, 0)
|
||||
panel.add(cbUpdatePackageDirective, gbc)
|
||||
|
||||
return panel
|
||||
}
|
||||
|
||||
override fun setData(psiElements: Array<out PsiElement>, initialTargetDirectory: PsiDirectory?, helpID: String) {
|
||||
super.setData(psiElements, initialTargetDirectory, helpID)
|
||||
|
||||
with (cbUpdatePackageDirective!!) {
|
||||
val jetFiles = psiElements.filterIsInstance<JetFile>()
|
||||
if (jetFiles.isEmpty()) {
|
||||
getParent().remove(cbUpdatePackageDirective)
|
||||
return
|
||||
}
|
||||
|
||||
val singleFile = jetFiles.singleOrNull()
|
||||
if (singleFile != null) {
|
||||
setSelected(singleFile.packageMatchesDirectory())
|
||||
setText("Update package directive")
|
||||
}
|
||||
else {
|
||||
setSelected(true)
|
||||
setText("Update package directive for Kotlin files")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,15 +16,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.util.Comparing
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.RefactoringSettings
|
||||
import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler
|
||||
import com.intellij.refactoring.move.MoveCallback
|
||||
import com.intellij.refactoring.move.MoveHandler
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesDialog
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import com.intellij.refactoring.move.moveMembers.MockMoveMembersOptions
|
||||
import com.intellij.refactoring.move.moveMembers.MoveMemberHandler
|
||||
import com.intellij.refactoring.move.moveMembers.MoveMembersProcessor
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
import com.intellij.refactoring.util.NonCodeUsageInfo
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.Function
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
@@ -35,10 +51,13 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.MoveFilesOrDirectoriesDialogWithKotlinOptions
|
||||
import org.jetbrains.kotlin.idea.references.JetReference
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
@@ -261,3 +280,73 @@ fun postProcessMoveUsages(usages: List<UsageInfo>,
|
||||
|
||||
return nonCodeUsages
|
||||
}
|
||||
|
||||
var JetFile.updatePackageDirective: Boolean? by UserDataProperty(Key.create("UPDATE_PACKAGE_DIRECTIVE"))
|
||||
|
||||
// Mostly copied from MoveFilesOrDirectoriesUtil.doMove()
|
||||
public fun moveFilesOrDirectories(
|
||||
project: Project,
|
||||
elements: Array<PsiElement>,
|
||||
targetElement: PsiElement?,
|
||||
moveCallback: (() -> Unit)? = null
|
||||
) {
|
||||
elements.forEach { if (it !is PsiFile && it !is PsiDirectory) throw IllegalArgumentException("unexpected element type: " + it) }
|
||||
|
||||
val targetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, targetElement)
|
||||
if (targetElement != null && targetDirectory == null) return
|
||||
|
||||
val initialTargetDirectory = MoveFilesOrDirectoriesUtil.getInitialTargetDirectory(targetDirectory, elements)
|
||||
|
||||
fun doRun(moveDialog: MoveFilesOrDirectoriesDialog?) {
|
||||
fun closeDialog() {
|
||||
moveDialog?.close(DialogWrapper.CANCEL_EXIT_CODE)
|
||||
}
|
||||
|
||||
project.executeCommand(MoveHandler.REFACTORING_NAME) {
|
||||
val selectedDir = if (moveDialog != null) moveDialog.getTargetDirectory() else initialTargetDirectory
|
||||
val updatePackageDirective = (moveDialog as? MoveFilesOrDirectoriesDialogWithKotlinOptions)?.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.getName(), "Move") }
|
||||
}
|
||||
|
||||
elementsToMove.forEach {
|
||||
MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir)
|
||||
(it as? JetFile)?.let { it.updatePackageDirective = updatePackageDirective }
|
||||
}
|
||||
|
||||
if (elementsToMove.isNotEmpty()) {
|
||||
MoveFilesOrDirectoriesProcessor(
|
||||
project,
|
||||
elementsToMove.toTypedArray(),
|
||||
selectedDir,
|
||||
RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE,
|
||||
false,
|
||||
false,
|
||||
moveCallback,
|
||||
::closeDialog
|
||||
).run()
|
||||
}
|
||||
else {
|
||||
closeDialog()
|
||||
}
|
||||
}
|
||||
catch (e: IncorrectOperationException) {
|
||||
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.getMessage(), "refactoring.moveFile", project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
doRun(null)
|
||||
return
|
||||
}
|
||||
|
||||
with(MoveFilesOrDirectoriesDialogWithKotlinOptions(project, ::doRun)) {
|
||||
setData(elements, initialTargetDirectory, "refactoring.moveFile")
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user