[LL FIR] KT-58257 Don't invalidate dependent sessions when root session is absent

- We don't need to invalidate dependent sessions when the root session
  isn't in the session cache, or if the session is already marked as
  invalid, because any dependent sessions that might exist won't be
  referencing entities from the root session at that point.
This commit is contained in:
Marco Pennekamp
2023-06-30 18:50:05 +02:00
committed by Space Team
parent abc1be2ee0
commit efabd55646
3 changed files with 21 additions and 13 deletions
@@ -68,6 +68,8 @@ abstract class LLFirSession(
}
private fun invalidateInWriteAction() {
if (!isValid) return
LLFirSessionInvalidationService.getInstance(project).invalidate(ktModule)
}
@@ -71,24 +71,23 @@ class LLFirSessionCache(private val project: Project) {
}
/**
* Removes the session(s) associated with [module] after it has been invalidated.
* Removes the session(s) associated with [module] after it has been invalidated. Must be called in a write action.
*
* [removeSession] must be called in a write action.
* @return `true` if any sessions were removed.
*/
fun removeSession(module: KtModule) {
fun removeSession(module: KtModule): Boolean {
ApplicationManager.getApplication().assertWriteAccessAllowed()
removeSessionFrom(module, sourceCache)
if (module is KtBinaryModule) {
removeSessionFrom(module, binaryCache)
}
val didSourceSessionExist = removeSessionFrom(module, sourceCache)
val didBinarySessionExist = if (module is KtBinaryModule) removeSessionFrom(module, binaryCache) else false
return didSourceSessionExist || didBinarySessionExist
}
private fun removeSessionFrom(module: KtModule, storage: SessionStorage) {
val session = storage.remove(module)
if (session != null) {
session.isValid = false
}
private fun removeSessionFrom(module: KtModule, storage: SessionStorage): Boolean {
val session = storage.remove(module) ?: return false
session.isValid = false
return true
}
/**
@@ -72,7 +72,14 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
ApplicationManager.getApplication().assertWriteAccessAllowed()
val sessionCache = LLFirSessionCache.getInstance(project)
sessionCache.removeSession(module)
val didSessionExist = sessionCache.removeSession(module)
// We don't have to invalidate dependent sessions if the root session does not exist in the cache. It is true that sessions can be
// created without their dependency sessions being created, as session dependencies are lazy. So some of the root session's
// dependents might exist. But if the root session does not exist, its dependent sessions won't contain any elements resolved by the
// root session, so they effectively don't depend on the root session at that moment and don't need to be invalidated.
if (!didSessionExist) return
KotlinModuleDependentsProvider.getInstance(project).getTransitiveDependents(module).forEach(sessionCache::removeSession)
}