[IR] Introduce API to register generated IR declaration to be present in metatada

KT-63881
This commit is contained in:
Dmitriy Novozhilov
2023-11-24 16:38:27 +02:00
parent 1cdc8361d6
commit 159bc1b435
6 changed files with 340 additions and 132 deletions
@@ -7,17 +7,18 @@ package org.jetbrains.kotlin.fir.serialization
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
import org.jetbrains.kotlin.fir.extensions.declarationForMetadataProviders
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
companion object {
@@ -32,6 +33,8 @@ abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
abstract fun getProvidedCallables(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirCallableDeclaration>
abstract fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>>
abstract fun registerDeclaration(declaration: FirCallableDeclaration)
private object Empty : FirProvidedDeclarationsForMetadataService() {
override fun getProvidedTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> {
return emptyList()
@@ -48,70 +51,57 @@ abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
override fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> {
return emptyList()
}
override fun registerDeclaration(declaration: FirCallableDeclaration) {
shouldNotBeCalled()
}
}
}
private class FirProvidedDeclarationsForMetadataServiceImpl(
session: FirSession,
private val session: FirSession,
private val extensionDeclarationProviders: List<FirDeclarationsForMetadataProviderExtension>
) : FirProvidedDeclarationsForMetadataService() {
private val cachesFactory = session.firCachesFactory
private val topLevelsCache: MutableMap<FqName, MutableList<FirDeclaration>> =
mutableMapOf()
private val topLevelsCache: FirCache<FqName, List<FirDeclaration>, ScopeSession> =
cachesFactory.createCache(::computeTopLevelDeclarations)
private val memberCache: MutableMap<FirClassSymbol<*>, ClassDeclarations> =
mutableMapOf()
private val membersCache: FirCache<FirClassSymbol<*>, ClassDeclarations, ScopeSession> =
cachesFactory.createCache(::computeMemberDeclarations)
private fun computeTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> {
return buildList {
for (extensionProvider in extensionDeclarationProviders) {
for (declaration in extensionProvider.provideTopLevelDeclarations(packageFqName, scopeSession)) {
add(declaration)
}
override fun registerDeclaration(declaration: FirCallableDeclaration) {
val containingClass = declaration.containingClassLookupTag()?.toFirRegularClass(session)
if (containingClass == null) {
val list = topLevelsCache.getOrPut(declaration.symbol.callableId.packageName) { mutableListOf() }
list += declaration
} else {
val declarations = memberCache.getOrPut(containingClass.symbol) { ClassDeclarations() }
when (declaration) {
is FirConstructor -> declarations.providedConstructors += declaration
else -> declarations.providedCallables += declaration
}
}
}
override fun getProvidedTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> {
return topLevelsCache.getValue(packageFqName, scopeSession)
return topLevelsCache[packageFqName] ?: emptyList()
}
override fun getProvidedConstructors(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirConstructor> {
return membersCache.getValue(owner, scopeSession).providedConstructors
return memberCache[owner]?.providedConstructors ?: emptyList()
}
override fun getProvidedCallables(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirCallableDeclaration> {
return membersCache.getValue(owner, scopeSession).providedCallables
return memberCache[owner]?.providedCallables ?: emptyList()
}
override fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> {
return membersCache.getValue(owner, scopeSession).providedNestedClasses
// TODO: remove
return emptyList()
}
private data class ClassDeclarations(
val providedCallables: List<FirCallableDeclaration>,
val providedConstructors: List<FirConstructor>,
val providedNestedClasses: List<FirClassLikeSymbol<*>>,
)
private fun computeMemberDeclarations(symbol: FirClassSymbol<*>, scopeSession: ScopeSession): ClassDeclarations {
val providedCallables = mutableListOf<FirCallableDeclaration>()
val providedConstructors = mutableListOf<FirConstructor>()
val providedNestedClassifiers = mutableListOf<FirClassLikeSymbol<*>>()
for (extensionProvider in extensionDeclarationProviders) {
for (declaration in extensionProvider.provideDeclarationsForClass(symbol.fir, scopeSession)) {
when (declaration) {
is FirConstructor -> providedConstructors += declaration
is FirCallableDeclaration -> providedCallables += declaration
is FirClassLikeDeclaration -> providedNestedClassifiers += declaration.symbol
else -> error("Unsupported declaration type in: $symbol ${declaration.render()}")
}
}
}
return ClassDeclarations(providedCallables, providedConstructors, providedNestedClassifiers)
private class ClassDeclarations {
val providedCallables: MutableList<FirCallableDeclaration> = mutableListOf()
val providedConstructors: MutableList<FirConstructor> = mutableListOf()
}
}