Move: Correctly determine target module for deferred files
This commit is contained in:
+10
@@ -16,11 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
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 org.jetbrains.kotlin.idea.core.getOrCreateCompanionObject
|
import org.jetbrains.kotlin.idea.core.getOrCreateCompanionObject
|
||||||
|
import org.jetbrains.kotlin.idea.util.projectStructure.getModule
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
@@ -38,10 +40,16 @@ interface KotlinMoveTarget {
|
|||||||
|
|
||||||
// Check possible errors and return corresponding message, or null if no errors are detected
|
// Check possible errors and return corresponding message, or null if no errors are detected
|
||||||
fun verify(file: PsiFile): String?
|
fun verify(file: PsiFile): String?
|
||||||
|
|
||||||
|
val targetScope: VirtualFile?
|
||||||
|
get() = targetFile
|
||||||
}
|
}
|
||||||
|
|
||||||
interface KotlinDirectoryBasedMoveTarget : KotlinMoveTarget {
|
interface KotlinDirectoryBasedMoveTarget : KotlinMoveTarget {
|
||||||
val directory: PsiDirectory?
|
val directory: PsiDirectory?
|
||||||
|
|
||||||
|
override val targetScope: VirtualFile?
|
||||||
|
get() = super.targetScope ?: directory?.virtualFile
|
||||||
}
|
}
|
||||||
|
|
||||||
object EmptyKotlinMoveTarget: KotlinMoveTarget {
|
object EmptyKotlinMoveTarget: KotlinMoveTarget {
|
||||||
@@ -111,3 +119,5 @@ class KotlinDirectoryMoveTarget(
|
|||||||
|
|
||||||
override fun verify(file: PsiFile) = null
|
override fun verify(file: PsiFile) = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KotlinMoveTarget.getTargetModule(project: Project) = targetScope?.getModule(project)
|
||||||
+1
-2
@@ -49,7 +49,6 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.move.*
|
import org.jetbrains.kotlin.idea.refactoring.move.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
||||||
import org.jetbrains.kotlin.idea.search.projectScope
|
import org.jetbrains.kotlin.idea.search.projectScope
|
||||||
import org.jetbrains.kotlin.idea.util.projectStructure.getModule
|
|
||||||
import org.jetbrains.kotlin.idea.util.projectStructure.module
|
import org.jetbrains.kotlin.idea.util.projectStructure.module
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -158,7 +157,7 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return false
|
val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return false
|
||||||
if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return false
|
if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return false
|
||||||
val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, descriptor.moveTarget)
|
val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, descriptor.moveTarget)
|
||||||
val targetModule = descriptor.moveTarget.targetFile?.getModule(project) ?: return false
|
val targetModule = descriptor.moveTarget.getTargetModule(project) ?: return false
|
||||||
return oldContainer == newContainer && ktDeclaration.module == targetModule
|
return oldContainer == newContainer && ktDeclaration.module == targetModule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-17
@@ -118,13 +118,8 @@ class MoveConflictChecker(
|
|||||||
|
|
||||||
is KotlinDirectoryBasedMoveTarget -> {
|
is KotlinDirectoryBasedMoveTarget -> {
|
||||||
val packageFqName = targetContainerFqName ?: return null
|
val packageFqName = targetContainerFqName ?: return null
|
||||||
val targetDir = directory?.virtualFile ?: targetFile
|
val targetModuleDescriptor = targetScope?.let { getModuleDescriptor(it) ?: return null }
|
||||||
val targetModuleDescriptor = if (targetDir != null) {
|
?: resolutionFacade.moduleDescriptor
|
||||||
getModuleDescriptor(targetDir) ?: return null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resolutionFacade.moduleDescriptor
|
|
||||||
}
|
|
||||||
MutablePackageFragmentDescriptor(targetModuleDescriptor, packageFqName).withSource(fakeFile)
|
MutablePackageFragmentDescriptor(targetModuleDescriptor, packageFqName).withSource(fakeFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,11 +166,11 @@ class MoveConflictChecker(
|
|||||||
// Based on RefactoringConflictsUtil.analyzeModuleConflicts
|
// Based on RefactoringConflictsUtil.analyzeModuleConflicts
|
||||||
fun analyzeModuleConflictsInUsages(project: Project,
|
fun analyzeModuleConflictsInUsages(project: Project,
|
||||||
usages: Collection<UsageInfo>,
|
usages: Collection<UsageInfo>,
|
||||||
targetFile: VirtualFile,
|
targetScope: VirtualFile,
|
||||||
conflicts: MultiMap<PsiElement, String>) {
|
conflicts: MultiMap<PsiElement, String>) {
|
||||||
val targetModule = targetFile.getModule(project) ?: return
|
val targetModule = targetScope.getModule(project) ?: return
|
||||||
|
|
||||||
val isInTestSources = ModuleRootManager.getInstance(targetModule).fileIndex.isInTestSourceContent(targetFile)
|
val isInTestSources = ModuleRootManager.getInstance(targetModule).fileIndex.isInTestSourceContent(targetScope)
|
||||||
NextUsage@ for (usage in usages) {
|
NextUsage@ for (usage in usages) {
|
||||||
val element = usage.element ?: continue
|
val element = usage.element ?: continue
|
||||||
if (PsiTreeUtil.getParentOfType(element, PsiImportStatement::class.java, false) != null) continue
|
if (PsiTreeUtil.getParentOfType(element, PsiImportStatement::class.java, false) != null) continue
|
||||||
@@ -205,9 +200,9 @@ class MoveConflictChecker(
|
|||||||
|
|
||||||
fun checkModuleConflictsInUsages(externalUsages: MutableSet<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
fun checkModuleConflictsInUsages(externalUsages: MutableSet<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
||||||
val newConflicts = MultiMap<PsiElement, String>()
|
val newConflicts = MultiMap<PsiElement, String>()
|
||||||
val targetFile = moveTarget.targetFile ?: return
|
val targetScope = moveTarget.targetScope ?: return
|
||||||
|
|
||||||
analyzeModuleConflictsInUsages(project, externalUsages, targetFile, newConflicts)
|
analyzeModuleConflictsInUsages(project, externalUsages, targetScope, newConflicts)
|
||||||
if (!newConflicts.isEmpty) {
|
if (!newConflicts.isEmpty) {
|
||||||
val referencedElementsToSkip = newConflicts.keySet().mapNotNullTo(HashSet()) { it.namedUnwrappedElement }
|
val referencedElementsToSkip = newConflicts.keySet().mapNotNullTo(HashSet()) { it.namedUnwrappedElement }
|
||||||
externalUsages.removeIf {
|
externalUsages.removeIf {
|
||||||
@@ -247,8 +242,8 @@ class MoveConflictChecker(
|
|||||||
internalUsages: MutableSet<UsageInfo>,
|
internalUsages: MutableSet<UsageInfo>,
|
||||||
conflicts: MultiMap<PsiElement, String>
|
conflicts: MultiMap<PsiElement, String>
|
||||||
) {
|
) {
|
||||||
val targetFile = moveTarget.targetFile ?: return
|
val targetScope = moveTarget.targetScope ?: return
|
||||||
val targetModule = targetFile.getModule(project) ?: return
|
val targetModule = targetScope.getModule(project) ?: return
|
||||||
val resolveScope = targetModule.getScopeWithPlatformAwareDependencies()
|
val resolveScope = targetModule.getScopeWithPlatformAwareDependencies()
|
||||||
|
|
||||||
fun isInScope(targetElement: PsiElement, targetDescriptor: DeclarationDescriptor): Boolean {
|
fun isInScope(targetElement: PsiElement, targetDescriptor: DeclarationDescriptor): Boolean {
|
||||||
@@ -260,7 +255,7 @@ class MoveConflictChecker(
|
|||||||
val renderedImportableTarget = DESCRIPTOR_RENDERER_FOR_COMPARISON.render(importableDescriptor)
|
val renderedImportableTarget = DESCRIPTOR_RENDERER_FOR_COMPARISON.render(importableDescriptor)
|
||||||
val renderedTarget by lazy { DESCRIPTOR_RENDERER_FOR_COMPARISON.render(targetDescriptor) }
|
val renderedTarget by lazy { DESCRIPTOR_RENDERER_FOR_COMPARISON.render(targetDescriptor) }
|
||||||
|
|
||||||
val targetModuleInfo = getModuleInfoByVirtualFile(project, targetFile)
|
val targetModuleInfo = getModuleInfoByVirtualFile(project, targetScope)
|
||||||
val dummyFile = KtPsiFactory(targetElement.project).createFile("dummy.kt", "").apply {
|
val dummyFile = KtPsiFactory(targetElement.project).createFile("dummy.kt", "").apply {
|
||||||
moduleInfo = targetModuleInfo
|
moduleInfo = targetModuleInfo
|
||||||
targetPlatform = TargetPlatformDetector.getPlatform(targetModule)
|
targetPlatform = TargetPlatformDetector.getPlatform(targetModule)
|
||||||
@@ -432,8 +427,7 @@ class MoveConflictChecker(
|
|||||||
private fun isToBeMoved(element: PsiElement): Boolean = allElementsToMove.any { it.isAncestor(element, false) }
|
private fun isToBeMoved(element: PsiElement): Boolean = allElementsToMove.any { it.isAncestor(element, false) }
|
||||||
|
|
||||||
private fun checkInternalMemberUsages(conflicts: MultiMap<PsiElement, String>) {
|
private fun checkInternalMemberUsages(conflicts: MultiMap<PsiElement, String>) {
|
||||||
val sourceRoot = moveTarget.targetFile ?: return
|
val targetModule = moveTarget.getTargetModule(project) ?: return
|
||||||
val targetModule = ModuleUtilCore.findModuleForFile(sourceRoot, project) ?: return
|
|
||||||
|
|
||||||
val membersToCheck = LinkedHashSet<KtDeclaration>()
|
val membersToCheck = LinkedHashSet<KtDeclaration>()
|
||||||
val memberCollector = object : KtVisitorVoid() {
|
val memberCollector = object : KtVisitorVoid() {
|
||||||
|
|||||||
Reference in New Issue
Block a user