diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt
index fdffe8b653e..4ce2cbd48eb 100644
--- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt
+++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt
@@ -8,17 +8,12 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.SpecialJvmAnnotations
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.descriptors.SourceElement
-import org.jetbrains.kotlin.load.java.JvmAbi
+import org.jetbrains.kotlin.load.kotlin.AbstractBinaryClassAnnotationAndConstantLoader.AnnotationsContainerWithConstants
import org.jetbrains.kotlin.metadata.ProtoBuf
-import org.jetbrains.kotlin.metadata.deserialization.*
-import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
-import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf.propertySignature
-import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite
+import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId
-import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
@@ -29,192 +24,27 @@ import org.jetbrains.kotlin.types.KotlinType
abstract class AbstractBinaryClassAnnotationAndConstantLoader(
storageManager: StorageManager,
- protected val kotlinClassFinder: KotlinClassFinder
-) : AnnotationAndConstantLoader {
- private val storage = storageManager.createMemoizedFunction> { kotlinClass ->
- loadAnnotationsAndInitializers(kotlinClass)
- }
+ kotlinClassFinder: KotlinClassFinder
+) : AnnotationAndConstantLoader,
+ AbstractBinaryClassAnnotationLoader>(kotlinClassFinder) {
+
+ private val storage =
+ storageManager.createMemoizedFunction> { kotlinClass ->
+ loadAnnotationsAndInitializers(kotlinClass)
+ }
+
+ override fun getAnnotationsContainer(binaryClass: KotlinJvmBinaryClass): AnnotationsContainerWithConstants = storage(binaryClass)
protected abstract fun loadConstant(desc: String, initializer: Any): C?
protected abstract fun transformToUnsignedConstant(constant: C): C?
- protected abstract fun loadAnnotation(
- annotationClassId: ClassId,
- source: SourceElement,
- result: MutableList
- ): KotlinJvmBinaryClass.AnnotationArgumentVisitor?
-
- protected abstract fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): A
-
protected abstract fun loadAnnotationMethodDefaultValue(
annotationClass: KotlinJvmBinaryClass,
methodSignature: MemberSignature,
visitResult: (C) -> Unit
): KotlinJvmBinaryClass.AnnotationArgumentVisitor?
- private fun loadAnnotationIfNotSpecial(
- annotationClassId: ClassId,
- source: SourceElement,
- result: MutableList
- ): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
- if (annotationClassId in SpecialJvmAnnotations.SPECIAL_ANNOTATIONS) return null
-
- return loadAnnotation(annotationClassId, source, result)
- }
-
- private fun ProtoContainer.Class.toBinaryClass(): KotlinJvmBinaryClass? =
- (source as? KotlinJvmBinarySourceElement)?.binaryClass
-
- protected open fun getCachedFileContent(kotlinClass: KotlinJvmBinaryClass): ByteArray? = null
-
- override fun loadClassAnnotations(container: ProtoContainer.Class): List {
- val kotlinClass = container.toBinaryClass() ?: error("Class for loading annotations is not found: ${container.debugFqName()}")
-
- val result = ArrayList(1)
-
- kotlinClass.loadClassAnnotations(object : KotlinJvmBinaryClass.AnnotationVisitor {
- override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
- return loadAnnotationIfNotSpecial(classId, source, result)
- }
-
- override fun visitEnd() {
- }
- }, getCachedFileContent(kotlinClass))
-
- return result
- }
-
- override fun loadCallableAnnotations(container: ProtoContainer, proto: MessageLite, kind: AnnotatedCallableKind): List {
- if (kind == AnnotatedCallableKind.PROPERTY) {
- return loadPropertyAnnotations(container, proto as ProtoBuf.Property, PropertyRelatedElement.PROPERTY)
- }
-
- val signature = getCallableSignature(proto, container.nameResolver, container.typeTable, kind) ?: return emptyList()
- return findClassAndLoadMemberAnnotations(container, signature)
- }
-
- override fun loadPropertyBackingFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List =
- loadPropertyAnnotations(container, proto, PropertyRelatedElement.BACKING_FIELD)
-
- override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List =
- loadPropertyAnnotations(container, proto, PropertyRelatedElement.DELEGATE_FIELD)
-
- private enum class PropertyRelatedElement {
- PROPERTY,
- BACKING_FIELD,
- DELEGATE_FIELD,
- }
-
- private fun loadPropertyAnnotations(container: ProtoContainer, proto: ProtoBuf.Property, element: PropertyRelatedElement): List {
- val isConst = Flags.IS_CONST.get(proto.flags)
- val isMovedFromInterfaceCompanion = JvmProtoBufUtil.isMovedFromInterfaceCompanion(proto)
- if (element == PropertyRelatedElement.PROPERTY) {
- val syntheticFunctionSignature =
- getPropertySignature(proto, container.nameResolver, container.typeTable, synthetic = true) ?: return emptyList()
- return findClassAndLoadMemberAnnotations(
- container, syntheticFunctionSignature, property = true, isConst = isConst,
- isMovedFromInterfaceCompanion = isMovedFromInterfaceCompanion
- )
- }
-
- val fieldSignature =
- getPropertySignature(proto, container.nameResolver, container.typeTable, field = true) ?: return emptyList()
-
- // TODO: check delegate presence in some other way
- val isDelegated = JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX in fieldSignature.signature
- if (isDelegated != (element == PropertyRelatedElement.DELEGATE_FIELD)) return emptyList()
-
- return findClassAndLoadMemberAnnotations(
- container, fieldSignature, property = true, field = true, isConst = isConst,
- isMovedFromInterfaceCompanion = isMovedFromInterfaceCompanion
- )
- }
-
- override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List {
- val signature = MemberSignature.fromFieldNameAndDesc(
- container.nameResolver.getString(proto.name),
- ClassMapperLite.mapClass((container as ProtoContainer.Class).classId.asString())
- )
- return findClassAndLoadMemberAnnotations(container, signature)
- }
-
- private fun findClassAndLoadMemberAnnotations(
- container: ProtoContainer,
- signature: MemberSignature,
- property: Boolean = false,
- field: Boolean = false,
- isConst: Boolean? = null,
- isMovedFromInterfaceCompanion: Boolean = false
- ): List {
- val kotlinClass =
- findClassWithAnnotationsAndInitializers(
- container,
- getSpecialCaseContainerClass(
- container,
- property,
- field,
- isConst,
- isMovedFromInterfaceCompanion
- )
- )
- ?: return listOf()
-
- return storage(kotlinClass).memberAnnotations[signature] ?: listOf()
- }
-
- override fun loadValueParameterAnnotations(
- container: ProtoContainer,
- callableProto: MessageLite,
- kind: AnnotatedCallableKind,
- parameterIndex: Int,
- proto: ProtoBuf.ValueParameter
- ): List {
- val methodSignature = getCallableSignature(callableProto, container.nameResolver, container.typeTable, kind)
- if (methodSignature != null) {
- val index = parameterIndex + computeJvmParameterIndexShift(container, callableProto)
- val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, index)
- return findClassAndLoadMemberAnnotations(container, paramSignature)
- }
-
- return listOf()
- }
-
- private fun computeJvmParameterIndexShift(container: ProtoContainer, message: MessageLite): Int {
- return when (message) {
- is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0
- is ProtoBuf.Property -> if (message.hasReceiver()) 1 else 0
- is ProtoBuf.Constructor -> when {
- (container as ProtoContainer.Class).kind == ProtoBuf.Class.Kind.ENUM_CLASS -> 2
- container.isInner -> 1
- else -> 0
- }
- else -> throw UnsupportedOperationException("Unsupported message: ${message::class.java}")
- }
- }
-
- override fun loadExtensionReceiverParameterAnnotations(
- container: ProtoContainer,
- proto: MessageLite,
- kind: AnnotatedCallableKind
- ): List {
- val methodSignature = getCallableSignature(proto, container.nameResolver, container.typeTable, kind)
- if (methodSignature != null) {
- val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, 0)
- return findClassAndLoadMemberAnnotations(container, paramSignature)
- }
-
- return emptyList()
- }
-
- override fun loadTypeAnnotations(proto: ProtoBuf.Type, nameResolver: NameResolver): List {
- return proto.getExtension(JvmProtoBuf.typeAnnotation).map { loadTypeAnnotation(it, nameResolver) }
- }
-
- override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List {
- return proto.getExtension(JvmProtoBuf.typeParameterAnnotation).map { loadTypeAnnotation(it, nameResolver) }
- }
-
override fun loadAnnotationDefaultValue(
container: ProtoContainer,
proto: ProtoBuf.Property,
@@ -237,7 +67,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader(
proto: ProtoBuf.Property,
annotatedCallableKind: AnnotatedCallableKind,
expectedType: KotlinType,
- loader: Storage.(MemberSignature) -> C?
+ loader: AnnotationsContainerWithConstants.(MemberSignature) -> C?
): C? {
val specialCase = getSpecialCaseContainerClass(
container,
@@ -260,63 +90,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader(
return if (UnsignedTypes.isUnsignedType(expectedType)) transformToUnsignedConstant(result) else result
}
- private fun findClassWithAnnotationsAndInitializers(
- container: ProtoContainer, specialCase: KotlinJvmBinaryClass?
- ): KotlinJvmBinaryClass? {
- return when {
- specialCase != null -> specialCase
- container is ProtoContainer.Class -> container.toBinaryClass()
- else -> null
- }
- }
-
- // TODO: do not use KotlinClassFinder#findKotlinClass here because it traverses the file system in the compiler
- // Introduce an API in KotlinJvmBinaryClass to find a class nearby instead
- private fun getSpecialCaseContainerClass(
- container: ProtoContainer,
- property: Boolean,
- field: Boolean,
- isConst: Boolean?,
- isMovedFromInterfaceCompanion: Boolean
- ): KotlinJvmBinaryClass? {
- if (property) {
- checkNotNull(isConst) { "isConst should not be null for property (container=$container)" }
- if (container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.INTERFACE) {
- return kotlinClassFinder.findKotlinClass(
- container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
- )
- }
- if (isConst && container is ProtoContainer.Package) {
- // Const properties in multifile classes are generated into the facade class
- val facadeClassName = (container.source as? JvmPackagePartSource)?.facadeClassName
- if (facadeClassName != null) {
- // Converting '/' to '.' is fine here because the facade class has a top level ClassId
- return kotlinClassFinder.findKotlinClass(ClassId.topLevel(FqName(facadeClassName.internalName.replace('/', '.'))))
- }
- }
- }
- if (field && container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
- val outerClass = container.outerClass
- if (outerClass != null &&
- (outerClass.kind == ProtoBuf.Class.Kind.CLASS || outerClass.kind == ProtoBuf.Class.Kind.ENUM_CLASS ||
- (isMovedFromInterfaceCompanion &&
- (outerClass.kind == ProtoBuf.Class.Kind.INTERFACE ||
- outerClass.kind == ProtoBuf.Class.Kind.ANNOTATION_CLASS)))
- ) {
- // Backing fields of properties of a companion object in a class are generated in the outer class
- return outerClass.toBinaryClass()
- }
- }
- if (container is ProtoContainer.Package && container.source is JvmPackagePartSource) {
- val jvmPackagePartSource = container.source as JvmPackagePartSource
-
- return jvmPackagePartSource.knownJvmBinaryClass
- ?: kotlinClassFinder.findKotlinClass(jvmPackagePartSource.classId)
- }
- return null
- }
-
- private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): Storage {
+ private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): AnnotationsContainerWithConstants {
val memberAnnotations = HashMap>()
val propertyConstants = HashMap()
val annotationParametersDefaultValues = HashMap()
@@ -375,61 +149,9 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader(
}
}, getCachedFileContent(kotlinClass))
- return Storage(memberAnnotations, propertyConstants, annotationParametersDefaultValues)
+ return AnnotationsContainerWithConstants(memberAnnotations, propertyConstants, annotationParametersDefaultValues)
}
- private fun getPropertySignature(
- proto: ProtoBuf.Property,
- nameResolver: NameResolver,
- typeTable: TypeTable,
- field: Boolean = false,
- synthetic: Boolean = false,
- requireHasFieldFlagForField: Boolean = true
- ): MemberSignature? {
- val signature = proto.getExtensionOrNull(propertySignature) ?: return null
-
- if (field) {
- val fieldSignature =
- JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable, requireHasFieldFlagForField) ?: return null
- return MemberSignature.fromJvmMemberSignature(fieldSignature)
- } else if (synthetic && signature.hasSyntheticMethod()) {
- return MemberSignature.fromMethod(nameResolver, signature.syntheticMethod)
- }
-
- return null
- }
-
- private fun getCallableSignature(
- proto: MessageLite,
- nameResolver: NameResolver,
- typeTable: TypeTable,
- kind: AnnotatedCallableKind,
- requireHasFieldFlagForField: Boolean = false
- ): MemberSignature? {
- return when (proto) {
- is ProtoBuf.Constructor -> {
- MemberSignature.fromJvmMemberSignature(
- JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable) ?: return null
- )
- }
- is ProtoBuf.Function -> {
- MemberSignature.fromJvmMemberSignature(JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable) ?: return null)
- }
- is ProtoBuf.Property -> {
- val signature = proto.getExtensionOrNull(propertySignature) ?: return null
- when (kind) {
- AnnotatedCallableKind.PROPERTY_GETTER ->
- if (signature.hasGetter()) MemberSignature.fromMethod(nameResolver, signature.getter) else null
- AnnotatedCallableKind.PROPERTY_SETTER ->
- if (signature.hasSetter()) MemberSignature.fromMethod(nameResolver, signature.setter) else null
- AnnotatedCallableKind.PROPERTY ->
- getPropertySignature(proto, nameResolver, typeTable, true, true, requireHasFieldFlagForField)
- else -> null
- }
- }
- else -> null
- }
- }
protected fun isRepeatableWithImplicitContainer(annotationClassId: ClassId, arguments: Map>): Boolean {
if (annotationClassId != SpecialJvmAnnotations.JAVA_LANG_ANNOTATION_REPEATABLE) return false
@@ -439,18 +161,10 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader(
return isImplicitRepeatableContainer(normalClass.classId)
}
- protected fun isImplicitRepeatableContainer(classId: ClassId): Boolean {
- if (classId.outerClassId == null ||
- classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME
- ) return false
-
- val klass = kotlinClassFinder.findKotlinClass(classId)
- return klass != null && SpecialJvmAnnotations.isAnnotatedWithContainerMetaAnnotation(klass)
- }
-
- private class Storage(
- val memberAnnotations: Map>,
+ class AnnotationsContainerWithConstants(
+ override val memberAnnotations: Map>,
val propertyConstants: Map,
val annotationParametersDefaultValues: Map
- )
+ ) : AbstractBinaryClassAnnotationLoader.AnnotationsContainer()
}
+
diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt
new file mode 100644
index 00000000000..297489c6ca0
--- /dev/null
+++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2010-2021 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.load.kotlin
+
+import org.jetbrains.kotlin.SpecialJvmAnnotations
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.load.java.JvmAbi
+import org.jetbrains.kotlin.metadata.ProtoBuf
+import org.jetbrains.kotlin.metadata.deserialization.*
+import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
+import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf.propertySignature
+import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite
+import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.protobuf.MessageLite
+import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
+import org.jetbrains.kotlin.serialization.deserialization.AnnotationLoader
+import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
+
+abstract class AbstractBinaryClassAnnotationLoader>(
+ protected val kotlinClassFinder: KotlinClassFinder
+) : AnnotationLoader {
+ protected abstract fun getAnnotationsContainer(binaryClass: KotlinJvmBinaryClass): S
+
+ protected abstract fun loadAnnotation(
+ annotationClassId: ClassId,
+ source: SourceElement,
+ result: MutableList
+ ): KotlinJvmBinaryClass.AnnotationArgumentVisitor?
+
+ protected abstract fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): A
+
+ protected fun loadAnnotationIfNotSpecial(
+ annotationClassId: ClassId,
+ source: SourceElement,
+ result: MutableList
+ ): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
+ if (annotationClassId in SpecialJvmAnnotations.SPECIAL_ANNOTATIONS) return null
+
+ return loadAnnotation(annotationClassId, source, result)
+ }
+
+ private fun ProtoContainer.Class.toBinaryClass(): KotlinJvmBinaryClass? =
+ (source as? KotlinJvmBinarySourceElement)?.binaryClass
+
+ protected open fun getCachedFileContent(kotlinClass: KotlinJvmBinaryClass): ByteArray? = null
+
+ override fun loadClassAnnotations(container: ProtoContainer.Class): List {
+ val kotlinClass = container.toBinaryClass() ?: error("Class for loading annotations is not found: ${container.debugFqName()}")
+
+ val result = ArrayList(1)
+
+ kotlinClass.loadClassAnnotations(object : KotlinJvmBinaryClass.AnnotationVisitor {
+ override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
+ return loadAnnotationIfNotSpecial(classId, source, result)
+ }
+
+ override fun visitEnd() {
+ }
+ }, getCachedFileContent(kotlinClass))
+
+ return result
+ }
+
+ override fun loadCallableAnnotations(container: ProtoContainer, proto: MessageLite, kind: AnnotatedCallableKind): List {
+ if (kind == AnnotatedCallableKind.PROPERTY) {
+ return loadPropertyAnnotations(container, proto as ProtoBuf.Property, PropertyRelatedElement.PROPERTY)
+ }
+
+ val signature = getCallableSignature(proto, container.nameResolver, container.typeTable, kind) ?: return emptyList()
+ return findClassAndLoadMemberAnnotations(container, signature)
+ }
+
+ override fun loadPropertyBackingFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List =
+ loadPropertyAnnotations(container, proto, PropertyRelatedElement.BACKING_FIELD)
+
+ override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List =
+ loadPropertyAnnotations(container, proto, PropertyRelatedElement.DELEGATE_FIELD)
+
+ private enum class PropertyRelatedElement {
+ PROPERTY,
+ BACKING_FIELD,
+ DELEGATE_FIELD,
+ }
+
+ private fun loadPropertyAnnotations(container: ProtoContainer, proto: ProtoBuf.Property, element: PropertyRelatedElement): List {
+ val isConst = Flags.IS_CONST.get(proto.flags)
+ val isMovedFromInterfaceCompanion = JvmProtoBufUtil.isMovedFromInterfaceCompanion(proto)
+ if (element == PropertyRelatedElement.PROPERTY) {
+ val syntheticFunctionSignature =
+ getPropertySignature(proto, container.nameResolver, container.typeTable, synthetic = true) ?: return emptyList()
+ return findClassAndLoadMemberAnnotations(
+ container, syntheticFunctionSignature, property = true, isConst = isConst,
+ isMovedFromInterfaceCompanion = isMovedFromInterfaceCompanion
+ )
+ }
+
+ val fieldSignature =
+ getPropertySignature(proto, container.nameResolver, container.typeTable, field = true) ?: return emptyList()
+
+ // TODO: check delegate presence in some other way
+ val isDelegated = JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX in fieldSignature.signature
+ if (isDelegated != (element == PropertyRelatedElement.DELEGATE_FIELD)) return emptyList()
+
+ return findClassAndLoadMemberAnnotations(
+ container, fieldSignature, property = true, field = true, isConst = isConst,
+ isMovedFromInterfaceCompanion = isMovedFromInterfaceCompanion
+ )
+ }
+
+ override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List {
+ val signature = MemberSignature.fromFieldNameAndDesc(
+ container.nameResolver.getString(proto.name),
+ ClassMapperLite.mapClass((container as ProtoContainer.Class).classId.asString())
+ )
+ return findClassAndLoadMemberAnnotations(container, signature)
+ }
+
+ private fun findClassAndLoadMemberAnnotations(
+ container: ProtoContainer,
+ signature: MemberSignature,
+ property: Boolean = false,
+ field: Boolean = false,
+ isConst: Boolean? = null,
+ isMovedFromInterfaceCompanion: Boolean = false
+ ): List {
+ val kotlinClass =
+ findClassWithAnnotationsAndInitializers(
+ container,
+ getSpecialCaseContainerClass(
+ container,
+ property,
+ field,
+ isConst,
+ isMovedFromInterfaceCompanion
+ )
+ )
+ ?: return listOf()
+
+ return getAnnotationsContainer(kotlinClass).memberAnnotations[signature] ?: listOf()
+ }
+
+ override fun loadValueParameterAnnotations(
+ container: ProtoContainer,
+ callableProto: MessageLite,
+ kind: AnnotatedCallableKind,
+ parameterIndex: Int,
+ proto: ProtoBuf.ValueParameter
+ ): List {
+ val methodSignature = getCallableSignature(callableProto, container.nameResolver, container.typeTable, kind)
+ if (methodSignature != null) {
+ val index = parameterIndex + computeJvmParameterIndexShift(container, callableProto)
+ val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, index)
+ return findClassAndLoadMemberAnnotations(container, paramSignature)
+ }
+
+ return listOf()
+ }
+
+ private fun computeJvmParameterIndexShift(container: ProtoContainer, message: MessageLite): Int {
+ return when (message) {
+ is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0
+ is ProtoBuf.Property -> if (message.hasReceiver()) 1 else 0
+ is ProtoBuf.Constructor -> when {
+ (container as ProtoContainer.Class).kind == ProtoBuf.Class.Kind.ENUM_CLASS -> 2
+ container.isInner -> 1
+ else -> 0
+ }
+ else -> throw UnsupportedOperationException("Unsupported message: ${message::class.java}")
+ }
+ }
+
+ override fun loadExtensionReceiverParameterAnnotations(
+ container: ProtoContainer,
+ proto: MessageLite,
+ kind: AnnotatedCallableKind
+ ): List {
+ val methodSignature = getCallableSignature(proto, container.nameResolver, container.typeTable, kind)
+ if (methodSignature != null) {
+ val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, 0)
+ return findClassAndLoadMemberAnnotations(container, paramSignature)
+ }
+
+ return emptyList()
+ }
+
+ override fun loadTypeAnnotations(proto: ProtoBuf.Type, nameResolver: NameResolver): List {
+ return proto.getExtension(JvmProtoBuf.typeAnnotation).map { loadTypeAnnotation(it, nameResolver) }
+ }
+
+ override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List {
+ return proto.getExtension(JvmProtoBuf.typeParameterAnnotation).map { loadTypeAnnotation(it, nameResolver) }
+ }
+
+ protected fun findClassWithAnnotationsAndInitializers(
+ container: ProtoContainer, specialCase: KotlinJvmBinaryClass?
+ ): KotlinJvmBinaryClass? {
+ return when {
+ specialCase != null -> specialCase
+ container is ProtoContainer.Class -> container.toBinaryClass()
+ else -> null
+ }
+ }
+
+ // TODO: do not use KotlinClassFinder#findKotlinClass here because it traverses the file system in the compiler
+ // Introduce an API in KotlinJvmBinaryClass to find a class nearby instead
+ protected fun getSpecialCaseContainerClass(
+ container: ProtoContainer,
+ property: Boolean,
+ field: Boolean,
+ isConst: Boolean?,
+ isMovedFromInterfaceCompanion: Boolean
+ ): KotlinJvmBinaryClass? {
+ if (property) {
+ checkNotNull(isConst) { "isConst should not be null for property (container=$container)" }
+ if (container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.INTERFACE) {
+ return kotlinClassFinder.findKotlinClass(
+ container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
+ )
+ }
+ if (isConst && container is ProtoContainer.Package) {
+ // Const properties in multifile classes are generated into the facade class
+ val facadeClassName = (container.source as? JvmPackagePartSource)?.facadeClassName
+ if (facadeClassName != null) {
+ // Converting '/' to '.' is fine here because the facade class has a top level ClassId
+ return kotlinClassFinder.findKotlinClass(ClassId.topLevel(FqName(facadeClassName.internalName.replace('/', '.'))))
+ }
+ }
+ }
+ if (field && container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
+ val outerClass = container.outerClass
+ if (outerClass != null &&
+ (outerClass.kind == ProtoBuf.Class.Kind.CLASS || outerClass.kind == ProtoBuf.Class.Kind.ENUM_CLASS ||
+ (isMovedFromInterfaceCompanion &&
+ (outerClass.kind == ProtoBuf.Class.Kind.INTERFACE ||
+ outerClass.kind == ProtoBuf.Class.Kind.ANNOTATION_CLASS)))
+ ) {
+ // Backing fields of properties of a companion object in a class are generated in the outer class
+ return outerClass.toBinaryClass()
+ }
+ }
+ if (container is ProtoContainer.Package && container.source is JvmPackagePartSource) {
+ val jvmPackagePartSource = container.source as JvmPackagePartSource
+
+ return jvmPackagePartSource.knownJvmBinaryClass
+ ?: kotlinClassFinder.findKotlinClass(jvmPackagePartSource.classId)
+ }
+ return null
+ }
+
+ protected fun getPropertySignature(
+ proto: ProtoBuf.Property,
+ nameResolver: NameResolver,
+ typeTable: TypeTable,
+ field: Boolean = false,
+ synthetic: Boolean = false,
+ requireHasFieldFlagForField: Boolean = true
+ ): MemberSignature? {
+ val signature = proto.getExtensionOrNull(propertySignature) ?: return null
+
+ if (field) {
+ val fieldSignature =
+ JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable, requireHasFieldFlagForField) ?: return null
+ return MemberSignature.fromJvmMemberSignature(fieldSignature)
+ } else if (synthetic && signature.hasSyntheticMethod()) {
+ return MemberSignature.fromMethod(nameResolver, signature.syntheticMethod)
+ }
+
+ return null
+ }
+
+ protected fun getCallableSignature(
+ proto: MessageLite,
+ nameResolver: NameResolver,
+ typeTable: TypeTable,
+ kind: AnnotatedCallableKind,
+ requireHasFieldFlagForField: Boolean = false
+ ): MemberSignature? {
+ return when (proto) {
+ is ProtoBuf.Constructor -> {
+ MemberSignature.fromJvmMemberSignature(
+ JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable) ?: return null
+ )
+ }
+ is ProtoBuf.Function -> {
+ MemberSignature.fromJvmMemberSignature(JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable) ?: return null)
+ }
+ is ProtoBuf.Property -> {
+ val signature = proto.getExtensionOrNull(propertySignature) ?: return null
+ when (kind) {
+ AnnotatedCallableKind.PROPERTY_GETTER ->
+ if (signature.hasGetter()) MemberSignature.fromMethod(nameResolver, signature.getter) else null
+ AnnotatedCallableKind.PROPERTY_SETTER ->
+ if (signature.hasSetter()) MemberSignature.fromMethod(nameResolver, signature.setter) else null
+ AnnotatedCallableKind.PROPERTY ->
+ getPropertySignature(proto, nameResolver, typeTable, true, true, requireHasFieldFlagForField)
+ else -> null
+ }
+ }
+ else -> null
+ }
+ }
+
+ protected fun isImplicitRepeatableContainer(classId: ClassId): Boolean {
+ if (classId.outerClassId == null ||
+ classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME
+ ) return false
+
+ val klass = kotlinClassFinder.findKotlinClass(classId)
+ return klass != null && SpecialJvmAnnotations.isAnnotatedWithContainerMetaAnnotation(klass)
+ }
+
+ abstract class AnnotationsContainer {
+ abstract val memberAnnotations: Map>
+ }
+}