diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt index 5c4dacf7ae2..5e6487b9756 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt @@ -35,8 +35,9 @@ data class ScriptModuleInfo( override val moduleOrigin: ModuleOrigin get() = ModuleOrigin.OTHER - val externalDependencies: ScriptDependencies - get() = ScriptDependenciesManager.getInstance(project).getScriptDependencies(scriptFile) + val externalDependencies: ScriptDependencies by lazy { + ScriptDependenciesManager.getInstance(project).getScriptDependencies(scriptFile) + } val relatedModuleSourceInfo: ModuleSourceInfo? = getScriptRelatedModuleInfo(project, scriptFile) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index 8f55538c9e0..91e012b1992 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -216,8 +216,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { val dependenciesForSyntheticFileCache = listOf( PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, - filesModificationTracker, - ScriptDependenciesModificationTracker.getInstance(project) + filesModificationTracker ) val resolverDebugName = @@ -383,17 +382,37 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } } + private val scriptsCacheProvider = CachedValueProvider { + CachedValueProvider.Result( + object : SLRUCache, ProjectResolutionFacade>(2, 3) { + override fun createValue(files: Set) = createFacadeForFilesWithSpecialModuleInfo(files) + }, + LibraryModificationTracker.getInstance(project), + ProjectRootModificationTracker.getInstance(project), + ScriptDependenciesModificationTracker.getInstance(project)) + } + + private fun getFacadeForScripts(files: Set): ProjectResolutionFacade { + return CachedValuesManager.getManager(project).getCachedValue(project, scriptsCacheProvider).get(files) + } + private fun getFacadeToAnalyzeFiles(files: Collection): ResolutionFacade { val file = files.first() val moduleInfo = file.getModuleInfo() - val specialFiles = files.filterNotInProjectSourceOrScript(moduleInfo) - return if (specialFiles.isNotEmpty()) { - val projectFacade = getFacadeForSpecialFiles(specialFiles) - ModuleResolutionFacadeImpl(projectFacade, moduleInfo) - } else { - val platform = TargetPlatformDetector.getPlatform(file) - getResolutionFacadeByModuleInfo(moduleInfo, platform) + val scripts = files.filterScripts() + if (scripts.isNotEmpty()) { + val projectFacade = getFacadeForScripts(scripts) + return ModuleResolutionFacadeImpl(projectFacade, moduleInfo) } + + val specialFiles = files.filterNotInProjectSource(moduleInfo) + if (specialFiles.isNotEmpty()) { + val projectFacade = getFacadeForSpecialFiles(specialFiles) + return ModuleResolutionFacadeImpl(projectFacade, moduleInfo) + } + + val platform = TargetPlatformDetector.getPlatform(file) + return getResolutionFacadeByModuleInfo(moduleInfo, platform) } override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade? { @@ -421,14 +440,20 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? = (moduleInfo as? IdeaModuleInfo)?.let { getResolutionFacadeByModuleInfo(it, platform) } - private fun Collection.filterNotInProjectSourceOrScript(moduleInfo: IdeaModuleInfo): Set { + private fun Collection.filterNotInProjectSource (moduleInfo: IdeaModuleInfo): Set { return mapNotNull { if (it is KtCodeFragment) it.getContextFile() else it }.filter { - !ProjectRootsUtil.isInProjectSource(it) || !moduleInfo.contentScope().contains(it) || it.isScript() + !ProjectRootsUtil.isInProjectSource(it) || !moduleInfo.contentScope().contains(it) }.toSet() } + private fun Collection.filterScripts(): Set { + return mapNotNull { + if (it is KtCodeFragment) it.getContextFile() else it + }.filter { it.isScript() }.toSet() + } + private fun KtCodeFragment.getContextFile(): KtFile? { val contextElement = context ?: return null val contextFile = (contextElement as? KtElement)?.containingKtFile