From 42c879a53cdd79e73f8d1afc9519386e33fb0c58 Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Wed, 12 Jul 2023 22:01:23 +0200 Subject: [PATCH] [LL FIR] KT-58257 Invalidate library sessions depending on anchor modules on global source modification - Any time an anchor module's session is invalidated, we need to make sure that all its dependents are also invalidated. Because those dependents may include libraries, invalidation after global source modification needs to invalidate such libraries, even if other stable module sessions should remain untouched. --- .../providers/KotlinAnchorModuleProvider.kt | 15 ++++++++++----- .../sessions/LLFirSessionInvalidationService.kt | 12 ++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinAnchorModuleProvider.kt b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinAnchorModuleProvider.kt index 0597ac1e467..a10634add6e 100644 --- a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinAnchorModuleProvider.kt +++ b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinAnchorModuleProvider.kt @@ -10,17 +10,22 @@ import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule /** - * Provide module which contains dependencies of the library. + * [KotlinAnchorModuleProvider] provides modules which contain dependencies of libraries. * - * Is required for navigation in IJ monorepo from kotlin compiler library sources to IJ platform sources. - * Kotlin compiler depends on platform but this dependency is not represented as jars in monorepo - * but should be replaced with given sources. + * In the IJ monorepo, anchor modules are required for navigation from Kotlin compiler library sources to IJ platform sources. The Kotlin + * compiler depends on the IJ platform, but this dependency is not represented as JARs in the monorepo, but rather by certain monorepo + * source modules, which are made visible to the Kotlin compiler library sources as dependencies via an anchor module. */ public interface KotlinAnchorModuleProvider { public fun getAnchorModule(libraryModule: KtLibraryModule): KtSourceModule? + /** + * Returns all anchor modules configured in the project. + */ + public fun getAllAnchorModules(): Collection + public companion object { public fun getInstance(project: Project): KotlinAnchorModuleProvider? = project.getService(KotlinAnchorModuleProvider::class.java) } -} \ No newline at end of file +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt index 6aa8171f831..5f8f97d41fe 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.project.structure.* +import org.jetbrains.kotlin.analysis.providers.KotlinAnchorModuleProvider import org.jetbrains.kotlin.analysis.providers.analysisMessageBus import org.jetbrains.kotlin.analysis.providers.topics.* @@ -87,6 +88,17 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable private fun invalidateAll(includeStableModules: Boolean) { ApplicationManager.getApplication().assertWriteAccessAllowed() + // When anchor modules are configured and `includeStableModules` is `false`, we get a situation where the anchor module session will + // be invalidated (because it is a source session), while its library dependents won't be invalidated (because they are sessions of + // stable modules). But such library sessions also need to be invalidated because they depend on the anchor module. + // + // Invalidating anchor modules before all source sessions has the advantage that `invalidate`'s session existence check will work, + // so we do not have to invalidate dependent sessions if the anchor module does not exist in the first place. + if (!includeStableModules) { + val anchorModules = KotlinAnchorModuleProvider.getInstance(project)?.getAllAnchorModules() + anchorModules?.forEach(::invalidate) + } + LLFirSessionCache.getInstance(project).removeAllSessions(includeStableModules) }