KT-35463 EA-214439 Pass adjusted files to KotlinAwareMoveFilesOrDirectoriesDialog instead of originals

- Passing raw `sourceElements` have lead to `ClassCastException` when `KtClassOrObject` was casted to `PsiFileSystemItem` in `KotlinAwareMoveFilesOrDirectoriesDialog::initializeData`
- Migrate from `[PsiElement]` to more precise `[PsiFileSystemItem]`
  - This removes the cast to `PsiFileSystemItem` at all
- This bug can be reproduced only in Android Studio for some reason
- ^KT-35463 Fixed
- ^EA-214439 Fixed
This commit is contained in:
Roman Golyshev
2019-12-13 18:46:22 +03:00
committed by Roman Golyshev
parent dd8396efbc
commit bd805d71b1
6 changed files with 23 additions and 18 deletions
@@ -71,9 +71,7 @@ internal class MoveKotlinDeclarationsHandlerTestActions(private val caseDataKeep
private fun KotlinAwareMoveFilesOrDirectoriesModel.testDataString(): String { private fun KotlinAwareMoveFilesOrDirectoriesModel.testDataString(): String {
return "KotlinAwareMoveFilesOrDirectoriesModel:\n" + return "KotlinAwareMoveFilesOrDirectoriesModel:\n" +
"elementsToMove = ${elementsToMove.joinToString { "elementsToMove = ${elementsToMove.joinToString { it.virtualFile.path }}\n" +
if (it is PsiFileSystemItem) it.virtualFile.path else it.javaClass.name
}}\n" +
"directoryName = $targetDirectoryName\n" + "directoryName = $targetDirectoryName\n" +
"updatePackageDirective = $updatePackageDirective\n" + "updatePackageDirective = $updatePackageDirective\n" +
"searchReferences = $searchReferences" "searchReferences = $searchReferences"
@@ -216,7 +214,7 @@ internal class MoveKotlinDeclarationsHandlerTestActions(private val caseDataKeep
override fun invokeKotlinAwareMoveFilesOrDirectoriesRefactoring( override fun invokeKotlinAwareMoveFilesOrDirectoriesRefactoring(
project: Project, project: Project,
initialDirectory: PsiDirectory?, initialDirectory: PsiDirectory?,
elements: Array<out PsiElement>, elements: List<PsiFileSystemItem>,
moveCallback: MoveCallback? moveCallback: MoveCallback?
) { ) {
val targetPath = val targetPath =
@@ -226,7 +224,7 @@ internal class MoveKotlinDeclarationsHandlerTestActions(private val caseDataKeep
val model = KotlinAwareMoveFilesOrDirectoriesModel( val model = KotlinAwareMoveFilesOrDirectoriesModel(
project = project, project = project,
elementsToMove = elements.toList(), elementsToMove = elements,
targetDirectoryName = randomDirectoryPathMutator(targetPath), targetDirectoryName = randomDirectoryPathMutator(targetPath),
updatePackageDirective = randomBoolean(), updatePackageDirective = randomBoolean(),
searchReferences = randomBoolean(), searchReferences = randomBoolean(),
@@ -86,7 +86,7 @@ private val defaultHandlerActions = object : MoveKotlinDeclarationsHandlerAction
override fun invokeKotlinAwareMoveFilesOrDirectoriesRefactoring( override fun invokeKotlinAwareMoveFilesOrDirectoriesRefactoring(
project: Project, project: Project,
initialDirectory: PsiDirectory?, initialDirectory: PsiDirectory?,
elements: Array<out PsiElement>, elements: List<PsiFileSystemItem>,
moveCallback: MoveCallback? moveCallback: MoveCallback?
) = KotlinAwareMoveFilesOrDirectoriesDialog(project, initialDirectory, elements, moveCallback).show() ) = KotlinAwareMoveFilesOrDirectoriesDialog(project, initialDirectory, elements, moveCallback).show()
} }
@@ -159,6 +159,7 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
} }
if (elements.all { it is KtFile }) { if (elements.all { it is KtFile }) {
val ktFileElements = elements.map { it as KtFile }
val initialTargetElement = when { val initialTargetElement = when {
targetContainer is PsiPackage || targetContainer is PsiDirectory -> targetContainer targetContainer is PsiPackage || targetContainer is PsiDirectory -> targetContainer
container is PsiPackage || container is PsiDirectory -> container container is PsiPackage || container is PsiDirectory -> container
@@ -167,7 +168,7 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
val initialTargetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, initialTargetElement) val initialTargetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, initialTargetElement)
handlerActions.invokeKotlinAwareMoveFilesOrDirectoriesRefactoring( handlerActions.invokeKotlinAwareMoveFilesOrDirectoriesRefactoring(
project, initialTargetDirectory, elements, callback project, initialTargetDirectory, ktFileElements, callback
) )
return true return true
@@ -9,6 +9,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFileSystemItem
import com.intellij.refactoring.move.MoveCallback import com.intellij.refactoring.move.MoveCallback
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -39,7 +40,7 @@ internal interface MoveKotlinDeclarationsHandlerActions {
fun invokeKotlinSelectNestedClassChooser(nestedClass: KtClassOrObject, targetContainer: PsiElement?) fun invokeKotlinSelectNestedClassChooser(nestedClass: KtClassOrObject, targetContainer: PsiElement?)
fun invokeKotlinAwareMoveFilesOrDirectoriesRefactoring( fun invokeKotlinAwareMoveFilesOrDirectoriesRefactoring(
project: Project, initialDirectory: PsiDirectory?, elements: Array<out PsiElement>, moveCallback: MoveCallback? project: Project, initialDirectory: PsiDirectory?, elements: List<PsiFileSystemItem>, moveCallback: MoveCallback?
) )
fun showErrorHint(project: Project, editor: Editor?, message: String, title: String, helpId: String?) fun showErrorHint(project: Project, editor: Editor?, message: String, title: String, helpId: String?)
@@ -41,7 +41,7 @@ import javax.swing.JComponent
class KotlinAwareMoveFilesOrDirectoriesDialog( class KotlinAwareMoveFilesOrDirectoriesDialog(
private val project: Project, private val project: Project,
private val initialDirectory: PsiDirectory?, private val initialDirectory: PsiDirectory?,
private val psiElements: Array<out PsiElement>, private val psiElements: List<PsiFileSystemItem>,
private val callback: MoveCallback? private val callback: MoveCallback?
) : DialogWrapper(project, true) { ) : DialogWrapper(project, true) {
@@ -115,7 +115,7 @@ class KotlinAwareMoveFilesOrDirectoriesDialog(
private fun initializeData() { private fun initializeData() {
val psiElement = psiElements.singleOrNull() val psiElement = psiElements.singleOrNull()
if (psiElement != null) { if (psiElement != null) {
val shortenedPath = CopyFilesOrDirectoriesDialog.shortenPath((psiElement as PsiFileSystemItem).virtualFile) val shortenedPath = CopyFilesOrDirectoriesDialog.shortenPath(psiElement.virtualFile)
nameLabel.text = when (psiElement) { nameLabel.text = when (psiElement) {
is PsiFile -> RefactoringBundle.message("move.file.0", shortenedPath) is PsiFile -> RefactoringBundle.message("move.file.0", shortenedPath)
else -> RefactoringBundle.message("move.directory.0", shortenedPath) else -> RefactoringBundle.message("move.directory.0", shortenedPath)
@@ -166,7 +166,7 @@ class KotlinAwareMoveFilesOrDirectoriesDialog(
PsiManager.getInstance(project).findDirectory(it) PsiManager.getInstance(project).findDirectory(it)
} }
val elementsToMove: List<PsiElement> = directory?.let { existentDirectory -> val elementsToMove = directory?.let { existentDirectory ->
val choice = if (psiElements.size > 1 || psiElements[0] is PsiDirectory) intArrayOf(-1) else null val choice = if (psiElements.size > 1 || psiElements[0] is PsiDirectory) intArrayOf(-1) else null
psiElements.filterNot { psiElements.filterNot {
it is PsiFile && CopyFilesOrDirectoriesHandler.checkFileExist(existentDirectory, choice, it, it.name, "Move") it is PsiFile && CopyFilesOrDirectoriesHandler.checkFileExist(existentDirectory, choice, it, it.name, "Move")
@@ -11,6 +11,7 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileSystemItem
import com.intellij.refactoring.move.MoveCallback import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
@@ -21,12 +22,11 @@ import org.jetbrains.kotlin.idea.refactoring.move.updatePackageDirective
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import java.nio.file.InvalidPathException import java.nio.file.InvalidPathException
import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
class KotlinAwareMoveFilesOrDirectoriesModel( class KotlinAwareMoveFilesOrDirectoriesModel(
val project: Project, val project: Project,
val elementsToMove: List<PsiElement>, val elementsToMove: List<PsiFileSystemItem>,
val targetDirectoryName: String, val targetDirectoryName: String,
val updatePackageDirective: Boolean, val updatePackageDirective: Boolean,
val searchReferences: Boolean, val searchReferences: Boolean,
@@ -23,12 +23,13 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() { class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() {
private fun adjustElements(elements: Array<out PsiElement>): Array<PsiElement>? { private fun adjustElements(elements: Array<out PsiElement>): Array<PsiFileSystemItem>? {
return elements.map { return elements.map {
when { when {
it is PsiFile || it is PsiDirectory -> it it is PsiFile -> it
it is PsiDirectory -> it
it is PsiClass && it.containingClass == null -> it.containingFile it is PsiClass && it.containingClass == null -> it.containingFile
it is KtClassOrObject && it.parent is KtFile -> it.parent it is KtClassOrObject && it.parent is KtFile -> it.parent as KtFile
else -> return null else -> return null
} }
}.toTypedArray() }.toTypedArray()
@@ -41,7 +42,11 @@ class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() {
return super.canMove(adjustedElements, targetContainer) return super.canMove(adjustedElements, targetContainer)
} }
override fun adjustForMove(project: Project, sourceElements: Array<out PsiElement>, targetElement: PsiElement?): Array<PsiElement>? { override fun adjustForMove(
project: Project,
sourceElements: Array<out PsiElement>,
targetElement: PsiElement?
): Array<PsiFileSystemItem>? {
return adjustElements(sourceElements) return adjustElements(sourceElements)
} }
@@ -71,7 +76,7 @@ class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() {
return return
} }
KotlinAwareMoveFilesOrDirectoriesDialog(project, initialTargetDirectory, elements, callback).show() KotlinAwareMoveFilesOrDirectoriesDialog(project, initialTargetDirectory, adjustedElementsToMove, callback).show()
} }
override fun tryToMove( override fun tryToMove(