From 2ba42b8677494f98d51b83e676552b75bc6e244d Mon Sep 17 00:00:00 2001 From: Marco Pennekamp Date: Tue, 18 Jul 2023 17:25:28 +0200 Subject: [PATCH] [LL FIR] KT-58257 Remove `LLFirSession.invalidate` - Due to problematic timing in `LLFirSession.invalidate` when the function is called from a read action, it's better to remove the function altogether. - The function's only usage was session invalidation after exceptions from resolve when FIR tree guards were turned off. Because FIR tree guards are stable enough, the flag that turned them off can be removed. This also allows removing `LLFirSession.invalidate`. - The alternative to removing `LLFirSession.invalidate` would be to rewrite session invalidation to be independent of write actions. That would require additional locking in `LLFirSessionCache`, which we want to avoid. ^KT-59297 --- .../LLFirModuleLazyDeclarationResolver.kt | 11 ----- .../level/api/fir/sessions/LLFirSession.kt | 42 ------------------- .../level/api/fir/transformers/StateKeeper.kt | 8 ---- 3 files changed, 61 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt index 315261a172b..0e21c8890ff 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirMo import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyResolverRunner -import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.USE_STATE_KEEPER import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.withOnAirDesignation import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile @@ -215,8 +214,6 @@ private fun handleExceptionFromResolve( } val session = firDeclarationToResolve.llFirSession - invalidateFailedSessionIfNeeded(session) - val moduleData = firDeclarationToResolve.llFirModuleData val module = moduleData.ktModule @@ -250,8 +247,6 @@ private fun handleExceptionFromResolve( } val session = designation.firFile.llFirSession - invalidateFailedSessionIfNeeded(session) - val moduleData = session.llFirModuleData val module = moduleData.ktModule @@ -271,9 +266,3 @@ private fun handleExceptionFromResolve( withEntry("firDesignationToResolve", designation) { it.toString() } } } - -private fun invalidateFailedSessionIfNeeded(session: LLFirSession) { - if (!USE_STATE_KEEPER) { - session.invalidate() - } -} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSession.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSession.kt index 2bfe250491d..688c0b2a460 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSession.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSession.kt @@ -5,11 +5,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.ModalityState import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker -import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.USE_STATE_KEEPER import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.FirElementWithResolveState @@ -17,7 +14,6 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.PrivateSessionConstructor import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol -import java.lang.ref.WeakReference import java.util.concurrent.atomic.AtomicLong @OptIn(PrivateSessionConstructor::class) @@ -46,31 +42,6 @@ abstract class LLFirSession( isValid = false } - fun invalidate() { - val application = ApplicationManager.getApplication() - if (application.isWriteAccessAllowed) { - invalidateInWriteAction() - } else { - // We have to invalidate the session on the EDT per the contract of `LLFirSessionInvalidationService`. The timing here is not - // 100% waterproof, but `LLFirSession.invalidate` is only a workaround for when FIR guards consistency protection (see KT-56503) - // is turned off. The check restricts usage of `invalidate` to this scenario. - check(!USE_STATE_KEEPER) { - "Outside a write action, a session may only be invalidated directly when FIR guards are turned off." - } - - // The lambda passed to `invokeLater` might survive beyond project disposal (especially in tests), so me must not capture a hard - // reference to `this` that can leak `project`. A weak reference is appropriate because we do not need to invalidate the session - // when it has already been collected. - val weakSession = WeakReference(this) - application.invokeLater( - { weakSession.invalidateIfAlive() }, - - // `ModalityState.any()` can be used because session invalidation does not modify PSI, VFS, or the project model. - ModalityState.any(), - ) - } - } - /** * Creates a [ModificationTracker] which tracks the validity of this session via [isValid]. */ @@ -91,19 +62,6 @@ abstract class LLFirSession( } } -private fun LLFirSession.invalidateInWriteAction() { - if (!isValid) return - - LLFirSessionInvalidationService.getInstance(project).invalidate(ktModule) -} - -private fun WeakReference.invalidateIfAlive() = ApplicationManager.getApplication().runWriteAction { - val session = get() ?: return@runWriteAction - if (session.project.isDisposed) return@runWriteAction - - session.invalidateInWriteAction() -} - abstract class LLFirModuleSession( ktModule: KtModule, builtinTypes: BuiltinTypes, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/StateKeeper.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/StateKeeper.kt index ee0ecd130d9..df999e7fb90 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/StateKeeper.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/StateKeeper.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers -import com.intellij.openapi.util.registry.Registry import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirSession @@ -241,8 +240,6 @@ internal class StateKeeper(val provider: (Owner, } } -internal val USE_STATE_KEEPER: Boolean = Registry.`is`("kotlin.analysis.use.state.keeper", true) - /** * State preserved by a [StateKeeper]. */ @@ -267,11 +264,6 @@ internal inline fun prepareTarget: (Target) -> Unit = {}, action: () -> Result, ): Result { - if (!USE_STATE_KEEPER) { - prepareTarget(target) - return action() - } - val onAirAnalysisTarget = target.moduleData.session.onAirAnalysisTarget if (onAirAnalysisTarget != null && target in onAirAnalysisTarget) { // Several arrangers reset declaration bodies to lazy ones, and then re-construct the FIR tree from the backing PSI.