Move to Separate File: Optimize usage search/processing

- Import optimization is already performed by refactoring helper,
so running optimizer explicitly is unnecessary

- Do not search external usages for declarations with unchaged package
and module

 #KT-18823 Fixed
This commit is contained in:
Alexey Sedunov
2017-09-15 19:20:40 +03:00
parent 0a0457298b
commit fefa2304a0
4 changed files with 29 additions and 8 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.codeInsight.navigation.NavigationUtil
import com.intellij.openapi.application.ApplicationManager
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
import org.jetbrains.kotlin.idea.refactoring.runRefactoringWithPostprocessing
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
@@ -108,9 +106,6 @@ class MoveDeclarationToSeparateFileIntention :
}
)
val move = { MoveKotlinDeclarationsProcessor(descriptor).run() }
val optimizeImports = { OptimizeImportsProcessor(project, file).run() }
move.runRefactoringWithPostprocessing(project, MoveKotlinDeclarationsProcessor.REFACTORING_ID, optimizeImports)
MoveKotlinDeclarationsProcessor(descriptor).run()
}
}
@@ -41,6 +41,7 @@ import com.intellij.util.containers.MultiMap
import gnu.trove.THashMap
import gnu.trove.TObjectHashingStrategy
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet
import org.jetbrains.kotlin.idea.core.deleteSingle
@@ -48,6 +49,9 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.idea.refactoring.move.*
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
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.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
@@ -149,8 +153,18 @@ class MoveKotlinDeclarationsProcessor(
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
fun canSkipUsages(element: PsiElement): Boolean {
val ktDeclaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return false
if (ktDeclaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return false
val (oldContainer, newContainer) = descriptor.delegate.getContainerChangeInfo(ktDeclaration, descriptor.moveTarget)
val targetModule = descriptor.moveTarget.targetFile?.getModule(project) ?: return false
return oldContainer == newContainer && ktDeclaration.module == targetModule
}
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
if (canSkipUsages(lightElement)) return@flatMapTo emptyList()
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
val foundReferences = HashSet<PsiReference>()
@@ -70,12 +70,20 @@ sealed class ContainerInfo {
override fun matches(descriptor: DeclarationDescriptor): Boolean {
return descriptor is PackageFragmentDescriptor && descriptor.fqName == fqName
}
override fun equals(other: Any?) = other is Package && other.fqName == fqName
override fun hashCode() = fqName.hashCode()
}
class Class(override val fqName: FqName) : ContainerInfo() {
override fun matches(descriptor: DeclarationDescriptor): Boolean {
return descriptor is ClassDescriptor && descriptor.importableFqName == fqName
}
override fun equals(other: Any?) = other is Class && other.fqName == fqName
override fun hashCode() = fqName.hashCode()
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.util.projectStructure
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ModuleRootManager
@@ -25,6 +26,8 @@ import com.intellij.openapi.roots.OrderEnumerator
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import java.io.File
fun Project.allModules() = ModuleManager.getInstance(this).modules.toList()
@@ -67,6 +70,7 @@ fun Library.ModifiableModel.replaceFileRoot(oldFile: File, newFile: File) {
replaceInRootType(OrderRootType.SOURCES)
}
fun VirtualFile.getModule(project: Project) = ModuleUtilCore.findModuleForFile(this, project)
val PsiElement.module
get() = ModuleUtilCore.findModuleForPsiElement(this)