From fc64d8d5e82edc7fddceeb35a06b4294be8318a6 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Sat, 5 Sep 2020 16:28:48 +0300 Subject: [PATCH] FIR IDE: reanalyse dependent modules only then they change --- .../level/api/FirIdeResolveStateService.kt | 38 ++++++++++++++----- .../api/sessions/FirIdeSessionFactory.kt | 7 ++-- .../api/sessions/FirIdeSourcesSession.kt | 2 + 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt index c795ba718a1..83106e3d259 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt @@ -7,26 +7,30 @@ package org.jetbrains.kotlin.idea.fir.low.level.api import com.intellij.openapi.components.service import com.intellij.openapi.project.Project +import com.intellij.openapi.util.ModificationTracker +import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager -import com.intellij.psi.util.PsiModificationTracker import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.LibraryModificationTracker import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver +import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeDependentModulesSourcesSession import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeLibrariesSession import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionFactory import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionProvider import org.jetbrains.kotlin.idea.util.cachedValue +import org.jetbrains.kotlin.idea.util.getValue import org.jetbrains.kotlin.idea.util.psiModificationTrackerBasedCachedValue import java.util.concurrent.ConcurrentHashMap -import org.jetbrains.kotlin.idea.util.getValue internal class FirIdeResolveStateService(private val project: Project) { private val stateCache by psiModificationTrackerBasedCachedValue(project) { ConcurrentHashMap() } + private val moduleLibraryDependencyStateCache = ConcurrentHashMap>() + private val librarySessionCache by cachedValue(project, LibraryModificationTracker.getInstance(project)) { ConcurrentHashMap() } @@ -41,13 +45,28 @@ internal class FirIdeResolveStateService(private val project: Project) { FirIdeSessionFactory.createLibrarySession(moduleInfo, sessionProvider, project) } - val dependentModulesSession = FirIdeSessionFactory.createDependentModulesSourcesSession( - project, - moduleInfo, - firPhaseRunner, - sessionProvider, - librariesSession, - ) + val dependentModulesSession = moduleLibraryDependencyStateCache.compute(moduleInfo) { _, cachedIdeaModuleInfo -> + if (cachedIdeaModuleInfo?.hasUpToDateValue() == true) cachedIdeaModuleInfo + else { + CachedValuesManager.getManager(project).createCachedValue { + val dependentSession = FirIdeSessionFactory.createDependentModulesSourcesSession( + project, + moduleInfo, + firPhaseRunner, + sessionProvider, + librariesSession, + ) + CachedValueProvider.Result.create( + dependentSession, + dependentSession.dependentModules.map { it.createModificationTracker() } + .takeUnless { it.isEmpty() } + ?: listOf(ModificationTracker.NEVER_CHANGED) + ) + } + } + }?.value ?: error("ModuleLibraryDependencyStateCache should be computed") + + val currentModuleSession = FirIdeSessionFactory.createCurrentModuleSourcesSession( project, moduleInfo, @@ -69,6 +88,7 @@ internal class FirIdeResolveStateService(private val project: Project) { ) } + fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl = stateCache.getOrPut(moduleInfo) { createResolveStateFor(moduleInfo) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index 5b9d0632f83..dea6013c400 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -81,9 +81,10 @@ internal object FirIdeSessionFactory { val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner) val dependentModules = moduleInfo.collectTransitiveDependenciesWithSelf() .filterIsInstance() - .filterNot { it === moduleInfo } - val searchScope = ModuleWithDependentsScope(project, dependentModules.mapTo(mutableListOf()) { it.module }) - return FirIdeDependentModulesSourcesSession(moduleInfo, sessionProvider, searchScope, firBuilder).apply { + .filterNot { it == moduleInfo } + val searchScope = if (dependentModules.isNotEmpty()) GlobalSearchScope.union(dependentModules.map { it.contentScope() }) + else GlobalSearchScope.EMPTY_SCOPE + return FirIdeDependentModulesSourcesSession(moduleInfo, dependentModules, sessionProvider, searchScope, firBuilder).apply { val cache = ModuleFileCacheImpl(this) registerCommonSourceSessionComponents( project, diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt index 2aec6d10221..627152ac09f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSourcesSession.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.sessions import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.fir.PrivateSessionConstructor +import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider @@ -37,6 +38,7 @@ internal class FirIdeCurrentModuleSourcesSession @PrivateSessionConstructor cons @OptIn(PrivateSessionConstructor::class) internal class FirIdeDependentModulesSourcesSession @PrivateSessionConstructor constructor( moduleInfo: ModuleInfo, + val dependentModules: List, sessionProvider: FirIdeSessionProvider, scope: GlobalSearchScope, firFileBuilder: FirFileBuilder,