Move: Fix processing of conflicting usages
Exclude conflict-associated usages from refactoring. Move search of file internal usages to MoveKotlinDeclarationsProcessor
This commit is contained in:
+4
-2
@@ -67,6 +67,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.LinkedHashMap
|
||||||
|
import kotlin.collections.LinkedHashSet
|
||||||
|
|
||||||
data class ExtractSuperInfo(
|
data class ExtractSuperInfo(
|
||||||
val originalClass: KtClassOrObject,
|
val originalClass: KtClassOrObject,
|
||||||
@@ -155,7 +157,7 @@ class ExtractSuperRefactoring(
|
|||||||
|
|
||||||
project.runSynchronouslyWithProgress(RefactoringBundle.message("detecting.possible.conflicts"), true) {
|
project.runSynchronouslyWithProgress(RefactoringBundle.message("detecting.possible.conflicts"), true) {
|
||||||
runReadAction {
|
runReadAction {
|
||||||
val usages = ArrayList<UsageInfo>()
|
val usages = LinkedHashSet<UsageInfo>()
|
||||||
for (element in elementsToMove) {
|
for (element in elementsToMove) {
|
||||||
ReferencesSearch.search(element).mapTo(usages) { MoveRenameUsageInfo(it, element) }
|
ReferencesSearch.search(element).mapTo(usages) { MoveRenameUsageInfo(it, element) }
|
||||||
if (element is KtCallableDeclaration) {
|
if (element is KtCallableDeclaration) {
|
||||||
@@ -164,7 +166,7 @@ class ExtractSuperRefactoring(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conflictChecker.checkAllConflicts(usages, conflicts)
|
conflictChecker.checkAllConflicts(usages, LinkedHashSet<UsageInfo>(), conflicts)
|
||||||
if (targetParent is PsiDirectory) {
|
if (targetParent is PsiDirectory) {
|
||||||
ExtractSuperClassUtil.checkSuperAccessible(targetParent, conflicts, originalClass.toLightClass())
|
ExtractSuperClassUtil.checkSuperAccessible(targetParent, conflicts, originalClass.toLightClass())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ class KotlinChangePackageRefactoring(val file: KtFile) {
|
|||||||
override fun verify(file: PsiFile) = null
|
override fun verify(file: PsiFile) = null
|
||||||
},
|
},
|
||||||
delegate = MoveDeclarationsDelegate.TopLevel,
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
updateInternalReferences = false
|
scanEntireFile = false
|
||||||
),
|
),
|
||||||
Mover.Idle // we don't need to move any declarations physically
|
Mover.Idle // we don't need to move any declarations physically
|
||||||
)
|
)
|
||||||
|
|||||||
-1
@@ -99,7 +99,6 @@ class MoveDeclarationToSeparateFileIntention :
|
|||||||
delegate = MoveDeclarationsDelegate.TopLevel,
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
searchInCommentsAndStrings = false,
|
searchInCommentsAndStrings = false,
|
||||||
searchInNonCode = false,
|
searchInNonCode = false,
|
||||||
updateInternalReferences = true,
|
|
||||||
moveCallback = MoveCallback {
|
moveCallback = MoveCallback {
|
||||||
val newFile = directory.findFile(targetFileName) as KtFile
|
val newFile = directory.findFile(targetFileName) as KtFile
|
||||||
val newDeclaration = newFile.declarations.first()
|
val newDeclaration = newFile.declarations.first()
|
||||||
|
|||||||
+7
-7
@@ -34,10 +34,10 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
|||||||
|
|
||||||
sealed class MoveDeclarationsDelegate {
|
sealed class MoveDeclarationsDelegate {
|
||||||
abstract fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo
|
abstract fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo
|
||||||
abstract fun findUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo>
|
abstract fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo>
|
||||||
abstract fun collectConflicts(
|
abstract fun collectConflicts(
|
||||||
descriptor: MoveDeclarationsDescriptor,
|
descriptor: MoveDeclarationsDescriptor,
|
||||||
usages: MutableList<UsageInfo>,
|
internalUsages: MutableSet<UsageInfo>,
|
||||||
conflicts: MultiMap<PsiElement, String>
|
conflicts: MultiMap<PsiElement, String>
|
||||||
)
|
)
|
||||||
abstract fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration)
|
abstract fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration)
|
||||||
@@ -49,11 +49,11 @@ sealed class MoveDeclarationsDelegate {
|
|||||||
ContainerInfo.Package(moveTarget.targetContainerFqName!!))
|
ContainerInfo.Package(moveTarget.targetContainerFqName!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> = emptyList()
|
override fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> = emptyList()
|
||||||
|
|
||||||
override fun collectConflicts(
|
override fun collectConflicts(
|
||||||
descriptor: MoveDeclarationsDescriptor,
|
descriptor: MoveDeclarationsDescriptor,
|
||||||
usages: MutableList<UsageInfo>,
|
internalUsages: MutableSet<UsageInfo>,
|
||||||
conflicts: MultiMap<PsiElement, String>
|
conflicts: MultiMap<PsiElement, String>
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -83,17 +83,17 @@ sealed class MoveDeclarationsDelegate {
|
|||||||
return ContainerChangeInfo(originalInfo, newInfo)
|
return ContainerChangeInfo(originalInfo, newInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> {
|
override fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> {
|
||||||
val classToMove = descriptor.elementsToMove.singleOrNull() as? KtClass ?: return emptyList()
|
val classToMove = descriptor.elementsToMove.singleOrNull() as? KtClass ?: return emptyList()
|
||||||
return collectOuterInstanceReferences(classToMove)
|
return collectOuterInstanceReferences(classToMove)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun collectConflicts(
|
override fun collectConflicts(
|
||||||
descriptor: MoveDeclarationsDescriptor,
|
descriptor: MoveDeclarationsDescriptor,
|
||||||
usages: MutableList<UsageInfo>,
|
internalUsages: MutableSet<UsageInfo>,
|
||||||
conflicts: MultiMap<PsiElement, String>
|
conflicts: MultiMap<PsiElement, String>
|
||||||
) {
|
) {
|
||||||
val usageIterator = usages.iterator()
|
val usageIterator = internalUsages.iterator()
|
||||||
while (usageIterator.hasNext()) {
|
while (usageIterator.hasNext()) {
|
||||||
val usage = usageIterator.next()
|
val usage = usageIterator.next()
|
||||||
val element = usage.element ?: continue
|
val element = usage.element ?: continue
|
||||||
|
|||||||
+41
-28
@@ -37,21 +37,16 @@ import com.intellij.usageView.UsageViewBundle
|
|||||||
import com.intellij.usageView.UsageViewDescriptor
|
import com.intellij.usageView.UsageViewDescriptor
|
||||||
import com.intellij.usageView.UsageViewUtil
|
import com.intellij.usageView.UsageViewUtil
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
import com.intellij.util.SmartList
|
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import gnu.trove.THashMap
|
import gnu.trove.THashMap
|
||||||
import gnu.trove.TObjectHashingStrategy
|
import gnu.trove.TObjectHashingStrategy
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||||
import org.jetbrains.kotlin.asJava.toLightElements
|
import org.jetbrains.kotlin.asJava.toLightElements
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||||
import org.jetbrains.kotlin.idea.core.deleteSingle
|
import org.jetbrains.kotlin.idea.core.deleteSingle
|
||||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.UnqualifiableMoveRenameUsageInfo
|
import org.jetbrains.kotlin.idea.refactoring.move.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.createMoveUsageInfoIfPossible
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
|
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
||||||
import org.jetbrains.kotlin.idea.search.projectScope
|
import org.jetbrains.kotlin.idea.search.projectScope
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -92,7 +87,7 @@ class MoveDeclarationsDescriptor(
|
|||||||
val delegate: MoveDeclarationsDelegate,
|
val delegate: MoveDeclarationsDelegate,
|
||||||
val searchInCommentsAndStrings: Boolean = true,
|
val searchInCommentsAndStrings: Boolean = true,
|
||||||
val searchInNonCode: Boolean = true,
|
val searchInNonCode: Boolean = true,
|
||||||
val updateInternalReferences: Boolean = true,
|
val scanEntireFile: Boolean = false,
|
||||||
val deleteSourceFiles: Boolean = false,
|
val deleteSourceFiles: Boolean = false,
|
||||||
val moveCallback: MoveCallback? = null,
|
val moveCallback: MoveCallback? = null,
|
||||||
val openInEditor: Boolean = false
|
val openInEditor: Boolean = false
|
||||||
@@ -125,16 +120,19 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
return MoveMultipleElementsViewDescriptor(elementsToMove.toTypedArray(), targetContainerFqName)
|
return MoveMultipleElementsViewDescriptor(elementsToMove.toTypedArray(), targetContainerFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val usagesToProcessBeforeMove = SmartList<UsageInfo>()
|
|
||||||
|
|
||||||
fun getConflictsAsUsages(): List<UsageInfo> = conflicts.entrySet().map { ConflictUsageInfo(it.key, it.value) }
|
fun getConflictsAsUsages(): List<UsageInfo> = conflicts.entrySet().map { ConflictUsageInfo(it.key, it.value) }
|
||||||
|
|
||||||
|
class UsagesToProcessBeforeMoveWrapper(
|
||||||
|
sourceFile: KtFile,
|
||||||
|
val usages: Collection<UsageInfo>
|
||||||
|
): UsageInfo(sourceFile)
|
||||||
|
|
||||||
public override fun findUsages(): Array<UsageInfo> {
|
public override fun findUsages(): Array<UsageInfo> {
|
||||||
if (elementsToMove.isEmpty()) return UsageInfo.EMPTY_ARRAY
|
if (elementsToMove.isEmpty()) return UsageInfo.EMPTY_ARRAY
|
||||||
|
|
||||||
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
|
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
|
||||||
|
|
||||||
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableList<UsageInfo>) {
|
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
|
||||||
kotlinToLightElements.values.flatMap { it }.flatMapTo(result) { lightElement ->
|
kotlinToLightElements.values.flatMap { it }.flatMapTo(result) { lightElement ->
|
||||||
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
|
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
|
||||||
|
|
||||||
@@ -169,24 +167,38 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val usagesToProcessBeforeMove = LinkedHashSet<UsageInfo>()
|
||||||
val usages = ArrayList<UsageInfo>()
|
val usages = ArrayList<UsageInfo>()
|
||||||
val conflictChecker = MoveConflictChecker(project, elementsToMove, descriptor.moveTarget, elementsToMove.first())
|
val conflictChecker = MoveConflictChecker(project, elementsToMove, descriptor.moveTarget, elementsToMove.first())
|
||||||
for (kotlinToLightElements in kotlinToLightElementsBySourceFile.values) {
|
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
|
||||||
kotlinToLightElements.keys.forEach {
|
val internalUsages = LinkedHashSet<UsageInfo>()
|
||||||
if (descriptor.updateInternalReferences) {
|
val externalUsages = LinkedHashSet<UsageInfo>()
|
||||||
|
|
||||||
|
if (descriptor.scanEntireFile) {
|
||||||
|
val changeInfo = ContainerChangeInfo(
|
||||||
|
ContainerInfo.Package(sourceFile.packageFqName),
|
||||||
|
descriptor.moveTarget.targetContainerFqName?.let { ContainerInfo.Package(it) } ?: ContainerInfo.UnknownPackage
|
||||||
|
)
|
||||||
|
internalUsages += sourceFile.getInternalReferencesToUpdateOnPackageNameChange(changeInfo)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
kotlinToLightElements.keys.forEach {
|
||||||
val packageNameInfo = descriptor.delegate.getContainerChangeInfo(it, descriptor.moveTarget)
|
val packageNameInfo = descriptor.delegate.getContainerChangeInfo(it, descriptor.moveTarget)
|
||||||
val (usagesToProcessLater, usagesToProcessEarly) = it
|
internalUsages += it.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
||||||
.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
|
||||||
.partition { it is UnqualifiableMoveRenameUsageInfo }
|
|
||||||
usages.addAll(usagesToProcessLater)
|
|
||||||
usagesToProcessBeforeMove.addAll(usagesToProcessEarly)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usages += descriptor.delegate.findUsages(descriptor)
|
internalUsages += descriptor.delegate.findInternalUsages(descriptor)
|
||||||
collectUsages(kotlinToLightElements, usages)
|
collectUsages(kotlinToLightElements, externalUsages)
|
||||||
conflictChecker.checkAllConflicts(usages, conflicts)
|
conflictChecker.checkAllConflicts(externalUsages, internalUsages, conflicts)
|
||||||
descriptor.delegate.collectConflicts(descriptor, usages, conflicts)
|
descriptor.delegate.collectConflicts(descriptor, internalUsages, conflicts)
|
||||||
|
|
||||||
|
usages += externalUsages
|
||||||
|
|
||||||
|
val (usagesToProcessLater, usagesToProcessEarly) = internalUsages.partition { it is UnqualifiableMoveRenameUsageInfo }
|
||||||
|
usages += usagesToProcessLater
|
||||||
|
usagesToProcessBeforeMove += usagesToProcessEarly
|
||||||
|
usages += UsagesToProcessBeforeMoveWrapper(sourceFile, usagesToProcessBeforeMove)
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.delegate.collectConflicts(descriptor, usagesToProcessBeforeMove, conflicts)
|
descriptor.delegate.collectConflicts(descriptor, usagesToProcessBeforeMove, conflicts)
|
||||||
@@ -217,7 +229,12 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
try {
|
try {
|
||||||
val usageList = usages.toList()
|
val usageList = usages.toList()
|
||||||
|
|
||||||
descriptor.delegate.preprocessUsages(project, usageList)
|
val (usagesToProcessBeforeMoveWrappers, usagesToProcessAfterMove) =
|
||||||
|
usageList.partition { it is UsagesToProcessBeforeMoveWrapper }
|
||||||
|
val usagesToProcessBeforeMove = usagesToProcessBeforeMoveWrappers.flatMap { (it as UsagesToProcessBeforeMoveWrapper).usages }
|
||||||
|
|
||||||
|
descriptor.delegate.preprocessUsages(project, usagesToProcessBeforeMove)
|
||||||
|
descriptor.delegate.preprocessUsages(project, usagesToProcessAfterMove)
|
||||||
|
|
||||||
postProcessMoveUsages(usagesToProcessBeforeMove, shorteningMode = ShorteningMode.NO_SHORTENING)
|
postProcessMoveUsages(usagesToProcessBeforeMove, shorteningMode = ShorteningMode.NO_SHORTENING)
|
||||||
|
|
||||||
@@ -268,7 +285,7 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nonCodeUsages = postProcessMoveUsages(usageList, oldToNewElementsMapping).toTypedArray()
|
nonCodeUsages = postProcessMoveUsages(usagesToProcessAfterMove, oldToNewElementsMapping).toTypedArray()
|
||||||
}
|
}
|
||||||
catch (e: IncorrectOperationException) {
|
catch (e: IncorrectOperationException) {
|
||||||
nonCodeUsages = null
|
nonCodeUsages = null
|
||||||
@@ -286,8 +303,4 @@ class MoveKotlinDeclarationsProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getCommandName(): String = REFACTORING_NAME
|
override fun getCommandName(): String = REFACTORING_NAME
|
||||||
}
|
|
||||||
|
|
||||||
interface D : DeclarationDescriptorWithSource {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+28
-9
@@ -140,15 +140,28 @@ class MoveConflictChecker(
|
|||||||
|
|
||||||
private fun render(declaration: PsiElement) = RefactoringUIUtil.getDescription(declaration, false)
|
private fun render(declaration: PsiElement) = RefactoringUIUtil.getDescription(declaration, false)
|
||||||
|
|
||||||
fun checkModuleConflictsInUsages(usages: List<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
fun checkModuleConflictsInUsages(externalUsages: MutableSet<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
||||||
|
val newConflicts = MultiMap<PsiElement, String>()
|
||||||
val sourceRoot = moveTarget.targetFile ?: return
|
val sourceRoot = moveTarget.targetFile ?: return
|
||||||
RefactoringConflictsUtil.analyzeModuleConflicts(project, elementsToMove, usages.toTypedArray(), sourceRoot, conflicts)
|
RefactoringConflictsUtil.analyzeModuleConflicts(project, elementsToMove, externalUsages.toTypedArray(), sourceRoot, newConflicts)
|
||||||
|
if (!newConflicts.isEmpty) {
|
||||||
|
val referencedElementsToSkip = newConflicts.keySet().mapNotNullTo(HashSet()) { it.namedUnwrappedElement }
|
||||||
|
externalUsages.removeIf {
|
||||||
|
it is MoveRenameUsageInfo &&
|
||||||
|
it.referencedElement?.namedUnwrappedElement?.let { it in referencedElementsToSkip } ?: false
|
||||||
|
}
|
||||||
|
conflicts.putAllValues(newConflicts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkModuleConflictsInDeclarations(conflicts: MultiMap<PsiElement, String>) {
|
private fun checkModuleConflictsInDeclarations(
|
||||||
|
internalUsages: MutableSet<UsageInfo>,
|
||||||
|
conflicts: MultiMap<PsiElement, String>
|
||||||
|
) {
|
||||||
val sourceRoot = moveTarget.targetFile ?: return
|
val sourceRoot = moveTarget.targetFile ?: return
|
||||||
val targetModule = ModuleUtilCore.findModuleForFile(sourceRoot, project) ?: return
|
val targetModule = ModuleUtilCore.findModuleForFile(sourceRoot, project) ?: return
|
||||||
val resolveScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(targetModule)
|
val resolveScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(targetModule)
|
||||||
|
val referencesToSkip = HashSet<KtReferenceExpression>()
|
||||||
for (declaration in elementsToMove - doNotGoIn) {
|
for (declaration in elementsToMove - doNotGoIn) {
|
||||||
declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr ->
|
declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr ->
|
||||||
val targetDescriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] ?: return@forEachDescendantOfType
|
val targetDescriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] ?: return@forEachDescendantOfType
|
||||||
@@ -172,11 +185,13 @@ class MoveConflictChecker(
|
|||||||
scopeDescription,
|
scopeDescription,
|
||||||
CommonRefactoringUtil.htmlEmphasize(targetModule.name))
|
CommonRefactoringUtil.htmlEmphasize(targetModule.name))
|
||||||
conflicts.putValue(target, CommonRefactoringUtil.capitalize(message))
|
conflicts.putValue(target, CommonRefactoringUtil.capitalize(message))
|
||||||
|
referencesToSkip += refExpr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internalUsages.removeIf { it.reference?.element?.let { it in referencesToSkip } ?: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkVisibilityInUsages(usages: List<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
fun checkVisibilityInUsages(usages: Collection<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
||||||
val declarationToContainers = HashMap<KtNamedDeclaration, MutableSet<PsiElement>>()
|
val declarationToContainers = HashMap<KtNamedDeclaration, MutableSet<PsiElement>>()
|
||||||
for (usage in usages) {
|
for (usage in usages) {
|
||||||
val element = usage.element
|
val element = usage.element
|
||||||
@@ -205,7 +220,7 @@ class MoveConflictChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkVisibilityInDeclarations(conflicts: MultiMap<PsiElement, String>) {
|
private fun checkVisibilityInDeclarations(conflicts: MultiMap<PsiElement, String>) {
|
||||||
val targetContainer = moveTarget.getContainerDescriptor() ?: return
|
val targetContainer = moveTarget.getContainerDescriptor() ?: return
|
||||||
for (declaration in elementsToMove - doNotGoIn) {
|
for (declaration in elementsToMove - doNotGoIn) {
|
||||||
declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr ->
|
declaration.forEachDescendantOfType<KtReferenceExpression> { refExpr ->
|
||||||
@@ -227,10 +242,14 @@ class MoveConflictChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkAllConflicts(usages: List<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
fun checkAllConflicts(
|
||||||
checkModuleConflictsInUsages(usages, conflicts)
|
externalUsages: MutableSet<UsageInfo>,
|
||||||
checkModuleConflictsInDeclarations(conflicts)
|
internalUsages: MutableSet<UsageInfo>,
|
||||||
checkVisibilityInUsages(usages, conflicts)
|
conflicts: MultiMap<PsiElement, String>
|
||||||
|
) {
|
||||||
|
checkModuleConflictsInUsages(externalUsages, conflicts)
|
||||||
|
checkModuleConflictsInDeclarations(internalUsages, conflicts)
|
||||||
|
checkVisibilityInUsages(externalUsages, conflicts)
|
||||||
checkVisibilityInDeclarations(conflicts)
|
checkVisibilityInDeclarations(conflicts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -91,7 +91,7 @@ class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
elementsToMove = psiFile.declarations.filterIsInstance<KtNamedDeclaration>(),
|
elementsToMove = psiFile.declarations.filterIsInstance<KtNamedDeclaration>(),
|
||||||
moveTarget = moveTarget,
|
moveTarget = moveTarget,
|
||||||
delegate = MoveDeclarationsDelegate.TopLevel,
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
updateInternalReferences = false
|
scanEntireFile = true
|
||||||
),
|
),
|
||||||
Mover.Idle
|
Mover.Idle
|
||||||
)
|
)
|
||||||
@@ -122,7 +122,6 @@ class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
usages += it.findUsages()
|
usages += it.findUsages()
|
||||||
usages += it.getConflictsAsUsages()
|
usages += it.getConflictsAsUsages()
|
||||||
}
|
}
|
||||||
newParent?.let { usages += findInternalUsages(psiFile, it) }
|
|
||||||
return usages
|
return usages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ private fun updateJavaReference(reference: PsiReferenceExpression, oldElement: P
|
|||||||
/**
|
/**
|
||||||
* Perform usage postprocessing and return non-code usages
|
* Perform usage postprocessing and return non-code usages
|
||||||
*/
|
*/
|
||||||
fun postProcessMoveUsages(usages: List<UsageInfo>,
|
fun postProcessMoveUsages(usages: Collection<UsageInfo>,
|
||||||
oldToNewElementsMapping: Map<PsiElement, PsiElement> = Collections.emptyMap(),
|
oldToNewElementsMapping: Map<PsiElement, PsiElement> = Collections.emptyMap(),
|
||||||
shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING
|
shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING
|
||||||
): List<NonCodeUsageInfo> {
|
): List<NonCodeUsageInfo> {
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
package a2
|
package a2
|
||||||
|
|
||||||
import b.internalTargetVal
|
import a1.internalTargetVal
|
||||||
|
|
||||||
internal val sourceVal = b.internalTargetVal
|
internal val sourceVal = internalTargetVal
|
||||||
+1
-2
@@ -1,3 +1,2 @@
|
|||||||
Property a1.internalTargetVal, referenced in file internalSource.kt, will not be accessible from module A
|
Property a1.internalTargetVal, referenced in file internalSource.kt, will not be accessible from module A
|
||||||
Property a1.internalTargetVal, referenced in file internalSource.kt, will not be accessible from module A
|
Property a1.internalTargetVal, referenced in file internalSource.kt, will not be accessible from module A
|
||||||
Property sourceVal uses property internalTargetVal which will be inaccessible after move
|
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package a
|
package a
|
||||||
|
|
||||||
val val2 = target.val1
|
val val2 = val1
|
||||||
-1
@@ -1,2 +1 @@
|
|||||||
Property a.val1, referenced in file test.kt, will not be accessible from module A
|
Property a.val1, referenced in file test.kt, will not be accessible from module A
|
||||||
Property a.val1, referenced in file test.kt, will not be accessible from module A
|
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package a2
|
package a2
|
||||||
|
|
||||||
import b.internalTargetVal
|
import a1.internalTargetVal
|
||||||
Reference in New Issue
Block a user