[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.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.caches.FirCache import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
import org.jetbrains.kotlin.fir.extensions.declarationForMetadataProviders import org.jetbrains.kotlin.fir.extensions.declarationForMetadataProviders
import org.jetbrains.kotlin.fir.extensions.extensionService 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.ScopeSession
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent { abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
companion object { companion object {
@@ -32,6 +33,8 @@ abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
abstract fun getProvidedCallables(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirCallableDeclaration> abstract fun getProvidedCallables(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirCallableDeclaration>
abstract fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> abstract fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>>
abstract fun registerDeclaration(declaration: FirCallableDeclaration)
private object Empty : FirProvidedDeclarationsForMetadataService() { private object Empty : FirProvidedDeclarationsForMetadataService() {
override fun getProvidedTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> { override fun getProvidedTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> {
return emptyList() return emptyList()
@@ -48,70 +51,57 @@ abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
override fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> { override fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> {
return emptyList() return emptyList()
} }
override fun registerDeclaration(declaration: FirCallableDeclaration) {
shouldNotBeCalled()
}
} }
} }
private class FirProvidedDeclarationsForMetadataServiceImpl( private class FirProvidedDeclarationsForMetadataServiceImpl(
session: FirSession, private val session: FirSession,
private val extensionDeclarationProviders: List<FirDeclarationsForMetadataProviderExtension> private val extensionDeclarationProviders: List<FirDeclarationsForMetadataProviderExtension>
) : FirProvidedDeclarationsForMetadataService() { ) : FirProvidedDeclarationsForMetadataService() {
private val cachesFactory = session.firCachesFactory private val topLevelsCache: MutableMap<FqName, MutableList<FirDeclaration>> =
mutableMapOf()
private val topLevelsCache: FirCache<FqName, List<FirDeclaration>, ScopeSession> = private val memberCache: MutableMap<FirClassSymbol<*>, ClassDeclarations> =
cachesFactory.createCache(::computeTopLevelDeclarations) mutableMapOf()
private val membersCache: FirCache<FirClassSymbol<*>, ClassDeclarations, ScopeSession> = override fun registerDeclaration(declaration: FirCallableDeclaration) {
cachesFactory.createCache(::computeMemberDeclarations) val containingClass = declaration.containingClassLookupTag()?.toFirRegularClass(session)
if (containingClass == null) {
private fun computeTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> { val list = topLevelsCache.getOrPut(declaration.symbol.callableId.packageName) { mutableListOf() }
return buildList { list += declaration
for (extensionProvider in extensionDeclarationProviders) { } else {
for (declaration in extensionProvider.provideTopLevelDeclarations(packageFqName, scopeSession)) { val declarations = memberCache.getOrPut(containingClass.symbol) { ClassDeclarations() }
add(declaration) when (declaration) {
} is FirConstructor -> declarations.providedConstructors += declaration
else -> declarations.providedCallables += declaration
} }
} }
} }
override fun getProvidedTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> { 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> { 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> { 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<*>> { override fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> {
return membersCache.getValue(owner, scopeSession).providedNestedClasses // TODO: remove
return emptyList()
} }
private data class ClassDeclarations( private class ClassDeclarations {
val providedCallables: List<FirCallableDeclaration>, val providedCallables: MutableList<FirCallableDeclaration> = mutableListOf()
val providedConstructors: List<FirConstructor>, val providedConstructors: MutableList<FirConstructor> = mutableListOf()
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)
} }
} }
@@ -5,29 +5,39 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.GeneratedDeclarationKey
import org.jetbrains.kotlin.backend.common.extensions.IrGeneratedDeclarationsRegistrar import org.jetbrains.kotlin.backend.common.extensions.IrGeneratedDeclarationsRegistrar
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationArgumentMapping import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.packageFqName import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.serialization.FirAdditionalMetadataProvider import org.jetbrains.kotlin.fir.serialization.FirAdditionalMetadataProvider
import org.jetbrains.kotlin.fir.types.constructClassType import org.jetbrains.kotlin.fir.serialization.providedDeclarationsForMetadataService
import org.jetbrains.kotlin.fir.types.toFirResolvedTypeRef import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.types.toLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.ir.declarations.nameWithPackage import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -37,6 +47,12 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
// opt-in is safe, this code runs after fir2ir is over and all symbols are bound // opt-in is safe, this code runs after fir2ir is over and all symbols are bound
@OptIn(UnsafeDuringIrConstructionAPI::class) @OptIn(UnsafeDuringIrConstructionAPI::class)
class Fir2IrIrGeneratedDeclarationsRegistrar(private val components: Fir2IrComponents) : IrGeneratedDeclarationsRegistrar() { class Fir2IrIrGeneratedDeclarationsRegistrar(private val components: Fir2IrComponents) : IrGeneratedDeclarationsRegistrar() {
private val session: FirSession
get() = components.session
private val implicitType: FirImplicitTypeRef
get() = FirImplicitTypeRefImplWithoutSource
private val generatedIrDeclarationsByFileByOffset = mutableMapOf<String, MutableMap<Pair<Int, Int>, MutableList<IrConstructorCall>>>() private val generatedIrDeclarationsByFileByOffset = mutableMapOf<String, MutableMap<Pair<Int, Int>, MutableList<IrConstructorCall>>>()
private fun IrConstructorCall.hasOnlySupportedAnnotationArgumentTypes(): Boolean { private fun IrConstructorCall.hasOnlySupportedAnnotationArgumentTypes(): Boolean {
@@ -62,10 +78,276 @@ class Fir2IrIrGeneratedDeclarationsRegistrar(private val components: Fir2IrCompo
declaration.annotations += annotations declaration.annotations += annotations
} }
fun createMetadataAnnotationsProvider(): FirAdditionalMetadataAnnotationsProvider { override fun registerFunctionAsMetadataVisible(irFunction: IrSimpleFunction) {
if (irFunction.isLocal || irFunction.parentClassOrNull?.isLocal == true) return
val firFunction = buildSimpleFunction {
moduleData = session.moduleData
origin = GeneratedForMetadata.origin
status = FirResolvedDeclarationStatusImpl(
irFunction.visibility.delegate,
irFunction.modality,
irFunction.visibility.delegate.toEffectiveVisibility(owner = null)
).apply {
isExpect = irFunction.isExpect
isActual = false
isOverride = irFunction.overriddenSymbols.isNotEmpty()
isInfix = irFunction.isInfix
isInline = irFunction.isInline
isTailRec = irFunction.isTailrec
isSuspend = irFunction.isSuspend
}
returnTypeRef = implicitType
dispatchReceiverType = irFunction.parent.toFirClass()?.defaultType()
// contextReceivers
// valueParameters
name = irFunction.name
symbol = FirNamedFunctionSymbol(irFunction.callableId)
// annotations
irFunction.typeParameters.mapTo(typeParameters) {
buildTypeParameter {
moduleData = session.moduleData
origin = GeneratedForMetadata.origin
name = it.name
symbol = FirTypeParameterSymbol()
containingDeclarationSymbol = this@buildSimpleFunction.symbol
variance = it.variance
isReified = it.isReified
// bounds
// annotations
}
}
}
with(TypeConverter(irFunction, firFunction)) {
with(firFunction) {
replaceReturnTypeRef(irFunction.returnType.toConeType().toFirResolvedTypeRef())
val valueParameters = irFunction.valueParameters.map {
buildValueParameter {
moduleData = session.moduleData
origin = GeneratedForMetadata.origin
returnTypeRef = it.type.toConeType().toFirResolvedTypeRef()
name = it.name
symbol = FirValueParameterSymbol(name)
if (it.defaultValue != null) {
defaultValue = buildExpressionStub {
coneTypeOrNull = this@buildValueParameter.returnTypeRef.coneType
}
}
containingFunctionSymbol = firFunction.symbol
isCrossinline = it.isCrossinline
isNoinline = it.isNoinline
isVararg = it.isVararg
annotations.addAll(it.convertAnnotations())
}
}
replaceValueParameters(valueParameters)
for ((firParameter, irParameter) in typeParameters.zip(irFunction.typeParameters)) {
val newBounds = irParameter.superTypes.map { it.toConeType().toFirResolvedTypeRef() }
firParameter.replaceBounds(newBounds)
firParameter.replaceAnnotations(irParameter.convertAnnotations())
}
replaceAnnotations(irFunction.convertAnnotations())
}
}
session.providedDeclarationsForMetadataService.registerDeclaration(firFunction)
irFunction.metadata = FirMetadataSource.Function(firFunction)
}
override fun registerConstructorAsMetadataVisible(irConstructor: IrConstructor) {
if (irConstructor.isLocal || irConstructor.parentAsClass.isLocal) return
val constructedClass = irConstructor.parent.toFirClass()
?: error("Fir class for constructor ${irConstructor.render()} not found")
val firConstructor = buildConstructor {
moduleData = session.moduleData
origin = GeneratedForMetadata.origin
status = FirResolvedDeclarationStatusImpl(
irConstructor.visibility.delegate,
Modality.FINAL,
irConstructor.visibility.delegate.toEffectiveVisibility(owner = null)
).apply {
isExpect = irConstructor.isExpect
isActual = false
}
returnTypeRef = implicitType
// contextReceivers
// valueParameters
symbol = FirConstructorSymbol(constructedClass.classId)
// annotations
constructedClass.typeParameters.mapTo(typeParameters) { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
}
with(TypeConverter(irConstructor, firConstructor)) {
with(firConstructor) {
replaceReturnTypeRef(irConstructor.returnType.toConeType().toFirResolvedTypeRef())
val valueParameters = irConstructor.valueParameters.map {
buildValueParameter {
moduleData = session.moduleData
origin = GeneratedForMetadata.origin
returnTypeRef = it.type.toConeType().toFirResolvedTypeRef()
name = it.name
symbol = FirValueParameterSymbol(name)
if (it.defaultValue != null) {
defaultValue = buildExpressionStub {
coneTypeOrNull = this@buildValueParameter.returnTypeRef.coneType
}
}
containingFunctionSymbol = firConstructor.symbol
isCrossinline = it.isCrossinline
isNoinline = it.isNoinline
isVararg = it.isVararg
annotations.addAll(it.convertAnnotations())
}
}
replaceValueParameters(valueParameters)
replaceAnnotations(irConstructor.convertAnnotations())
containingClassForStaticMemberAttr = constructedClass.symbol.toLookupTag()
}
}
session.providedDeclarationsForMetadataService.registerDeclaration(firConstructor)
irConstructor.metadata = FirMetadataSource.Function(firConstructor)
}
fun createAdditionalMetadataProvider(): FirAdditionalMetadataProvider {
return Provider() return Provider()
} }
private fun IrDeclarationParent.toFirClass(): FirRegularClass? {
return (this as? IrClass)?.classIdOrFail?.toLookupTag()?.toFirRegularClass(session)
}
private fun IrAnnotationContainer.convertAnnotations(): List<FirAnnotation> {
return this.annotations.map { it.toFirAnnotation() }
}
private inner class TypeConverter(val originalFunction: IrFunction, val convertedFunction: FirFunction) {
fun IrType.toConeType(): ConeKotlinType {
return when (this) {
is IrSimpleType -> {
val lookupTag = classifier.toLookupTag()
lookupTag.constructType(
this.arguments.map { it.toConeTypeProjection() }.toTypedArray(),
isNullable = this.isNullable()
)
}
is IrDynamicType -> ConeDynamicType.create(session)
else -> error("Unsupported IR type: $this")
}
}
private fun IrTypeArgument.toConeTypeProjection(): ConeTypeProjection {
return when (this) {
is IrStarProjection -> ConeStarProjection
is IrTypeProjection -> type.toConeType().toTypeProjection(variance)
}
}
private fun IrClassifierSymbol.toLookupTag(): ConeClassifierLookupTag {
return when (val owner = owner) {
is IrClass -> owner.classIdOrFail.toLookupTag()
is IrTypeParameter -> {
val typeParameter = when (val parent = owner.parent) {
originalFunction -> convertedFunction.typeParameters[owner.index]
is IrClass -> {
val firClass = parent.classIdOrFail.toLookupTag().toFirRegularClass(session)
?: error("Fir class for ${parent.render()} not found")
firClass.typeParameters[owner.index]
}
else -> error("Unsupported type parameter container: ${parent.render()}")
}
typeParameter.symbol.toLookupTag()
}
else -> error("Unsupported IR classifier: ${owner.render()}")
}
}
}
private fun IrConstructorCall.toFirAnnotation(): FirAnnotation {
val annotationClassId = this.symbol.owner.constructedClass.classId!!
return buildAnnotation {
annotationTypeRef = annotationClassId
.toLookupTag()
.constructClassType(typeArguments = emptyArray(), isNullable = false)
.toFirResolvedTypeRef()
argumentMapping = buildAnnotationArgumentMapping {
for (i in 0 until this@toFirAnnotation.valueArgumentsCount) {
val name = this@toFirAnnotation.symbol.owner.valueParameters[i].name
val argument = this@toFirAnnotation.getValueArgument(i) as IrConst<*>
this.mapping[name] = when (argument.kind) {
IrConstKind.Boolean -> buildConstExpression(
source = null,
ConstantValueKind.Boolean,
argument.value as Boolean,
setType = true
)
IrConstKind.Byte -> buildConstExpression(
source = null,
ConstantValueKind.Byte,
argument.value as Byte,
setType = true
)
IrConstKind.Char -> buildConstExpression(
source = null,
ConstantValueKind.Char,
argument.value as Char,
setType = true
)
IrConstKind.Double -> buildConstExpression(
source = null,
ConstantValueKind.Double,
argument.value as Double,
setType = true
)
IrConstKind.Float -> buildConstExpression(
source = null,
ConstantValueKind.Float,
argument.value as Float,
setType = true
)
IrConstKind.Int -> buildConstExpression(
source = null,
ConstantValueKind.Int,
argument.value as Int,
setType = true
)
IrConstKind.Long -> buildConstExpression(
source = null,
ConstantValueKind.Long,
argument.value as Long,
setType = true
)
IrConstKind.Null -> buildConstExpression(
source = null,
ConstantValueKind.Null,
value = null,
setType = true
)
IrConstKind.Short -> buildConstExpression(
source = null,
ConstantValueKind.Short,
argument.value as Short,
setType = false
)
IrConstKind.String -> buildConstExpression(
source = null,
ConstantValueKind.String,
argument.value as String,
setType = false
)
}
}
}
}
}
private object GeneratedForMetadata : GeneratedDeclarationKey()
private inner class Provider : FirAdditionalMetadataProvider() { private inner class Provider : FirAdditionalMetadataProvider() {
override fun findGeneratedAnnotationsFor(declaration: FirDeclaration): List<FirAnnotation> { override fun findGeneratedAnnotationsFor(declaration: FirDeclaration): List<FirAnnotation> {
val irAnnotations = extractGeneratedIrDeclarations(declaration).takeUnless { it.isEmpty() } ?: return emptyList() val irAnnotations = extractGeneratedIrDeclarations(declaration).takeUnless { it.isEmpty() } ?: return emptyList()
@@ -111,83 +393,5 @@ class Fir2IrIrGeneratedDeclarationsRegistrar(private val components: Fir2IrCompo
private val ClassId.topmostParentClassId: ClassId private val ClassId.topmostParentClassId: ClassId
get() = parentClassId?.topmostParentClassId ?: this get() = parentClassId?.topmostParentClassId ?: this
private fun IrConstructorCall.toFirAnnotation(): FirAnnotation {
val annotationClassId = this.symbol.owner.constructedClass.classId!!
return buildAnnotation {
annotationTypeRef = annotationClassId
.toLookupTag()
.constructClassType(typeArguments = emptyArray(), isNullable = false)
.toFirResolvedTypeRef()
argumentMapping = buildAnnotationArgumentMapping {
for (i in 0 until this@toFirAnnotation.valueArgumentsCount) {
val name = this@toFirAnnotation.symbol.owner.valueParameters[i].name
val argument = this@toFirAnnotation.getValueArgument(i) as IrConst<*>
this.mapping[name] = when (argument.kind) {
IrConstKind.Boolean -> buildConstExpression(
source = null,
ConstantValueKind.Boolean,
argument.value as Boolean,
setType = true
)
IrConstKind.Byte -> buildConstExpression(
source = null,
ConstantValueKind.Byte,
argument.value as Byte,
setType = true
)
IrConstKind.Char -> buildConstExpression(
source = null,
ConstantValueKind.Char,
argument.value as Char,
setType = true
)
IrConstKind.Double -> buildConstExpression(
source = null,
ConstantValueKind.Double,
argument.value as Double,
setType = true
)
IrConstKind.Float -> buildConstExpression(
source = null,
ConstantValueKind.Float,
argument.value as Float,
setType = true
)
IrConstKind.Int -> buildConstExpression(
source = null,
ConstantValueKind.Int,
argument.value as Int,
setType = true
)
IrConstKind.Long -> buildConstExpression(
source = null,
ConstantValueKind.Long,
argument.value as Long,
setType = true
)
IrConstKind.Null -> buildConstExpression(
source = null,
ConstantValueKind.Null,
value = null,
setType = true
)
IrConstKind.Short -> buildConstExpression(
source = null,
ConstantValueKind.Short,
argument.value as Short,
setType = false
)
IrConstKind.String -> buildConstExpression(
source = null,
ConstantValueKind.String,
argument.value as String,
setType = false
)
}
}
}
}
}
} }
} }
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.backend.common.extensions package org.jetbrains.kotlin.backend.common.extensions
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
abstract class IrGeneratedDeclarationsRegistrar { abstract class IrGeneratedDeclarationsRegistrar {
@@ -14,4 +16,10 @@ abstract class IrGeneratedDeclarationsRegistrar {
fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, vararg annotations: IrConstructorCall) { fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, vararg annotations: IrConstructorCall) {
addMetadataVisibleAnnotationsToElement(declaration, annotations.toList()) addMetadataVisibleAnnotationsToElement(declaration, annotations.toList())
} }
abstract fun registerFunctionAsMetadataVisible(irFunction: IrSimpleFunction)
abstract fun registerConstructorAsMetadataVisible(irConstructor: IrConstructor)
// TODO: KT-63881
// abstract fun registerPropertyAsMetadataVisible(irProperty: IrProperty)
} }
@@ -186,5 +186,10 @@ open class IrPluginContextImpl constructor(
override fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, annotations: List<IrConstructorCall>) { override fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, annotations: List<IrConstructorCall>) {
declaration.annotations += annotations declaration.annotations += annotations
} }
override fun registerFunctionAsMetadataVisible(irFunction: IrSimpleFunction) {}
override fun registerConstructorAsMetadataVisible(irConstructor: IrConstructor) {}
} }
} }
@@ -89,7 +89,7 @@ internal fun PhaseContext.firSerializerBase(
}, },
allowErrorTypes = false, allowErrorTypes = false,
exportKDoc = shouldExportKDoc(), exportKDoc = shouldExportKDoc(),
additionalMetadataProvider = fir2IrInput?.components?.annotationsFromPluginRegistrar?.createMetadataAnnotationsProvider() additionalMetadataProvider = fir2IrInput?.components?.annotationsFromPluginRegistrar?.createAdditionalMetadataProvider()
), ),
configuration.languageVersionSettings, configuration.languageVersionSettings,
produceHeaderKlib, produceHeaderKlib,
@@ -84,6 +84,7 @@ class AllPropertiesConstructorIrGenerator(val context: IrPluginContext) : IrElem
} }
) )
) )
context.metadataDeclarationRegistrar.registerConstructorAsMetadataVisible(ctor)
} }
} }