[AA] Implement disposable KtResolveExtensions

- This commit adds the `Disposable` interface to `KtResolveExtension`.
  Resolve extensions are disposed after their associated session has
  been invalidated, or reclaimed by the GC.
- Example use case: Opening a message bus connection with the lifetime
  of the resolve extension.

^KT-61222 fixed
This commit is contained in:
Marco Pennekamp
2023-08-18 19:11:41 +02:00
committed by Space Team
parent efb56ed30a
commit 7a5a1833e7
3 changed files with 43 additions and 9 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentScopeProvider
@@ -39,9 +40,17 @@ internal fun LLFirSession.registerIdeComponents(project: Project) {
register(SealedClassInheritorsProvider::class, createSealedInheritorsProvider(project))
register(FirExceptionHandler::class, LLFirExceptionHandler)
register(CodeFragmentScopeProvider::class, CodeFragmentScopeProvider(this))
createResolveExtensionTool()?.let {
register(LLFirResolveExtensionTool::class, it)
}
registerResolveExtensionTool()
}
@SessionConfiguration
private fun LLFirSession.registerResolveExtensionTool() {
val resolveExtensionTool = createResolveExtensionTool() ?: return
// `KtResolveExtension`s are disposables meant to be tied to the lifetime of the `LLFirSession`.
resolveExtensionTool.extensions.forEach { Disposer.register(requestDisposable(), it) }
register(LLFirResolveExtensionTool::class, resolveExtensionTool)
}
private fun LLFirSession.createResolveExtensionTool(): LLFirResolveExtensionTool? {
@@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentHashMap
* for the [org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider].
*/
abstract class LLFirResolveExtensionTool : FirSessionComponent {
internal abstract val extensions: List<KtResolveExtension>
abstract val declarationProvider: LLFirResolveExtensionToolDeclarationProvider
abstract val packageProvider: KotlinPackageProvider
abstract val packageFilter: LLFirResolveExtensionToolPackageFilter
@@ -48,7 +50,7 @@ val FirSession.llResolveExtensionTool: LLFirResolveExtensionTool? by FirSession.
internal class LLFirNonEmptyResolveExtensionTool(
session: LLFirSession,
extensions: List<KtResolveExtension>,
override val extensions: List<KtResolveExtension>,
) : LLFirResolveExtensionTool() {
init {
require(extensions.isNotEmpty())