diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt index 7163fc0c674..11c83f67ffa 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt @@ -94,10 +94,6 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, for } } -fun Module.cached(provider: CachedValueProvider): T { - return CachedValuesManager.getManager(project).getCachedValue(this, provider) -} - private fun OrderEntry.acceptAsDependency(forProduction: Boolean): Boolean { return this !is ExportableOrderEntry || !forProduction diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/cacheUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/cacheUtil.kt new file mode 100644 index 00000000000..a59649368c8 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/cacheUtil.kt @@ -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 Module.cached(provider: CachedValueProvider): T { + return CachedValuesManager.getManager(project).getCachedValue(this, provider) +} + +fun Project.cached(provider: CachedValueProvider): T { + return CachedValuesManager.getManager(this).getCachedValue(this, provider) +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/moduleInfosFromIdeaModel.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/moduleInfosFromIdeaModel.kt index 9d3a1993c4c..774ea606d7a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/moduleInfosFromIdeaModel.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/moduleInfosFromIdeaModel.kt @@ -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 { +fun getModuleInfosFromIdeaModel(project: Project, platform: TargetPlatform): List { + val modelInfosCache = project.cached(CachedValueProvider { + CachedValueProvider.Result(collectModuleInfosFromIdeaModel(project), ProjectRootModificationTracker.getInstance(project)) + }) + return modelInfosCache.forPlatform(platform) +} + +private class IdeaModelInfosCache( + val moduleSourceInfos: List, + val libraryInfos: List, + val sdkInfos: List +) { + private val resultByPlatform = ConcurrentHashMap>() + + fun forPlatform(platform: TargetPlatform): List { + 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().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, + allModules: List, platform: TargetPlatform ): List { 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) -> diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt index b0176d3a9bd..07af168b025 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt @@ -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