[FIR/IR] Introduce an ability to propagate generated IR annotation to metadata
^KT-58638 Fixed
This commit is contained in:
committed by
Space Team
parent
24e07fdfe0
commit
5717b59f52
@@ -260,7 +260,8 @@ private class Fir2KlibSerializer(
|
|||||||
FirKLibSerializerExtension(
|
FirKLibSerializerExtension(
|
||||||
session, metadataVersion,
|
session, metadataVersion,
|
||||||
ConstValueProviderImpl(fir2IrActualizedResult.components),
|
ConstValueProviderImpl(fir2IrActualizedResult.components),
|
||||||
allowErrorTypes = false, exportKDoc = false
|
allowErrorTypes = false, exportKDoc = false,
|
||||||
|
fir2IrActualizedResult.components.annotationsFromPluginRegistrar.createMetadataAnnotationsProvider()
|
||||||
),
|
),
|
||||||
languageVersionSettings,
|
languageVersionSettings,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -167,7 +167,8 @@ internal class FirMetadataSerializer(
|
|||||||
actualizedExpectDeclarations = null,
|
actualizedExpectDeclarations = null,
|
||||||
FirKLibSerializerExtension(
|
FirKLibSerializerExtension(
|
||||||
session, metadataVersion, constValueProvider = null,
|
session, metadataVersion, constValueProvider = null,
|
||||||
allowErrorTypes = false, exportKDoc = false
|
allowErrorTypes = false, exportKDoc = false,
|
||||||
|
additionalAnnotationsProvider = null
|
||||||
),
|
),
|
||||||
languageVersionSettings,
|
languageVersionSettings,
|
||||||
)
|
)
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
|
||||||
|
abstract class FirAdditionalMetadataAnnotationsProvider {
|
||||||
|
abstract fun findGeneratedAnnotationsFor(declaration: FirDeclaration): List<FirAnnotation>
|
||||||
|
abstract fun hasGeneratedAnnotationsFor(declaration: FirDeclaration): Boolean
|
||||||
|
}
|
||||||
+12
-8
@@ -129,7 +129,7 @@ class FirElementSerializer private constructor(
|
|||||||
|
|
||||||
val hasEnumEntries = klass.classKind == ClassKind.ENUM_CLASS && languageVersionSettings.supportsFeature(LanguageFeature.EnumEntries)
|
val hasEnumEntries = klass.classKind == ClassKind.ENUM_CLASS && languageVersionSettings.supportsFeature(LanguageFeature.EnumEntries)
|
||||||
val flags = Flags.getClassFlags(
|
val flags = Flags.getClassFlags(
|
||||||
klass.nonSourceAnnotations(session).isNotEmpty(),
|
klass.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(klass),
|
||||||
ProtoEnumFlags.visibility(regularClass?.let { normalizeVisibility(it) } ?: Visibilities.Local),
|
ProtoEnumFlags.visibility(regularClass?.let { normalizeVisibility(it) } ?: Visibilities.Local),
|
||||||
ProtoEnumFlags.modality(modality),
|
ProtoEnumFlags.modality(modality),
|
||||||
ProtoEnumFlags.classKind(klass.classKind, regularClass?.isCompanion == true),
|
ProtoEnumFlags.classKind(klass.classKind, regularClass?.isCompanion == true),
|
||||||
@@ -377,6 +377,8 @@ class FirElementSerializer private constructor(
|
|||||||
|
|
||||||
val hasAnnotations = property.nonSourceAnnotations(session).isNotEmpty()
|
val hasAnnotations = property.nonSourceAnnotations(session).isNotEmpty()
|
||||||
|| property.backingField?.nonSourceAnnotations(session)?.isNotEmpty() == true
|
|| property.backingField?.nonSourceAnnotations(session)?.isNotEmpty() == true
|
||||||
|
|| extension.hasAdditionalAnnotations(property)
|
||||||
|
|| property.backingField?.let { extension.hasAdditionalAnnotations(it) } == true
|
||||||
|
|
||||||
val modality = property.modality!!
|
val modality = property.modality!!
|
||||||
val defaultAccessorFlags = Flags.getAccessorFlags(
|
val defaultAccessorFlags = Flags.getAccessorFlags(
|
||||||
@@ -499,7 +501,7 @@ class FirElementSerializer private constructor(
|
|||||||
val local = createChildSerializer(function)
|
val local = createChildSerializer(function)
|
||||||
|
|
||||||
val flags = Flags.getFunctionFlags(
|
val flags = Flags.getFunctionFlags(
|
||||||
function.nonSourceAnnotations(session).isNotEmpty(),
|
function.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(function),
|
||||||
ProtoEnumFlags.visibility(simpleFunction?.let { normalizeVisibility(it) } ?: Visibilities.Local),
|
ProtoEnumFlags.visibility(simpleFunction?.let { normalizeVisibility(it) } ?: Visibilities.Local),
|
||||||
ProtoEnumFlags.modality(simpleFunction?.modality ?: Modality.FINAL),
|
ProtoEnumFlags.modality(simpleFunction?.modality ?: Modality.FINAL),
|
||||||
if (function.origin == FirDeclarationOrigin.Delegated) ProtoBuf.MemberKind.DELEGATION else ProtoBuf.MemberKind.DECLARATION,
|
if (function.origin == FirDeclarationOrigin.Delegated) ProtoBuf.MemberKind.DELEGATION else ProtoBuf.MemberKind.DECLARATION,
|
||||||
@@ -603,7 +605,7 @@ class FirElementSerializer private constructor(
|
|||||||
val local = createChildSerializer(typeAlias)
|
val local = createChildSerializer(typeAlias)
|
||||||
|
|
||||||
val flags = Flags.getTypeAliasFlags(
|
val flags = Flags.getTypeAliasFlags(
|
||||||
typeAlias.nonSourceAnnotations(session).isNotEmpty(),
|
typeAlias.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(typeAlias),
|
||||||
ProtoEnumFlags.visibility(normalizeVisibility(typeAlias))
|
ProtoEnumFlags.visibility(normalizeVisibility(typeAlias))
|
||||||
)
|
)
|
||||||
if (flags != builder.flags) {
|
if (flags != builder.flags) {
|
||||||
@@ -657,7 +659,7 @@ class FirElementSerializer private constructor(
|
|||||||
val local = createChildSerializer(constructor)
|
val local = createChildSerializer(constructor)
|
||||||
|
|
||||||
val flags = Flags.getConstructorFlags(
|
val flags = Flags.getConstructorFlags(
|
||||||
constructor.nonSourceAnnotations(session).isNotEmpty(),
|
constructor.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(constructor),
|
||||||
ProtoEnumFlags.visibility(normalizeVisibility(constructor)),
|
ProtoEnumFlags.visibility(normalizeVisibility(constructor)),
|
||||||
!constructor.isPrimary,
|
!constructor.isPrimary,
|
||||||
shouldSetStableParameterNames(constructor)
|
shouldSetStableParameterNames(constructor)
|
||||||
@@ -703,7 +705,9 @@ class FirElementSerializer private constructor(
|
|||||||
function.symbol.getSingleExpectForActualOrNull(compatibleOnly = true).containsDefaultValue(index)
|
function.symbol.getSingleExpectForActualOrNull(compatibleOnly = true).containsDefaultValue(index)
|
||||||
|
|
||||||
val flags = Flags.getValueParameterFlags(
|
val flags = Flags.getValueParameterFlags(
|
||||||
additionalAnnotations.isNotEmpty() || parameter.nonSourceAnnotations(session).isNotEmpty(),
|
additionalAnnotations.isNotEmpty()
|
||||||
|
|| parameter.nonSourceAnnotations(session).isNotEmpty()
|
||||||
|
|| extension.hasAdditionalAnnotations(parameter),
|
||||||
declaresDefaultValue,
|
declaresDefaultValue,
|
||||||
parameter.isCrossinline,
|
parameter.isCrossinline,
|
||||||
parameter.isNoinline
|
parameter.isNoinline
|
||||||
@@ -1026,15 +1030,15 @@ class FirElementSerializer private constructor(
|
|||||||
private fun getAccessorFlags(accessor: FirPropertyAccessor, property: FirProperty): Int {
|
private fun getAccessorFlags(accessor: FirPropertyAccessor, property: FirProperty): Int {
|
||||||
// [FirDefaultPropertyAccessor]---a property accessor without body---can still hold other information, such as annotations,
|
// [FirDefaultPropertyAccessor]---a property accessor without body---can still hold other information, such as annotations,
|
||||||
// user-contributed visibility, and modifiers, such as `external` or `inline`.
|
// user-contributed visibility, and modifiers, such as `external` or `inline`.
|
||||||
val nonSourceAnnotations = accessor.nonSourceAnnotations(session)
|
val hasAnnotations = accessor.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(accessor)
|
||||||
val isDefault = property.isLocal ||
|
val isDefault = property.isLocal ||
|
||||||
(accessor is FirDefaultPropertyAccessor &&
|
(accessor is FirDefaultPropertyAccessor &&
|
||||||
nonSourceAnnotations.isEmpty() &&
|
!hasAnnotations &&
|
||||||
accessor.visibility == property.visibility &&
|
accessor.visibility == property.visibility &&
|
||||||
!accessor.isExternal &&
|
!accessor.isExternal &&
|
||||||
!accessor.isInline)
|
!accessor.isInline)
|
||||||
return Flags.getAccessorFlags(
|
return Flags.getAccessorFlags(
|
||||||
nonSourceAnnotations.isNotEmpty(),
|
hasAnnotations,
|
||||||
ProtoEnumFlags.visibility(normalizeVisibility(accessor)),
|
ProtoEnumFlags.visibility(normalizeVisibility(accessor)),
|
||||||
// non-default accessor modality is always final, so we check property.modality instead
|
// non-default accessor modality is always final, so we check property.modality instead
|
||||||
ProtoEnumFlags.modality(property.modality!!),
|
ProtoEnumFlags.modality(property.modality!!),
|
||||||
|
|||||||
+2
-1
@@ -29,7 +29,8 @@ class FirKLibSerializerExtension(
|
|||||||
override val metadataVersion: BinaryVersion,
|
override val metadataVersion: BinaryVersion,
|
||||||
override val constValueProvider: ConstValueProvider?,
|
override val constValueProvider: ConstValueProvider?,
|
||||||
private val allowErrorTypes: Boolean,
|
private val allowErrorTypes: Boolean,
|
||||||
private val exportKDoc: Boolean
|
private val exportKDoc: Boolean,
|
||||||
|
override val additionalAnnotationsProvider: FirAdditionalMetadataAnnotationsProvider?
|
||||||
) : FirSerializerExtensionBase(KlibMetadataSerializerProtocol) {
|
) : FirSerializerExtensionBase(KlibMetadataSerializerProtocol) {
|
||||||
override fun shouldUseTypeTable(): Boolean = true
|
override fun shouldUseTypeTable(): Boolean = true
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -27,6 +27,7 @@ abstract class FirSerializerExtension {
|
|||||||
val annotationSerializer by lazy { FirAnnotationSerializer(session, stringTable, constValueProvider) }
|
val annotationSerializer by lazy { FirAnnotationSerializer(session, stringTable, constValueProvider) }
|
||||||
|
|
||||||
protected abstract val constValueProvider: ConstValueProvider?
|
protected abstract val constValueProvider: ConstValueProvider?
|
||||||
|
protected abstract val additionalAnnotationsProvider: FirAdditionalMetadataAnnotationsProvider?
|
||||||
|
|
||||||
@OptIn(ConstValueProviderInternals::class)
|
@OptIn(ConstValueProviderInternals::class)
|
||||||
internal inline fun <T> processFile(firFile: FirFile, crossinline action: () -> T): T {
|
internal inline fun <T> processFile(firFile: FirFile, crossinline action: () -> T): T {
|
||||||
@@ -97,7 +98,16 @@ abstract class FirSerializerExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasAdditionalAnnotations(declaration: FirDeclaration): Boolean {
|
||||||
|
return additionalAnnotationsProvider?.hasGeneratedAnnotationsFor(declaration) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add usages
|
||||||
|
fun getAnnotationsGeneratedByPlugins(declaration: FirDeclaration): List<FirAnnotation> {
|
||||||
|
return additionalAnnotationsProvider?.findGeneratedAnnotationsFor(declaration) ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
open fun serializeErrorType(type: ConeErrorType, builder: ProtoBuf.Type.Builder) {
|
open fun serializeErrorType(type: ConeErrorType, builder: ProtoBuf.Type.Builder) {
|
||||||
throw IllegalStateException("Cannot serialize error type: $type")
|
error("Cannot serialize error type: $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-3
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.serialization
|
|||||||
import org.jetbrains.kotlin.constant.ConstantValue
|
import org.jetbrains.kotlin.constant.ConstantValue
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
||||||
@@ -63,7 +64,7 @@ abstract class FirSerializerExtensionBase(
|
|||||||
val fieldPropertyAnnotations = mutableListOf<FirAnnotation>()
|
val fieldPropertyAnnotations = mutableListOf<FirAnnotation>()
|
||||||
val delegatePropertyAnnotations = mutableListOf<FirAnnotation>()
|
val delegatePropertyAnnotations = mutableListOf<FirAnnotation>()
|
||||||
|
|
||||||
for (annotation in property.backingField?.nonSourceAnnotations(session).orEmpty()) {
|
for (annotation in property.backingField?.allRequiredAnnotations(session).orEmpty()) {
|
||||||
val destination = when (annotation.useSiteTarget) {
|
val destination = when (annotation.useSiteTarget) {
|
||||||
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> delegatePropertyAnnotations
|
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> delegatePropertyAnnotations
|
||||||
else -> fieldPropertyAnnotations
|
else -> fieldPropertyAnnotations
|
||||||
@@ -71,7 +72,7 @@ abstract class FirSerializerExtensionBase(
|
|||||||
destination += annotation
|
destination += annotation
|
||||||
}
|
}
|
||||||
|
|
||||||
property.nonSourceAnnotations(session).serializeAnnotations(proto, protocol.propertyAnnotation)
|
property.allRequiredAnnotations(session).serializeAnnotations(proto, protocol.propertyAnnotation)
|
||||||
fieldPropertyAnnotations.serializeAnnotations(proto, protocol.propertyBackingFieldAnnotation)
|
fieldPropertyAnnotations.serializeAnnotations(proto, protocol.propertyBackingFieldAnnotation)
|
||||||
delegatePropertyAnnotations.serializeAnnotations(proto, protocol.propertyDelegatedFieldAnnotation)
|
delegatePropertyAnnotations.serializeAnnotations(proto, protocol.propertyDelegatedFieldAnnotation)
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ abstract class FirSerializerExtensionBase(
|
|||||||
extension: GeneratedMessageLite.GeneratedExtension<MessageType, List<ProtoBuf.Annotation>>?
|
extension: GeneratedMessageLite.GeneratedExtension<MessageType, List<ProtoBuf.Annotation>>?
|
||||||
) {
|
) {
|
||||||
if (extension == null) return
|
if (extension == null) return
|
||||||
this.nonSourceAnnotations(session).serializeAnnotations(proto, extension)
|
this.allRequiredAnnotations(session).serializeAnnotations(proto, extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("Reformat")
|
@Suppress("Reformat")
|
||||||
@@ -140,4 +141,14 @@ abstract class FirSerializerExtensionBase(
|
|||||||
addExtension(extension, value)
|
addExtension(extension, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirAnnotationContainer.allRequiredAnnotations(session: FirSession): List<FirAnnotation> {
|
||||||
|
val nonSourceAnnotations = nonSourceAnnotations(session)
|
||||||
|
val additionalMetadataAnnotationsProvider = additionalAnnotationsProvider
|
||||||
|
return if (this is FirDeclaration && additionalMetadataAnnotationsProvider != null) {
|
||||||
|
nonSourceAnnotations + additionalMetadataAnnotationsProvider.findGeneratedAnnotationsFor(this)
|
||||||
|
} else {
|
||||||
|
nonSourceAnnotations
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -61,6 +61,7 @@ class FirJvmSerializerExtension(
|
|||||||
private val jvmDefaultMode: JvmDefaultMode,
|
private val jvmDefaultMode: JvmDefaultMode,
|
||||||
override val stringTable: FirElementAwareStringTable,
|
override val stringTable: FirElementAwareStringTable,
|
||||||
override val constValueProvider: ConstValueProvider?,
|
override val constValueProvider: ConstValueProvider?,
|
||||||
|
override val additionalAnnotationsProvider: FirAdditionalMetadataAnnotationsProvider?,
|
||||||
) : FirSerializerExtension() {
|
) : FirSerializerExtension() {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -77,6 +78,7 @@ class FirJvmSerializerExtension(
|
|||||||
state.globalSerializationBindings, state.useTypeTableInSerializer, state.moduleName, state.classBuilderMode,
|
state.globalSerializationBindings, state.useTypeTableInSerializer, state.moduleName, state.classBuilderMode,
|
||||||
state.isParamAssertionsDisabled, state.unifiedNullChecks, state.metadataVersion, state.jvmDefaultMode,
|
state.isParamAssertionsDisabled, state.unifiedNullChecks, state.metadataVersion, state.jvmDefaultMode,
|
||||||
FirJvmElementAwareStringTable(typeMapper, components), ConstValueProviderImpl(components),
|
FirJvmElementAwareStringTable(typeMapper, components), ConstValueProviderImpl(components),
|
||||||
|
components.annotationsFromPluginRegistrar.createMetadataAnnotationsProvider()
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun shouldUseTypeTable(): Boolean = useTypeTable
|
override fun shouldUseTypeTable(): Boolean = useTypeTable
|
||||||
|
|||||||
+2
-1
@@ -104,7 +104,8 @@ fun makeLocalFirMetadataSerializerForMetadataSource(
|
|||||||
configuration.metadataVersion(session.languageVersionSettings.languageVersion),
|
configuration.metadataVersion(session.languageVersionSettings.languageVersion),
|
||||||
session.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode),
|
session.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode),
|
||||||
stringTable,
|
stringTable,
|
||||||
constValueProvider = null
|
constValueProvider = null,
|
||||||
|
additionalAnnotationsProvider = null
|
||||||
)
|
)
|
||||||
return FirMetadataSerializer(
|
return FirMetadataSerializer(
|
||||||
globalSerializationBindings,
|
globalSerializationBindings,
|
||||||
|
|||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.backend
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.extensions.IrAnnotationsFromPluginRegistrar
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyAnnotationArgumentMapping
|
||||||
|
import org.jetbrains.kotlin.fir.packageFqName
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.serialization.FirAdditionalMetadataAnnotationsProvider
|
||||||
|
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||||
|
import org.jetbrains.kotlin.fir.types.toFirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.toLookupTag
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.nameWithPackage
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
|
class Fir2IrAnnotationsFromPluginRegistrar(private val components: Fir2IrComponents) : IrAnnotationsFromPluginRegistrar() {
|
||||||
|
private val generatedIrDeclarationsByFileByOffset = mutableMapOf<String, MutableMap<Pair<Int, Int>, MutableList<IrConstructorCall>>>()
|
||||||
|
|
||||||
|
override fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, annotations: List<IrConstructorCall>) {
|
||||||
|
require(annotations.all { it.valueArgumentsCount == 0 && it.typeArgumentsCount == 0 }) {
|
||||||
|
"Saving annotations with arguments from IR to metadata is not supported yet. See KT-58968"
|
||||||
|
}
|
||||||
|
annotations.forEach {
|
||||||
|
require(it.symbol.owner.constructedClass.isAnnotationClass) { "${it.render()} is not an annotation constructor call" }
|
||||||
|
}
|
||||||
|
val fileFqName = declaration.file.nameWithPackage
|
||||||
|
val fileStorage = generatedIrDeclarationsByFileByOffset.getOrPut(fileFqName) { mutableMapOf() }
|
||||||
|
val storage = fileStorage.getOrPut(declaration.startOffset to declaration.endOffset) { mutableListOf() }
|
||||||
|
storage += annotations
|
||||||
|
declaration.annotations += annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createMetadataAnnotationsProvider(): FirAdditionalMetadataAnnotationsProvider {
|
||||||
|
return Provider()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class Provider : FirAdditionalMetadataAnnotationsProvider() {
|
||||||
|
private val session = components.session
|
||||||
|
|
||||||
|
override fun findGeneratedAnnotationsFor(declaration: FirDeclaration): List<FirAnnotation> {
|
||||||
|
val irAnnotations = extractGeneratedIrDeclarations(declaration).takeUnless { it.isEmpty() } ?: return emptyList()
|
||||||
|
return irAnnotations.map { it.toFirAnnotation() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasGeneratedAnnotationsFor(declaration: FirDeclaration): Boolean {
|
||||||
|
return extractGeneratedIrDeclarations(declaration).isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractGeneratedIrDeclarations(declaration: FirDeclaration): List<IrConstructorCall> {
|
||||||
|
val firFile = declaration.containingFile() ?: return emptyList()
|
||||||
|
val fileFqName = firFile.packageFqName.child(Name.identifier(firFile.name)).asString()
|
||||||
|
val source = declaration.source ?: return emptyList()
|
||||||
|
val fileStorage = generatedIrDeclarationsByFileByOffset[fileFqName] ?: return emptyList()
|
||||||
|
return fileStorage[source.startOffset to source.endOffset] ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirDeclaration.containingFile(): FirFile? {
|
||||||
|
if (this is FirFile) return this
|
||||||
|
val topmostParent = topmostParent()
|
||||||
|
return components.session.firProvider.getContainingFile(topmostParent.symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirDeclaration.topmostParent(): FirDeclaration {
|
||||||
|
return when (this) {
|
||||||
|
is FirClassLikeDeclaration -> runIf(!classId.isLocal) { classId.topmostParentClassId.toSymbol(session)?.fir }
|
||||||
|
is FirTypeParameter -> containingDeclarationSymbol.fir.topmostParent()
|
||||||
|
is FirValueParameter -> containingFunctionSymbol.fir.topmostParent()
|
||||||
|
is FirCallableDeclaration -> symbol.callableId.classId
|
||||||
|
?.takeIf { !it.isLocal }
|
||||||
|
?.topmostParentClassId
|
||||||
|
?.toSymbol(session)
|
||||||
|
?.fir
|
||||||
|
else -> error("Unsupported declaration type: $this")
|
||||||
|
} ?: this
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ClassId.topmostParentClassId: ClassId
|
||||||
|
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 = FirEmptyAnnotationArgumentMapping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,4 +43,6 @@ interface Fir2IrComponents {
|
|||||||
|
|
||||||
val extensions: Fir2IrExtensions
|
val extensions: Fir2IrExtensions
|
||||||
val configuration: Fir2IrConfiguration
|
val configuration: Fir2IrConfiguration
|
||||||
|
|
||||||
|
val annotationsFromPluginRegistrar: Fir2IrAnnotationsFromPluginRegistrar
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ class Fir2IrComponentsStorage(
|
|||||||
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
|
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
|
||||||
override lateinit var delegatedMemberGenerator: DelegatedMemberGenerator
|
override lateinit var delegatedMemberGenerator: DelegatedMemberGenerator
|
||||||
|
|
||||||
|
override lateinit var annotationsFromPluginRegistrar: Fir2IrAnnotationsFromPluginRegistrar
|
||||||
|
|
||||||
override val lock: IrLock
|
override val lock: IrLock
|
||||||
get() = symbolTable.lock
|
get() = symbolTable.lock
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -481,6 +481,7 @@ class Fir2IrConverter(
|
|||||||
components.fakeOverrideGenerator = FakeOverrideGenerator(components, conversionScope)
|
components.fakeOverrideGenerator = FakeOverrideGenerator(components, conversionScope)
|
||||||
components.callGenerator = CallAndReferenceGenerator(components, fir2irVisitor, conversionScope)
|
components.callGenerator = CallAndReferenceGenerator(components, fir2irVisitor, conversionScope)
|
||||||
components.irProviders = listOf(FirIrProvider(components))
|
components.irProviders = listOf(FirIrProvider(components))
|
||||||
|
components.annotationsFromPluginRegistrar = Fir2IrAnnotationsFromPluginRegistrar(components)
|
||||||
|
|
||||||
fir2IrExtensions.registerDeclarations(commonMemberStorage.symbolTable)
|
fir2IrExtensions.registerDeclarations(commonMemberStorage.symbolTable)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.backend
|
package org.jetbrains.kotlin.fir.backend
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
|
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
|
||||||
|
import org.jetbrains.kotlin.backend.common.extensions.IrAnnotationsFromPluginRegistrar
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
|
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
@@ -72,6 +73,9 @@ class Fir2IrPluginContext(
|
|||||||
private val symbolProvider: FirSymbolProvider
|
private val symbolProvider: FirSymbolProvider
|
||||||
get() = components.session.symbolProvider
|
get() = components.session.symbolProvider
|
||||||
|
|
||||||
|
override val annotationsRegistrar: Fir2IrAnnotationsFromPluginRegistrar
|
||||||
|
get() = components.annotationsFromPluginRegistrar
|
||||||
|
|
||||||
override fun referenceClass(classId: ClassId): IrClassSymbol? {
|
override fun referenceClass(classId: ClassId): IrClassSymbol? {
|
||||||
val firSymbol = symbolProvider.getClassLikeSymbolByClassId(classId) as? FirClassSymbol<*> ?: return null
|
val firSymbol = symbolProvider.getClassLikeSymbolByClassId(classId) as? FirClassSymbol<*> ?: return null
|
||||||
return components.classifierStorage.getIrClassSymbol(firSymbol)
|
return components.classifierStorage.getIrClassSymbol(firSymbol)
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.extensions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
|
||||||
|
abstract class IrAnnotationsFromPluginRegistrar {
|
||||||
|
abstract fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, annotations: List<IrConstructorCall>)
|
||||||
|
|
||||||
|
fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, vararg annotations: IrConstructorCall) {
|
||||||
|
addMetadataVisibleAnnotationsToElement(declaration, annotations.toList())
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -56,6 +56,12 @@ interface IrPluginContext : IrGeneratorContext {
|
|||||||
|
|
||||||
val platform: TargetPlatform?
|
val platform: TargetPlatform?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this service to add annotations to declarations if those annotations should be saved into metadata
|
||||||
|
* This service properly works only in K2 compiler
|
||||||
|
*/
|
||||||
|
val annotationsRegistrar: IrAnnotationsFromPluginRegistrar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a logger instance to post diagnostic messages from plugin
|
* Returns a logger instance to post diagnostic messages from plugin
|
||||||
*
|
*
|
||||||
|
|||||||
+11
-1
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
@@ -51,6 +53,9 @@ open class IrPluginContextImpl constructor(
|
|||||||
|
|
||||||
override val symbolTable: ReferenceSymbolTable = st
|
override val symbolTable: ReferenceSymbolTable = st
|
||||||
|
|
||||||
|
final override val annotationsRegistrar: IrAnnotationsFromPluginRegistrar
|
||||||
|
get() = DummyIrAnnotationsFromPluginRegistrar
|
||||||
|
|
||||||
private fun resolveMemberScope(fqName: FqName): MemberScope? {
|
private fun resolveMemberScope(fqName: FqName): MemberScope? {
|
||||||
val pkg = module.getPackage(fqName)
|
val pkg = module.getPackage(fqName)
|
||||||
|
|
||||||
@@ -124,7 +129,6 @@ open class IrPluginContextImpl constructor(
|
|||||||
|
|
||||||
@OptIn(FirIncompatiblePluginAPI::class)
|
@OptIn(FirIncompatiblePluginAPI::class)
|
||||||
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
|
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
|
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
|
||||||
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
|
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
|
||||||
}
|
}
|
||||||
@@ -176,4 +180,10 @@ open class IrPluginContextImpl constructor(
|
|||||||
linker.postProcess(inOrAfterLinkageStep = false)
|
linker.postProcess(inOrAfterLinkageStep = false)
|
||||||
return symbol
|
return symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object DummyIrAnnotationsFromPluginRegistrar : IrAnnotationsFromPluginRegistrar() {
|
||||||
|
override fun addMetadataVisibleAnnotationsToElement(declaration: IrDeclaration, annotations: List<IrConstructorCall>) {
|
||||||
|
declaration.annotations += annotations
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -146,7 +146,8 @@ class Fir2IrJsResultsConverter(
|
|||||||
FirKLibSerializerExtension(
|
FirKLibSerializerExtension(
|
||||||
components.session, metadataVersion,
|
components.session, metadataVersion,
|
||||||
ConstValueProviderImpl(components),
|
ConstValueProviderImpl(components),
|
||||||
allowErrorTypes = false, exportKDoc = false
|
allowErrorTypes = false, exportKDoc = false,
|
||||||
|
components.annotationsFromPluginRegistrar.createMetadataAnnotationsProvider()
|
||||||
),
|
),
|
||||||
configuration.languageVersionSettings,
|
configuration.languageVersionSettings,
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-1
@@ -85,7 +85,9 @@ internal fun PhaseContext.firSerializerBase(
|
|||||||
fir2IrInput?.let {
|
fir2IrInput?.let {
|
||||||
ConstValueProviderImpl(fir2IrInput.components)
|
ConstValueProviderImpl(fir2IrInput.components)
|
||||||
},
|
},
|
||||||
allowErrorTypes = false, exportKDoc = shouldExportKDoc()
|
allowErrorTypes = false,
|
||||||
|
exportKDoc = shouldExportKDoc(),
|
||||||
|
additionalAnnotationsProvider = fir2IrInput?.components?.annotationsFromPluginRegistrar?.createMetadataAnnotationsProvider()
|
||||||
),
|
),
|
||||||
configuration.languageVersionSettings,
|
configuration.languageVersionSettings,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ class TransformerForAddingAnnotations(val context: IrPluginContext) : IrElementV
|
|||||||
type = annotationClass.defaultType,
|
type = annotationClass.defaultType,
|
||||||
constructorSymbol = annotationConstructor.symbol
|
constructorSymbol = annotationConstructor.symbol
|
||||||
)
|
)
|
||||||
declaration.annotations += annotationCall
|
context.annotationsRegistrar.addMetadataVisibleAnnotationsToElement(declaration, annotationCall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -1,13 +1,13 @@
|
|||||||
@R|org/jetbrains/kotlin/fir/plugin/AddAnnotations|() public final class Some : R|kotlin/Any| {
|
@R|org/jetbrains/kotlin/fir/plugin/AddAnnotations|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public final class Some : R|kotlin/Any| {
|
||||||
public final fun foo(): R|kotlin/Unit|
|
@R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public final fun foo(): R|kotlin/Unit|
|
||||||
|
|
||||||
public final val x: R|kotlin/Int|
|
@PROPERTY:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public final val x: R|kotlin/Int|
|
||||||
public get(): R|kotlin/Int|
|
@PROPERTY_GETTER:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY_GETTER:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY_GETTER:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY_GETTER:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @PROPERTY_GETTER:R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public get(): R|kotlin/Int|
|
||||||
|
|
||||||
public constructor(x: R|kotlin/Int|): R|test/Some|
|
@R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public constructor(@R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() x: R|kotlin/Int|): R|test/Some|
|
||||||
|
|
||||||
public final class Derived : R|kotlin/Any| {
|
@R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public final class Derived : R|kotlin/Any| {
|
||||||
public constructor(): R|test/Some.Derived|
|
@R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() @R|org/jetbrains/kotlin/fir/plugin/AnnotationToAdd|() public constructor(): R|test/Some.Derived|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user