[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 {
|
private fun <T : KtModule> getCachedSession(module: T, storage: SessionStorage, factory: (T) -> LLFirSession): LLFirSession {
|
||||||
checkCanceled()
|
checkCanceled()
|
||||||
|
|
||||||
val session = storage.computeIfAbsent(module) { factory(module) }
|
val session = if (module.supportsIsolatedSessionCreation) {
|
||||||
checkSessionValidity(session)
|
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
|
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 {
|
private fun createSession(module: KtModule): LLFirSession {
|
||||||
val sessionFactory = createPlatformAwareSessionFactory(module)
|
val sessionFactory = createPlatformAwareSessionFactory(module)
|
||||||
return when (module) {
|
return when (module) {
|
||||||
|
|||||||
Reference in New Issue
Block a user