[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
+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 flags = Flags.getClassFlags(
|
||||
klass.nonSourceAnnotations(session).isNotEmpty(),
|
||||
klass.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(klass),
|
||||
ProtoEnumFlags.visibility(regularClass?.let { normalizeVisibility(it) } ?: Visibilities.Local),
|
||||
ProtoEnumFlags.modality(modality),
|
||||
ProtoEnumFlags.classKind(klass.classKind, regularClass?.isCompanion == true),
|
||||
@@ -377,6 +377,8 @@ class FirElementSerializer private constructor(
|
||||
|
||||
val hasAnnotations = property.nonSourceAnnotations(session).isNotEmpty()
|
||||
|| property.backingField?.nonSourceAnnotations(session)?.isNotEmpty() == true
|
||||
|| extension.hasAdditionalAnnotations(property)
|
||||
|| property.backingField?.let { extension.hasAdditionalAnnotations(it) } == true
|
||||
|
||||
val modality = property.modality!!
|
||||
val defaultAccessorFlags = Flags.getAccessorFlags(
|
||||
@@ -499,7 +501,7 @@ class FirElementSerializer private constructor(
|
||||
val local = createChildSerializer(function)
|
||||
|
||||
val flags = Flags.getFunctionFlags(
|
||||
function.nonSourceAnnotations(session).isNotEmpty(),
|
||||
function.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(function),
|
||||
ProtoEnumFlags.visibility(simpleFunction?.let { normalizeVisibility(it) } ?: Visibilities.Local),
|
||||
ProtoEnumFlags.modality(simpleFunction?.modality ?: Modality.FINAL),
|
||||
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 flags = Flags.getTypeAliasFlags(
|
||||
typeAlias.nonSourceAnnotations(session).isNotEmpty(),
|
||||
typeAlias.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(typeAlias),
|
||||
ProtoEnumFlags.visibility(normalizeVisibility(typeAlias))
|
||||
)
|
||||
if (flags != builder.flags) {
|
||||
@@ -657,7 +659,7 @@ class FirElementSerializer private constructor(
|
||||
val local = createChildSerializer(constructor)
|
||||
|
||||
val flags = Flags.getConstructorFlags(
|
||||
constructor.nonSourceAnnotations(session).isNotEmpty(),
|
||||
constructor.nonSourceAnnotations(session).isNotEmpty() || extension.hasAdditionalAnnotations(constructor),
|
||||
ProtoEnumFlags.visibility(normalizeVisibility(constructor)),
|
||||
!constructor.isPrimary,
|
||||
shouldSetStableParameterNames(constructor)
|
||||
@@ -703,7 +705,9 @@ class FirElementSerializer private constructor(
|
||||
function.symbol.getSingleExpectForActualOrNull(compatibleOnly = true).containsDefaultValue(index)
|
||||
|
||||
val flags = Flags.getValueParameterFlags(
|
||||
additionalAnnotations.isNotEmpty() || parameter.nonSourceAnnotations(session).isNotEmpty(),
|
||||
additionalAnnotations.isNotEmpty()
|
||||
|| parameter.nonSourceAnnotations(session).isNotEmpty()
|
||||
|| extension.hasAdditionalAnnotations(parameter),
|
||||
declaresDefaultValue,
|
||||
parameter.isCrossinline,
|
||||
parameter.isNoinline
|
||||
@@ -1026,15 +1030,15 @@ class FirElementSerializer private constructor(
|
||||
private fun getAccessorFlags(accessor: FirPropertyAccessor, property: FirProperty): Int {
|
||||
// [FirDefaultPropertyAccessor]---a property accessor without body---can still hold other information, such as annotations,
|
||||
// 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 ||
|
||||
(accessor is FirDefaultPropertyAccessor &&
|
||||
nonSourceAnnotations.isEmpty() &&
|
||||
!hasAnnotations &&
|
||||
accessor.visibility == property.visibility &&
|
||||
!accessor.isExternal &&
|
||||
!accessor.isInline)
|
||||
return Flags.getAccessorFlags(
|
||||
nonSourceAnnotations.isNotEmpty(),
|
||||
hasAnnotations,
|
||||
ProtoEnumFlags.visibility(normalizeVisibility(accessor)),
|
||||
// non-default accessor modality is always final, so we check property.modality instead
|
||||
ProtoEnumFlags.modality(property.modality!!),
|
||||
|
||||
+2
-1
@@ -29,7 +29,8 @@ class FirKLibSerializerExtension(
|
||||
override val metadataVersion: BinaryVersion,
|
||||
override val constValueProvider: ConstValueProvider?,
|
||||
private val allowErrorTypes: Boolean,
|
||||
private val exportKDoc: Boolean
|
||||
private val exportKDoc: Boolean,
|
||||
override val additionalAnnotationsProvider: FirAdditionalMetadataAnnotationsProvider?
|
||||
) : FirSerializerExtensionBase(KlibMetadataSerializerProtocol) {
|
||||
override fun shouldUseTypeTable(): Boolean = true
|
||||
|
||||
|
||||
+11
-1
@@ -27,6 +27,7 @@ abstract class FirSerializerExtension {
|
||||
val annotationSerializer by lazy { FirAnnotationSerializer(session, stringTable, constValueProvider) }
|
||||
|
||||
protected abstract val constValueProvider: ConstValueProvider?
|
||||
protected abstract val additionalAnnotationsProvider: FirAdditionalMetadataAnnotationsProvider?
|
||||
|
||||
@OptIn(ConstValueProviderInternals::class)
|
||||
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) {
|
||||
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.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
||||
@@ -63,7 +64,7 @@ abstract class FirSerializerExtensionBase(
|
||||
val fieldPropertyAnnotations = 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) {
|
||||
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> delegatePropertyAnnotations
|
||||
else -> fieldPropertyAnnotations
|
||||
@@ -71,7 +72,7 @@ abstract class FirSerializerExtensionBase(
|
||||
destination += annotation
|
||||
}
|
||||
|
||||
property.nonSourceAnnotations(session).serializeAnnotations(proto, protocol.propertyAnnotation)
|
||||
property.allRequiredAnnotations(session).serializeAnnotations(proto, protocol.propertyAnnotation)
|
||||
fieldPropertyAnnotations.serializeAnnotations(proto, protocol.propertyBackingFieldAnnotation)
|
||||
delegatePropertyAnnotations.serializeAnnotations(proto, protocol.propertyDelegatedFieldAnnotation)
|
||||
|
||||
@@ -110,7 +111,7 @@ abstract class FirSerializerExtensionBase(
|
||||
extension: GeneratedMessageLite.GeneratedExtension<MessageType, List<ProtoBuf.Annotation>>?
|
||||
) {
|
||||
if (extension == null) return
|
||||
this.nonSourceAnnotations(session).serializeAnnotations(proto, extension)
|
||||
this.allRequiredAnnotations(session).serializeAnnotations(proto, extension)
|
||||
}
|
||||
|
||||
@Suppress("Reformat")
|
||||
@@ -140,4 +141,14 @@ abstract class FirSerializerExtensionBase(
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user