Move Directory: Support Kotlin files
#KT-8350 Fixed #KT-8351 Fixed
This commit is contained in:
@@ -286,6 +286,9 @@
|
|||||||
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsHandler"
|
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsHandler"
|
||||||
order="before kotlin.moveFilesOrDirectories"/>
|
order="before kotlin.moveFilesOrDirectories"/>
|
||||||
<moveFileHandler implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinFileHandler" />
|
<moveFileHandler implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinFileHandler" />
|
||||||
|
<refactoring.moveDirectoryWithClassesHelper
|
||||||
|
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.KotlinMoveDirectoryWithClassesHelper"
|
||||||
|
order="first" />
|
||||||
<refactoring.moveInnerClassUsagesHandler
|
<refactoring.moveInnerClassUsagesHandler
|
||||||
implementationClass="org.jetbrains.kotlin.idea.refactoring.move.MoveJavaInnerClassKotlinUsagesHandler"
|
implementationClass="org.jetbrains.kotlin.idea.refactoring.move.MoveJavaInnerClassKotlinUsagesHandler"
|
||||||
language="jet" />
|
language="jet" />
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ import com.intellij.codeInsight.unwrap.UnwrapHandler
|
|||||||
import com.intellij.ide.util.PsiElementListCellRenderer
|
import com.intellij.ide.util.PsiElementListCellRenderer
|
||||||
import com.intellij.lang.java.JavaLanguage
|
import com.intellij.lang.java.JavaLanguage
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.command.CommandAdapter
|
||||||
|
import com.intellij.openapi.command.CommandEvent
|
||||||
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.colors.EditorColors
|
import com.intellij.openapi.editor.colors.EditorColors
|
||||||
import com.intellij.openapi.editor.colors.EditorColorsManager
|
import com.intellij.openapi.editor.colors.EditorColorsManager
|
||||||
@@ -111,6 +114,8 @@ public fun File.toPsiDirectory(project: Project): PsiDirectory? {
|
|||||||
|
|
||||||
public fun VirtualFile.toPsiFile(project: Project): PsiFile? = PsiManager.getInstance(project).findFile(this)
|
public fun VirtualFile.toPsiFile(project: Project): PsiFile? = PsiManager.getInstance(project).findFile(this)
|
||||||
|
|
||||||
|
public fun VirtualFile.toPsiDirectory(project: Project): PsiDirectory? = PsiManager.getInstance(project).findDirectory(this)
|
||||||
|
|
||||||
public fun PsiElement.getUsageContext(): PsiElement {
|
public fun PsiElement.getUsageContext(): PsiElement {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is JetElement -> PsiTreeUtil.getParentOfType(this, javaClass<JetNamedDeclaration>(), javaClass<JetFile>())!!
|
is JetElement -> PsiTreeUtil.getParentOfType(this, javaClass<JetNamedDeclaration>(), javaClass<JetFile>())!!
|
||||||
@@ -646,3 +651,14 @@ public fun <T : Any> Project.runSynchronouslyWithProgress(progressTitle: String,
|
|||||||
ProgressManager.getInstance().runProcessWithProgressSynchronously( { result = action() }, progressTitle, canBeCanceled, this)
|
ProgressManager.getInstance().runProcessWithProgressSynchronously( { result = action() }, progressTitle, canBeCanceled, this)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun invokeOnceOnCommandFinish(action: () -> Unit) {
|
||||||
|
val commandProcessor = CommandProcessor.getInstance()
|
||||||
|
val listener = object: CommandAdapter() {
|
||||||
|
override fun beforeCommandFinished(event: CommandEvent?) {
|
||||||
|
action()
|
||||||
|
commandProcessor.removeCommandListener(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commandProcessor.addCommandListener(listener)
|
||||||
|
}
|
||||||
+1
-1
@@ -58,7 +58,7 @@ public class KotlinChangePackageRefactoring(val file: JetFile) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val declarationUsages = declarationProcessor.findUsages().toList()
|
val declarationUsages = declarationProcessor.findUsages().toList()
|
||||||
val internalUsages = file.getInternalReferencesToUpdateOnPackageNameChange(PackageNameInfo(currentFqName, newFqName))
|
val internalUsages = file.getInternalReferencesToUpdateOnPackageNameChange(PackageNameInfo(currentFqName, newFqName.toUnsafe()))
|
||||||
|
|
||||||
project.executeWriteCommand("Change file's package to '${newFqName.asString()}'") {
|
project.executeWriteCommand("Change file's package to '${newFqName.asString()}'") {
|
||||||
packageDirective.setFqName(newFqName)
|
packageDirective.setFqName(newFqName)
|
||||||
|
|||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* 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.moveFilesOrDirectories
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiDirectory
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||||
|
import com.intellij.refactoring.move.moveClassesOrPackages.MoveDirectoryWithClassesHelper
|
||||||
|
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||||
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import com.intellij.util.Function
|
||||||
|
import org.jetbrains.kotlin.idea.core.getPackage
|
||||||
|
import org.jetbrains.kotlin.idea.core.refactoring.invokeOnceOnCommandFinish
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsProcessor
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
|
public class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() {
|
||||||
|
private class FileUsagesWrapper(
|
||||||
|
val psiFile: PsiFile,
|
||||||
|
val usages: List<UsageInfo>,
|
||||||
|
val moveDeclarationsProcessor: MoveKotlinTopLevelDeclarationsProcessor?
|
||||||
|
) : UsageInfo(psiFile)
|
||||||
|
|
||||||
|
private class MoveContext(
|
||||||
|
val newParent: PsiDirectory,
|
||||||
|
val internalUsages: MoveKotlinFileHandler.InternalUsagesWrapper,
|
||||||
|
val moveDeclarationsProcessor: MoveKotlinTopLevelDeclarationsProcessor?
|
||||||
|
)
|
||||||
|
|
||||||
|
private val fileHandler = MoveKotlinFileHandler()
|
||||||
|
|
||||||
|
private var fileToMoveContext: MutableMap<PsiFile, MoveContext>? = null
|
||||||
|
|
||||||
|
private fun getOrCreateMoveContextMap(): MutableMap<PsiFile, MoveContext> {
|
||||||
|
return fileToMoveContext
|
||||||
|
?: HashMap<PsiFile, MoveContext>().apply {
|
||||||
|
fileToMoveContext = this
|
||||||
|
invokeOnceOnCommandFinish { fileToMoveContext = null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findUsages(
|
||||||
|
filesToMove: MutableCollection<PsiFile>,
|
||||||
|
directoriesToMove: Array<out PsiDirectory>,
|
||||||
|
result: MutableCollection<UsageInfo>,
|
||||||
|
searchInComments: Boolean,
|
||||||
|
searchInNonJavaFiles: Boolean,
|
||||||
|
project: Project) {
|
||||||
|
filesToMove
|
||||||
|
.filterIsInstance<JetFile>()
|
||||||
|
.mapTo(result) { FileUsagesWrapper(it, fileHandler.findUsages(it, null, searchInComments, searchInNonJavaFiles), null) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeMove(psiFile: PsiFile) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual move logic is implemented in postProcessUsages since usages are not available here
|
||||||
|
override fun move(
|
||||||
|
file: PsiFile,
|
||||||
|
moveDestination: PsiDirectory,
|
||||||
|
oldToNewElementsMapping: MutableMap<PsiElement, PsiElement>,
|
||||||
|
movedFiles: MutableList<PsiFile>,
|
||||||
|
listener: RefactoringElementListener?
|
||||||
|
): Boolean {
|
||||||
|
if (file !is JetFile) return false
|
||||||
|
|
||||||
|
val moveDeclarationsProcessor = fileHandler.initMoveProcessor(file, moveDestination)
|
||||||
|
val moveContextMap = getOrCreateMoveContextMap()
|
||||||
|
moveContextMap[file] = MoveContext(moveDestination,
|
||||||
|
fileHandler.findInternalUsages(file, moveDestination),
|
||||||
|
moveDeclarationsProcessor)
|
||||||
|
moveDestination.getPackage()?.let { newPackage -> file.packageDirective?.fqName = FqName(newPackage.qualifiedName) }
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterMove(newElement: PsiElement) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun postProcessUsages(usages: Array<out UsageInfo>, newDirMapper: Function<PsiDirectory, PsiDirectory>) {
|
||||||
|
val fileToMoveContext = fileToMoveContext ?: return
|
||||||
|
try {
|
||||||
|
val usagesToProcessAfterMove = ArrayList<FileUsagesWrapper>()
|
||||||
|
usages
|
||||||
|
.filterIsInstance<FileUsagesWrapper>()
|
||||||
|
.forEach body@ {
|
||||||
|
val file = it.psiFile
|
||||||
|
val moveContext = fileToMoveContext[file] ?: return@body
|
||||||
|
|
||||||
|
MoveFilesOrDirectoriesUtil.doMoveFile(file, moveContext.newParent)
|
||||||
|
val movedFile = moveContext.newParent.findFile(file.name) ?: return@body
|
||||||
|
|
||||||
|
usagesToProcessAfterMove +=
|
||||||
|
FileUsagesWrapper(movedFile, it.usages + moveContext.internalUsages, moveContext.moveDeclarationsProcessor)
|
||||||
|
}
|
||||||
|
usagesToProcessAfterMove.forEach { fileHandler.retargetUsages(it.usages, it.moveDeclarationsProcessor!!) }
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.fileToMoveContext = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
-32
@@ -26,22 +26,16 @@ import org.jetbrains.kotlin.idea.JetLanguage
|
|||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.runWithElementsToShortenIsEmptyIgnored
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.runWithElementsToShortenIsEmptyIgnored
|
||||||
import org.jetbrains.kotlin.idea.core.getPackage
|
import org.jetbrains.kotlin.idea.core.getPackage
|
||||||
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.PackageNameInfo
|
import org.jetbrains.kotlin.idea.refactoring.move.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
|
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.DeferredJetFileKotlinMoveTarget
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsOptions
|
|
||||||
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.JetFile
|
||||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class MoveKotlinFileHandler : MoveFileHandler() {
|
public class MoveKotlinFileHandler : MoveFileHandler() {
|
||||||
private class InternalUsagesWrapper(file: JetFile, val usages: List<UsageInfo>) : UsageInfo(file)
|
internal class InternalUsagesWrapper(file: JetFile, val usages: List<UsageInfo>) : UsageInfo(file)
|
||||||
|
|
||||||
// This is special 'PsiElement' whose purpose is to wrap MoveKotlinTopLevelDeclarationsProcessor
|
// This is special 'PsiElement' whose purpose is to wrap MoveKotlinTopLevelDeclarationsProcessor
|
||||||
// so that it can be kept in the transition map
|
// so that it can be kept in the transition map
|
||||||
@@ -52,33 +46,42 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
override fun toString() = ""
|
override fun toString() = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JetFile.getPackageNameInfo(newParent: PsiDirectory, clearUserData: Boolean): PackageNameInfo? {
|
private fun JetFile.getPackageNameInfo(newParent: PsiDirectory?, clearUserData: Boolean): PackageNameInfo? {
|
||||||
val shouldUpdatePackageDirective = updatePackageDirective ?: packageMatchesDirectory()
|
val shouldUpdatePackageDirective = updatePackageDirective ?: packageMatchesDirectory()
|
||||||
updatePackageDirective = if (clearUserData) null else shouldUpdatePackageDirective
|
updatePackageDirective = if (clearUserData) null else shouldUpdatePackageDirective
|
||||||
|
|
||||||
if (!shouldUpdatePackageDirective) return null
|
if (!shouldUpdatePackageDirective) return null
|
||||||
val newPackage = newParent.getPackage() ?: return null
|
|
||||||
|
|
||||||
val oldPackageName = getPackageFqName()
|
val oldPackageName = packageFqName
|
||||||
val newPackageName = FqName(newPackage.getQualifiedName())
|
val newPackage = newParent?.getPackage() ?: return PackageNameInfo(oldPackageName, UNKNOWN_PACKAGE_FQ_NAME)
|
||||||
if (oldPackageName == newPackageName) return null
|
|
||||||
|
val newPackageName = FqNameUnsafe(newPackage.qualifiedName)
|
||||||
|
if (oldPackageName.asString() == newPackageName.asString()) return null
|
||||||
|
|
||||||
return PackageNameInfo(oldPackageName, newPackageName)
|
return PackageNameInfo(oldPackageName, newPackageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initMoveProcessor(psiFile: PsiFile, newParent: PsiDirectory): MoveKotlinTopLevelDeclarationsProcessor? {
|
fun initMoveProcessor(psiFile: PsiFile, newParent: PsiDirectory?): MoveKotlinTopLevelDeclarationsProcessor? {
|
||||||
if (psiFile !is JetFile) return null
|
if (psiFile !is JetFile) return null
|
||||||
val packageNameInfo = psiFile.getPackageNameInfo(newParent, false) ?: return null
|
val packageNameInfo = psiFile.getPackageNameInfo(newParent, false) ?: return null
|
||||||
|
|
||||||
val project = psiFile.getProject()
|
val project = psiFile.project
|
||||||
|
|
||||||
|
val newPackageName = packageNameInfo.newPackageName
|
||||||
|
val moveTarget = when (newPackageName) {
|
||||||
|
UNKNOWN_PACKAGE_FQ_NAME -> EmptyKotlinMoveTarget
|
||||||
|
|
||||||
|
else -> DeferredJetFileKotlinMoveTarget(project, newPackageName.toSafe()) {
|
||||||
|
MoveFilesOrDirectoriesUtil.doMoveFile(psiFile, newParent)
|
||||||
|
newParent?.findFile(psiFile.name) as? JetFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val declarationMoveProcessor = MoveKotlinTopLevelDeclarationsProcessor(
|
val declarationMoveProcessor = MoveKotlinTopLevelDeclarationsProcessor(
|
||||||
project,
|
project,
|
||||||
MoveKotlinTopLevelDeclarationsOptions(
|
MoveKotlinTopLevelDeclarationsOptions(
|
||||||
elementsToMove = psiFile.getDeclarations().filterIsInstance<JetNamedDeclaration>(),
|
elementsToMove = psiFile.declarations.filterIsInstance<JetNamedDeclaration>(),
|
||||||
moveTarget = DeferredJetFileKotlinMoveTarget(project, packageNameInfo.newPackageName) {
|
moveTarget = moveTarget,
|
||||||
MoveFilesOrDirectoriesUtil.doMoveFile(psiFile, newParent)
|
|
||||||
newParent.findFile(psiFile.getName()) as? JetFile
|
|
||||||
},
|
|
||||||
updateInternalReferences = false
|
updateInternalReferences = false
|
||||||
),
|
),
|
||||||
Mover.Idle
|
Mover.Idle
|
||||||
@@ -91,9 +94,15 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
return !JavaProjectRootsUtil.isOutsideJavaSourceRoot(element)
|
return !JavaProjectRootsUtil.isOutsideJavaSourceRoot(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun findInternalUsages(file: JetFile, newParent: PsiDirectory): InternalUsagesWrapper {
|
||||||
|
val packageNameInfo = file.getPackageNameInfo(newParent, false)
|
||||||
|
val usages = packageNameInfo?.let { file.getInternalReferencesToUpdateOnPackageNameChange(it) } ?: emptyList()
|
||||||
|
return InternalUsagesWrapper(file, usages)
|
||||||
|
}
|
||||||
|
|
||||||
override fun findUsages(
|
override fun findUsages(
|
||||||
psiFile: PsiFile,
|
psiFile: PsiFile,
|
||||||
newParent: PsiDirectory,
|
newParent: PsiDirectory?,
|
||||||
searchInComments: Boolean,
|
searchInComments: Boolean,
|
||||||
searchInNonJavaFiles: Boolean
|
searchInNonJavaFiles: Boolean
|
||||||
): List<UsageInfo> {
|
): List<UsageInfo> {
|
||||||
@@ -101,10 +110,7 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
|
|
||||||
val usages = ArrayList<UsageInfo>()
|
val usages = ArrayList<UsageInfo>()
|
||||||
initMoveProcessor(psiFile, newParent)?.findUsages()?.let { usages += it }
|
initMoveProcessor(psiFile, newParent)?.findUsages()?.let { usages += it }
|
||||||
val packageNameInfo = psiFile.getPackageNameInfo(newParent, false)
|
newParent?.let { usages += findInternalUsages(psiFile, it) }
|
||||||
if (packageNameInfo != null) {
|
|
||||||
usages += InternalUsagesWrapper(psiFile, psiFile.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo))
|
|
||||||
}
|
|
||||||
return usages
|
return usages
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,15 +124,20 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
if (file !is JetFile) return
|
if (file !is JetFile) return
|
||||||
val newDirectory = file.parent ?: return
|
val newDirectory = file.parent ?: return
|
||||||
val packageNameInfo = file.getPackageNameInfo(newDirectory, true) ?: return
|
val packageNameInfo = file.getPackageNameInfo(newDirectory, true) ?: return
|
||||||
file.packageDirective?.fqName = packageNameInfo.newPackageName
|
val newPackageName = packageNameInfo.newPackageName
|
||||||
|
assert(newPackageName.isSafe, newPackageName)
|
||||||
|
file.packageDirective?.fqName = newPackageName.toSafe()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun retargetUsages(usageInfos: List<UsageInfo>?, oldToNewMap: Map<PsiElement, PsiElement>) {
|
override fun retargetUsages(usageInfos: List<UsageInfo>?, oldToNewMap: Map<PsiElement, PsiElement>) {
|
||||||
postProcessMoveUsages(usageInfos?.firstIsInstanceOrNull<InternalUsagesWrapper>()?.usages ?: emptyList())
|
|
||||||
val moveContext = oldToNewMap.keySet().firstIsInstanceOrNull<MoveContext>() ?: return
|
val moveContext = oldToNewMap.keySet().firstIsInstanceOrNull<MoveContext>() ?: return
|
||||||
val processor = moveContext.declarationMoveProcessor
|
retargetUsages(usageInfos, moveContext.declarationMoveProcessor)
|
||||||
processor.project.runWithElementsToShortenIsEmptyIgnored {
|
}
|
||||||
usageInfos?.let { processor.execute(it) }
|
|
||||||
|
fun retargetUsages(usageInfos: List<UsageInfo>?, moveDeclarationsProcessor: MoveKotlinTopLevelDeclarationsProcessor) {
|
||||||
|
postProcessMoveUsages(usageInfos?.firstIsInstanceOrNull<InternalUsagesWrapper>()?.usages ?: emptyList())
|
||||||
|
moveDeclarationsProcessor.project.runWithElementsToShortenIsEmptyIgnored {
|
||||||
|
usageInfos?.let { moveDeclarationsProcessor.execute(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -23,7 +23,7 @@ import com.intellij.psi.PsiManager
|
|||||||
import com.intellij.refactoring.PackageWrapper
|
import com.intellij.refactoring.PackageWrapper
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import java.util.*
|
import java.util.HashMap
|
||||||
|
|
||||||
public interface KotlinMoveTarget {
|
public interface KotlinMoveTarget {
|
||||||
val packageWrapper: PackageWrapper?
|
val packageWrapper: PackageWrapper?
|
||||||
@@ -34,6 +34,13 @@ public interface KotlinMoveTarget {
|
|||||||
fun verify(file: PsiFile): String?
|
fun verify(file: PsiFile): String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object EmptyKotlinMoveTarget: KotlinMoveTarget {
|
||||||
|
override val packageWrapper: PackageWrapper? get() = null
|
||||||
|
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = null
|
||||||
|
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
||||||
|
override fun verify(file: PsiFile) = null
|
||||||
|
}
|
||||||
|
|
||||||
public class JetFileKotlinMoveTarget(val targetFile: JetFile): KotlinMoveTarget {
|
public class JetFileKotlinMoveTarget(val targetFile: JetFile): KotlinMoveTarget {
|
||||||
override val packageWrapper: PackageWrapper? = targetFile.getPackageFqName().asString().let { packageName ->
|
override val packageWrapper: PackageWrapper? = targetFile.getPackageFqName().asString().let { packageName ->
|
||||||
PackageWrapper(PsiManager.getInstance(targetFile.getProject()), packageName)
|
PackageWrapper(PsiManager.getInstance(targetFile.getProject()), packageName)
|
||||||
|
|||||||
+3
-1
@@ -184,6 +184,8 @@ public class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun collectConflictsInDeclarations() {
|
fun collectConflictsInDeclarations() {
|
||||||
|
if (newPackageName == UNKNOWN_PACKAGE_FQ_NAME.asString()) return
|
||||||
|
|
||||||
val declarationToReferenceTargets = HashMap<JetNamedDeclaration, MutableSet<PsiElement>>()
|
val declarationToReferenceTargets = HashMap<JetNamedDeclaration, MutableSet<PsiElement>>()
|
||||||
for (declaration in elementsToMove) {
|
for (declaration in elementsToMove) {
|
||||||
val referenceToContext = JetFileReferencesResolver.resolve(element = declaration, resolveQualifiers = false)
|
val referenceToContext = JetFileReferencesResolver.resolve(element = declaration, resolveQualifiers = false)
|
||||||
@@ -251,7 +253,7 @@ public class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
?: throw AssertionError("Couldn't create Kotlin file for: ${declaration.javaClass}: ${declaration.getText()}")
|
?: throw AssertionError("Couldn't create Kotlin file for: ${declaration.javaClass}: ${declaration.getText()}")
|
||||||
|
|
||||||
if (options.updateInternalReferences) {
|
if (options.updateInternalReferences) {
|
||||||
val packageNameInfo = PackageNameInfo(file!!.getPackageFqName(), targetFile.getPackageFqName())
|
val packageNameInfo = PackageNameInfo(file!!.getPackageFqName(), targetFile.getPackageFqName().toUnsafe())
|
||||||
val (usagesToProcessLater, usagesToProcessNow) = declaration
|
val (usagesToProcessLater, usagesToProcessNow) = declaration
|
||||||
.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
||||||
.partition { it is MoveRenameUsageInfoForExtension }
|
.partition { it is MoveRenameUsageInfoForExtension }
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
|||||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -65,7 +66,9 @@ import java.util.ArrayList
|
|||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.Comparator
|
import java.util.Comparator
|
||||||
|
|
||||||
public class PackageNameInfo(val oldPackageName: FqName, val newPackageName: FqName)
|
val UNKNOWN_PACKAGE_FQ_NAME = FqNameUnsafe("org.jetbrains.kotlin.idea.refactoring.move.<unknown-package>")
|
||||||
|
|
||||||
|
public class PackageNameInfo(val oldPackageName: FqName, val newPackageName: FqNameUnsafe)
|
||||||
|
|
||||||
public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo: PackageNameInfo): List<UsageInfo> {
|
public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo: PackageNameInfo): List<UsageInfo> {
|
||||||
val file = getContainingFile() as? JetFile ?: return listOf()
|
val file = getContainingFile() as? JetFile ?: return listOf()
|
||||||
@@ -113,7 +116,7 @@ public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNa
|
|||||||
return when {
|
return when {
|
||||||
isExtension,
|
isExtension,
|
||||||
packageName == packageNameInfo.oldPackageName,
|
packageName == packageNameInfo.oldPackageName,
|
||||||
packageName == packageNameInfo.newPackageName,
|
packageName?.asString() == packageNameInfo.newPackageName.asString(),
|
||||||
isImported(descriptor) -> {
|
isImported(descriptor) -> {
|
||||||
createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false)
|
createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p1
|
||||||
|
|
||||||
|
import p2.p.J
|
||||||
|
import p2.p.K
|
||||||
|
|
||||||
|
public class M {
|
||||||
|
val j = J()
|
||||||
|
val k = K()
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p2;
|
||||||
|
|
||||||
|
import p2.p.K;
|
||||||
|
import p1.M;
|
||||||
|
|
||||||
|
public class JJ {
|
||||||
|
K k = new K();
|
||||||
|
M m = new M();
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p2
|
||||||
|
|
||||||
|
import p1.M
|
||||||
|
import p2.p.K
|
||||||
|
|
||||||
|
public class L {
|
||||||
|
private val k = K()
|
||||||
|
private val m = M()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package p2.p;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
K k = new K();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package p2.p
|
||||||
|
|
||||||
|
public class K {
|
||||||
|
val j = J()
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p1
|
||||||
|
|
||||||
|
import p1.p.J
|
||||||
|
import p1.p.K
|
||||||
|
|
||||||
|
public class M {
|
||||||
|
val j = J()
|
||||||
|
val k = K()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package p1.p;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
K k = new K();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package p1.p
|
||||||
|
|
||||||
|
public class K {
|
||||||
|
val j = J()
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p2;
|
||||||
|
|
||||||
|
import p1.p.K;
|
||||||
|
import p1.M;
|
||||||
|
|
||||||
|
public class JJ {
|
||||||
|
K k = new K();
|
||||||
|
M m = new M();
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p2
|
||||||
|
|
||||||
|
import p1.M
|
||||||
|
import p1.p.K
|
||||||
|
|
||||||
|
public class L {
|
||||||
|
private val k = K()
|
||||||
|
private val m = M()
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "p1/M.kt",
|
||||||
|
"type": "MOVE_DIRECTORY_WITH_CLASSES",
|
||||||
|
"sourceDir": "p1/p",
|
||||||
|
"targetDir": "p2"
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ import com.intellij.refactoring.PackageWrapper
|
|||||||
import com.intellij.refactoring.move.MoveHandler
|
import com.intellij.refactoring.move.MoveHandler
|
||||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassToInnerProcessor
|
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassToInnerProcessor
|
||||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesProcessor
|
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesProcessor
|
||||||
|
import com.intellij.refactoring.move.moveClassesOrPackages.MoveDirectoryWithClassesProcessor
|
||||||
import com.intellij.refactoring.move.moveClassesOrPackages.MultipleRootsMoveDestination
|
import com.intellij.refactoring.move.moveClassesOrPackages.MultipleRootsMoveDestination
|
||||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor
|
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor
|
||||||
import com.intellij.refactoring.move.moveInner.MoveInnerProcessor
|
import com.intellij.refactoring.move.moveInner.MoveInnerProcessor
|
||||||
@@ -37,6 +38,7 @@ import com.intellij.refactoring.move.moveMembers.MockMoveMembersOptions
|
|||||||
import com.intellij.refactoring.move.moveMembers.MoveMembersProcessor
|
import com.intellij.refactoring.move.moveMembers.MoveMembersProcessor
|
||||||
import com.intellij.util.ActionRunner
|
import com.intellij.util.ActionRunner
|
||||||
import org.jetbrains.kotlin.idea.core.refactoring.createKotlinFile
|
import org.jetbrains.kotlin.idea.core.refactoring.createKotlinFile
|
||||||
|
import org.jetbrains.kotlin.idea.core.refactoring.toPsiDirectory
|
||||||
import org.jetbrains.kotlin.idea.jsonUtils.getNullableString
|
import org.jetbrains.kotlin.idea.jsonUtils.getNullableString
|
||||||
import org.jetbrains.kotlin.idea.jsonUtils.getString
|
import org.jetbrains.kotlin.idea.jsonUtils.getString
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.changePackage.KotlinChangePackageRefactoring
|
import org.jetbrains.kotlin.idea.refactoring.move.changePackage.KotlinChangePackageRefactoring
|
||||||
@@ -264,6 +266,15 @@ enum class MoveAction {
|
|||||||
override fun runRefactoring(rootDir: VirtualFile, mainFile: PsiFile, elementAtCaret: PsiElement?, config: JsonObject) {
|
override fun runRefactoring(rootDir: VirtualFile, mainFile: PsiFile, elementAtCaret: PsiElement?, config: JsonObject) {
|
||||||
KotlinChangePackageRefactoring(mainFile as JetFile).run(FqName(config.getString("newPackageName")))
|
KotlinChangePackageRefactoring(mainFile as JetFile).run(FqName(config.getString("newPackageName")))
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
MOVE_DIRECTORY_WITH_CLASSES {
|
||||||
|
override fun runRefactoring(rootDir: VirtualFile, mainFile: PsiFile, elementAtCaret: PsiElement?, config: JsonObject) {
|
||||||
|
val project = mainFile.project
|
||||||
|
val sourceDir = rootDir.findFileByRelativePath(config.getString("sourceDir"))!!.toPsiDirectory(project)!!
|
||||||
|
val targetDir = rootDir.findFileByRelativePath(config.getString("targetDir"))!!.toPsiDirectory(project)!!
|
||||||
|
MoveDirectoryWithClassesProcessor(project, arrayOf(sourceDir), targetDir, true, true, true, {}).run()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract fun runRefactoring(rootDir: VirtualFile, mainFile: PsiFile, elementAtCaret: PsiElement?, config: JsonObject)
|
abstract fun runRefactoring(rootDir: VirtualFile, mainFile: PsiFile, elementAtCaret: PsiElement?, config: JsonObject)
|
||||||
|
|||||||
@@ -227,6 +227,12 @@ public class JetMoveTestGenerated extends AbstractJetMoveTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kotlin/moveDirectory/moveDirectory.test")
|
||||||
|
public void testKotlin_moveDirectory_MoveDirectory() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveDirectory/moveDirectory.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kotlin/moveFile/addExtensionImport/addExtensionImport.test")
|
@TestMetadata("kotlin/moveFile/addExtensionImport/addExtensionImport.test")
|
||||||
public void testKotlin_moveFile_addExtensionImport_AddExtensionImport() throws Exception {
|
public void testKotlin_moveFile_addExtensionImport_AddExtensionImport() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveFile/addExtensionImport/addExtensionImport.test");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveFile/addExtensionImport/addExtensionImport.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user