[Analysis API] Move 'KtCodeFragment' import modification subscription
Subscribing from service constructors may be dangerous, as services are
initialized lazily. It's unlikely for that code fragment import
modification to happen before 'LLFirDeclarationModificationService' is
created, but it still looks error-prone.
The new place, 'LLFirSessionInvalidationService', is called for code
fragments from 'LLFirDeclarationModificationService', so there should
not be any differences in behavior.
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt
index 9f14088..9319495 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt
@@ -35,7 +35,6 @@
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi
-import org.jetbrains.kotlin.psi.KotlinCodeFragmentImportModificationListener
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtCodeFragment
@@ -70,11 +69,6 @@
},
this,
)
-
- project.messageBus.connect(this).subscribe(
- KtCodeFragment.IMPORT_MODIFICATION,
- KotlinCodeFragmentImportModificationListener { codeFragment -> outOfBlockModification(codeFragment) }
- )
}
private var inBlockModificationQueue: MutableSet<ChangeType.InBlock>? = null
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt
index 7dcd7f1..384f9ab 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionInvalidationService.kt
@@ -13,6 +13,8 @@
import org.jetbrains.kotlin.analysis.providers.KotlinAnchorModuleProvider
import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
import org.jetbrains.kotlin.analysis.providers.topics.*
+import org.jetbrains.kotlin.psi.KotlinCodeFragmentImportModificationListener
+import org.jetbrains.kotlin.psi.KtCodeFragment
/**
* [LLFirSessionInvalidationService] listens to [modification events][KotlinTopics] and invalidates [LLFirSession]s which depend on the
@@ -64,6 +66,12 @@
PsiModificationTracker.TOPIC,
PsiModificationTracker.Listener { invalidateUnstableDanglingFileSessions() }
)
+
+ // 'KtCodeFragment' doesn't have access to 'analysisMessageBus' and always uses the project message bus
+ project.messageBus.connect(this).subscribe(
+ KtCodeFragment.IMPORT_MODIFICATION,
+ KotlinCodeFragmentImportModificationListener { codeFragment -> invalidateCodeFragment(codeFragment) }
+ )
}
/**
@@ -116,6 +124,11 @@
sessionCache.removeAllSessions(includeLibraryModules)
}
+ private fun invalidateCodeFragment(codeFragment: KtCodeFragment) {
+ val module = ProjectStructureProvider.getModule(project, codeFragment, contextualModule = null)
+ invalidateContextualDanglingFileSessions(module)
+ }
+
private fun invalidateContextualDanglingFileSessions(contextModule: KtModule) {
sessionCache.removeContextualDanglingFileSessions(contextModule)
}