[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
This commit is contained in:
committed by
Space Team
parent
03c8654fe3
commit
2ba42b8677
-11
@@ -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()
|
||||
}
|
||||
}
|
||||
-42
@@ -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<LLFirSession>.invalidateIfAlive() = ApplicationManager.getApplication().runWriteAction {
|
||||
val session = get() ?: return@runWriteAction
|
||||
if (session.project.isDisposed) return@runWriteAction
|
||||
|
||||
session.invalidateInWriteAction()
|
||||
}
|
||||
|
||||
abstract class LLFirModuleSession(
|
||||
ktModule: KtModule,
|
||||
builtinTypes: BuiltinTypes,
|
||||
|
||||
-8
@@ -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<in Owner : Any, Context : Any>(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 <Target : FirElementWithResolveState, Context : Any, Result>
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user