[LL API] Invalidate code fragment sessions on PSI modifications
Code fragments depend not only on their context module, but also on body of the context declaration.
This commit is contained in:
+16
-3
@@ -35,6 +35,7 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
|
|
||||||
private val sourceCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
private val sourceCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
private val binaryCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
private val binaryCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
|
private val codeFragmentSessionCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the existing session if found, or creates a new session and caches it.
|
* Returns the existing session if found, or creates a new session and caches it.
|
||||||
@@ -47,7 +48,12 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return getCachedSession(module, sourceCache, ::createSession)
|
val targetCache = when (module) {
|
||||||
|
is KtCodeFragmentModule -> codeFragmentSessionCache
|
||||||
|
else -> sourceCache
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCachedSession(module, targetCache, ::createSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,9 +85,10 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
ApplicationManager.getApplication().assertWriteAccessAllowed()
|
ApplicationManager.getApplication().assertWriteAccessAllowed()
|
||||||
|
|
||||||
val didSourceSessionExist = removeSessionFrom(module, sourceCache)
|
val didSourceSessionExist = removeSessionFrom(module, sourceCache)
|
||||||
val didBinarySessionExist = if (module is KtBinaryModule) removeSessionFrom(module, binaryCache) else false
|
val didBinarySessionExist = module is KtBinaryModule && removeSessionFrom(module, binaryCache)
|
||||||
|
val didCodeFragmentSessionExist = module is KtCodeFragmentModule && removeSessionFrom(module, codeFragmentSessionCache)
|
||||||
|
|
||||||
return didSourceSessionExist || didBinarySessionExist
|
return didSourceSessionExist || didBinarySessionExist || didCodeFragmentSessionExist
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSessionFrom(module: KtModule, storage: SessionStorage): Boolean {
|
private fun removeSessionFrom(module: KtModule, storage: SessionStorage): Boolean {
|
||||||
@@ -106,6 +113,12 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
// `binaryCache` can only contain library modules, so we only need to remove sessions from `sourceCache`.
|
// `binaryCache` can only contain library modules, so we only need to remove sessions from `sourceCache`.
|
||||||
removeAllMatchingSessionsFrom(sourceCache) { it !is KtBinaryModule && it !is KtLibrarySourceModule }
|
removeAllMatchingSessionsFrom(sourceCache) { it !is KtBinaryModule && it !is KtLibrarySourceModule }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeAllCodeFragmentSessions()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeAllCodeFragmentSessions() {
|
||||||
|
removeAllSessionsFrom(codeFragmentSessionCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removing script sessions is only needed temporarily until KTIJ-25620 has been implemented.
|
// Removing script sessions is only needed temporarily until KTIJ-25620 has been implemented.
|
||||||
|
|||||||
+11
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
|||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinAnchorModuleProvider
|
import org.jetbrains.kotlin.analysis.providers.KotlinAnchorModuleProvider
|
||||||
import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
|
import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
|
||||||
@@ -51,6 +52,10 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
|
|||||||
KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION,
|
KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION,
|
||||||
KotlinGlobalSourceOutOfBlockModificationListener { invalidateAll(includeLibraryModules = false) },
|
KotlinGlobalSourceOutOfBlockModificationListener { invalidateAll(includeLibraryModules = false) },
|
||||||
)
|
)
|
||||||
|
busConnection.subscribe(
|
||||||
|
PsiModificationTracker.TOPIC,
|
||||||
|
PsiModificationTracker.Listener { invalidateAllCodeFragments() }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +84,8 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
|
|||||||
if (module is KtScriptModule || module is KtScriptDependencyModule || module is KtLibraryModule) {
|
if (module is KtScriptModule || module is KtScriptDependencyModule || module is KtLibraryModule) {
|
||||||
sessionCache.removeAllScriptSessions()
|
sessionCache.removeAllScriptSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionCache.removeAllCodeFragmentSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invalidateAll(includeLibraryModules: Boolean) {
|
private fun invalidateAll(includeLibraryModules: Boolean) {
|
||||||
@@ -98,6 +105,10 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
|
|||||||
LLFirSessionCache.getInstance(project).removeAllSessions(includeLibraryModules)
|
LLFirSessionCache.getInstance(project).removeAllSessions(includeLibraryModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun invalidateAllCodeFragments() {
|
||||||
|
LLFirSessionCache.getInstance(project).removeAllCodeFragmentSessions()
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -15,6 +15,9 @@ import com.intellij.openapi.project.Project
|
|||||||
* should keep this limitation in mind and handle it separately. For example, a global modification event should be published for builtins
|
* should keep this limitation in mind and handle it separately. For example, a global modification event should be published for builtins
|
||||||
* and SDK changes.
|
* and SDK changes.
|
||||||
*
|
*
|
||||||
|
* An empty set is also returned for [KtCodeFragmentModule]s, as no other module can depend on a code fragment.
|
||||||
|
* Additionally, [KtCodeFragmentModule] are not returned from [getDirectDependents] for their context modules.
|
||||||
|
*
|
||||||
* Implementations of this provider should ensure that results are provided in reasonable time, for example by caching results, as its
|
* Implementations of this provider should ensure that results are provided in reasonable time, for example by caching results, as its
|
||||||
* functions may be called frequently.
|
* functions may be called frequently.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user