Optimize collecting module info in IDE

The problem was that there is no special entity for libraries
in the IntelliJ model, and when we have an element for a library
we have to search through all of its dependencies
(see getOrderEntriesForFile call in collectInfosByVirtualFile)

But for popular library there could be quite a lot of dependencies,
while in most cases we need only the first one to obtain module
info for library itself (see changed usage in resolverForElement).

So it's worth replacing List with Sequence here
This commit is contained in:
Denis Zharkov
2018-01-13 17:16:39 +03:00
parent d848238a46
commit b4e5f8cf1c
2 changed files with 19 additions and 16 deletions
@@ -79,9 +79,9 @@ internal class ProjectResolutionFacade(
fun resolverForElement(element: PsiElement): ResolverForModule { fun resolverForElement(element: PsiElement): ResolverForModule {
val infos = element.getModuleInfos() val infos = element.getModuleInfos()
return infos.firstNotNullResult { resolverForProject.tryGetResolverForModule(it) } return infos.asIterable().firstNotNullResult { resolverForProject.tryGetResolverForModule(it) }
?: resolverForProject.tryGetResolverForModule(NotUnderContentRootModuleInfo) ?: resolverForProject.tryGetResolverForModule(NotUnderContentRootModuleInfo)
?: resolverForProject.diagnoseUnknownModuleInfo(infos) ?: resolverForProject.diagnoseUnknownModuleInfo(infos.toList())
} }
fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = resolverForProject.resolverForModuleDescriptor(moduleDescriptor) fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = resolverForProject.resolverForModuleDescriptor(moduleDescriptor)
@@ -33,12 +33,14 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.script.getScriptDefinition import org.jetbrains.kotlin.script.getScriptDefinition
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
import org.jetbrains.kotlin.utils.yieldIfNotNull
import kotlin.coroutines.experimental.buildSequence
fun PsiElement.getModuleInfo(): IdeaModuleInfo = this.collectInfos(ModuleInfoCollector.NotNullTakeFirst) fun PsiElement.getModuleInfo(): IdeaModuleInfo = this.collectInfos(ModuleInfoCollector.NotNullTakeFirst)
fun PsiElement.getNullableModuleInfo(): IdeaModuleInfo? = this.collectInfos(ModuleInfoCollector.NullableTakeFirst) fun PsiElement.getNullableModuleInfo(): IdeaModuleInfo? = this.collectInfos(ModuleInfoCollector.NullableTakeFirst)
fun PsiElement.getModuleInfos(): List<IdeaModuleInfo> = this.collectInfos(ModuleInfoCollector.ToList) fun PsiElement.getModuleInfos(): Sequence<IdeaModuleInfo> = this.collectInfos(ModuleInfoCollector.ToSequence)
fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile): IdeaModuleInfo? = collectInfosByVirtualFile( fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile): IdeaModuleInfo? = collectInfosByVirtualFile(
project, virtualFile, project, virtualFile,
@@ -80,17 +82,17 @@ private sealed class ModuleInfoCollector<out T>(
} }
) )
object ToList : ModuleInfoCollector<List<IdeaModuleInfo>>( object ToSequence : ModuleInfoCollector<Sequence<IdeaModuleInfo>>(
onResult = { it?.let(::listOf).orEmpty() }, onResult = { result -> result?.let { sequenceOf(it) } ?: emptySequence() },
onFailure = { reason -> onFailure = { reason ->
LOG.warn("Could not find correct module information.\nReason: $reason") LOG.warn("Could not find correct module information.\nReason: $reason")
emptyList() emptySequence()
}, },
virtualFileProcessor = { project, virtualFile, isLibrarySource -> virtualFileProcessor = { project, virtualFile, isLibrarySource ->
val result = mutableListOf<IdeaModuleInfo>() buildSequence {
collectInfosByVirtualFile(project, virtualFile, isLibrarySource, { result.addIfNotNull(it) }) collectInfosByVirtualFile(project, virtualFile, isLibrarySource, { yieldIfNotNull(it) })
result
} }
}
) )
} }
@@ -212,6 +214,7 @@ private fun OrderEntry.toIdeaModuleInfo(
virtualFile: VirtualFile, virtualFile: VirtualFile,
treatAsLibrarySource: Boolean = false treatAsLibrarySource: Boolean = false
): IdeaModuleInfo? { ): IdeaModuleInfo? {
if (this is ModuleOrderEntry) return null
if (!isValid) return null if (!isValid) return null
when (this) { when (this) {