Cache result of collectModulesFromIdeaModel

Cache base module infos from idea model until next root modification
Calculate platform specific module infos (see PlatformModuleInfo)
    on demand based on cached module infos from idea model

 #KT-24144 Fixed
This commit is contained in:
Pavel V. Talanov
2018-04-27 17:05:33 +02:00
parent 406a3888c7
commit 607fab994c
4 changed files with 55 additions and 19 deletions
@@ -94,10 +94,6 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, for
}
}
fun <T> Module.cached(provider: CachedValueProvider<T>): T {
return CachedValuesManager.getManager(project).getCachedValue(this, provider)
}
private fun OrderEntry.acceptAsDependency(forProduction: Boolean): Boolean {
return this !is ExportableOrderEntry
|| !forProduction
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.caches.project
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
fun <T> Module.cached(provider: CachedValueProvider<T>): T {
return CachedValuesManager.getManager(project).getCachedValue(this, provider)
}
fun <T> Project.cached(provider: CachedValueProvider<T>): T {
return CachedValuesManager.getManager(this).getCachedValue(this, provider)
}
@@ -13,11 +13,37 @@ import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.psi.util.CachedValueProvider
import org.jetbrains.kotlin.resolve.TargetPlatform
import java.util.concurrent.ConcurrentHashMap
fun collectAllModuleInfosFromIdeaModel(project: Project, platform: TargetPlatform): List<IdeaModuleInfo> {
fun getModuleInfosFromIdeaModel(project: Project, platform: TargetPlatform): List<IdeaModuleInfo> {
val modelInfosCache = project.cached(CachedValueProvider {
CachedValueProvider.Result(collectModuleInfosFromIdeaModel(project), ProjectRootModificationTracker.getInstance(project))
})
return modelInfosCache.forPlatform(platform)
}
private class IdeaModelInfosCache(
val moduleSourceInfos: List<ModuleSourceInfo>,
val libraryInfos: List<LibraryInfo>,
val sdkInfos: List<SdkInfo>
) {
private val resultByPlatform = ConcurrentHashMap<TargetPlatform, List<IdeaModuleInfo>>()
fun forPlatform(platform: TargetPlatform): List<IdeaModuleInfo> {
return resultByPlatform.getOrPut(platform) {
mergePlatformModules(moduleSourceInfos, platform) + libraryInfos + sdkInfos
}
}
}
private fun collectModuleInfosFromIdeaModel(
project: Project
): IdeaModelInfosCache {
val ideaModules = ModuleManager.getInstance(project).modules.toList()
val modulesSourcesInfos = ideaModules.flatMap(Module::correspondingModuleInfos)
//TODO: (module refactoring) include libraries that are not among dependencies of any module
val ideaLibraries = ideaModules.flatMap {
@@ -26,33 +52,28 @@ fun collectAllModuleInfosFromIdeaModel(project: Project, platform: TargetPlatfor
}
}.filterNotNull().toSet()
val librariesInfos = ideaLibraries.map { LibraryInfo(project, it) }
val sdksFromModulesDependencies = ideaModules.flatMap {
ModuleRootManager.getInstance(it).orderEntries.filterIsInstance<JdkOrderEntry>().map {
it.jdk
}
}
val sdksInfos = (sdksFromModulesDependencies + getAllProjectSdks()).filterNotNull().toSet().map {
SdkInfo(
project,
it
)
}
return mergePlatformModules(modulesSourcesInfos, platform) + librariesInfos + sdksInfos
return IdeaModelInfosCache(
moduleSourceInfos = ideaModules.flatMap(Module::correspondingModuleInfos),
libraryInfos = ideaLibraries.map { LibraryInfo(project, it) },
sdkInfos = (sdksFromModulesDependencies + getAllProjectSdks()).filterNotNull().toSet().map { SdkInfo(project, it) }
)
}
private fun mergePlatformModules(
allModules: List<IdeaModuleInfo>,
allModules: List<ModuleSourceInfo>,
platform: TargetPlatform
): List<IdeaModuleInfo> {
if (platform == TargetPlatform.Common) return allModules
val platformModules =
allModules.flatMap { module ->
if (module is ModuleSourceInfo && module.platform == platform && module.expectedBy.isNotEmpty())
if (module.platform == platform && module.expectedBy.isNotEmpty())
listOf(module to module.expectedBy)
else emptyList()
}.map { (module, expectedBys) ->
@@ -104,7 +104,7 @@ internal class ProjectResolutionFacade(
globalContext
)
val allModuleInfos = (allModules ?: collectAllModuleInfosFromIdeaModel(project, settings.platform)).toMutableSet()
val allModuleInfos = (allModules ?: getModuleInfosFromIdeaModel(project, settings.platform)).toMutableSet()
val syntheticFilesByModule = syntheticFiles.groupBy(KtFile::getModuleInfo)
val syntheticFilesModules = syntheticFilesByModule.keys