[LL] Fix computeIfAbsent contract violation during dangling file session creation
- To avoid recursive updates, we can create sessions which cannot be created in isolation outside `computeIfAbsent`. Note that this is the current behavior of the default implementation of `ConcurrentMap.computeIfAbsent`, which will be replaced soon with the stricter behavior of `CleanableSoftValueCache` (see KT-61222). ^KT-65683 fixed
This commit is contained in:
committed by
Space Team
parent
2e2e592cc3
commit
b24c75d04c
+18
-2
@@ -88,9 +88,18 @@ class LLFirSessionCache(private val project: Project) {
|
||||
private fun <T : KtModule> getCachedSession(module: T, storage: SessionStorage, factory: (T) -> LLFirSession): LLFirSession {
|
||||
checkCanceled()
|
||||
|
||||
val session = storage.computeIfAbsent(module) { factory(module) }
|
||||
checkSessionValidity(session)
|
||||
val session = if (module.supportsIsolatedSessionCreation) {
|
||||
storage.computeIfAbsent(module) { factory(module) }
|
||||
} else {
|
||||
// Non-isolated session creation may need to access other sessions, so we should create the session outside `computeIfAbsent` to
|
||||
// avoid recursive update exceptions.
|
||||
storage[module] ?: run {
|
||||
val danglingSession = factory(module)
|
||||
storage.computeIfAbsent(module) { danglingSession }
|
||||
}
|
||||
}
|
||||
|
||||
checkSessionValidity(session)
|
||||
return session
|
||||
}
|
||||
|
||||
@@ -199,6 +208,13 @@ class LLFirSessionCache(private val project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the session for [module] can be created without getting other sessions from the cache. Should be kept in sync with
|
||||
* [createSession].
|
||||
*/
|
||||
private val KtModule.supportsIsolatedSessionCreation: Boolean
|
||||
get() = this !is KtDanglingFileModule
|
||||
|
||||
private fun createSession(module: KtModule): LLFirSession {
|
||||
val sessionFactory = createPlatformAwareSessionFactory(module)
|
||||
return when (module) {
|
||||
|
||||
Reference in New Issue
Block a user