[refactoring] extract base class for annotation loaders

Annotation loaders for descriptors (AnnotationAndConstantLoaderImpl) and
stubs (AnnotationLoaderForStubBuilderImpl) share the loading logic until
mapping ProtoBuf.Annotations to output values. The shared logic has been
extracted to the base class.

KTIJ-26761
KTIJ-26961
This commit is contained in:
Pavel Kirpichenkov
2023-10-24 11:59:19 +03:00
committed by Space Team
parent 30d45039fb
commit 2d10877fda
3 changed files with 108 additions and 173 deletions
@@ -8,93 +8,13 @@ package org.jetbrains.kotlin.analysis.decompiler.stub.file
import org.jetbrains.kotlin.analysis.decompiler.stub.AnnotationWithArgs import org.jetbrains.kotlin.analysis.decompiler.stub.AnnotationWithArgs
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.psi.stubs.impl.createConstantValue import org.jetbrains.kotlin.psi.stubs.impl.createConstantValue
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.*
class AnnotationLoaderForStubBuilderImpl( class AnnotationLoaderForStubBuilderImpl(
private val protocol: SerializerExtensionProtocol protocol: SerializerExtensionProtocol,
) : AnnotationLoader<AnnotationWithArgs> { ) : AbstractAnnotationLoader<AnnotationWithArgs>(protocol) {
override fun loadClassAnnotations(container: ProtoContainer.Class): List<AnnotationWithArgs> =
container.classProto.getExtension(protocol.classAnnotation).orEmpty()
.map { loadAnnotation(it, container.nameResolver) }
override fun loadCallableAnnotations(
container: ProtoContainer,
proto: MessageLite,
kind: AnnotatedCallableKind
): List<AnnotationWithArgs> {
val annotations = when (proto) {
is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation)
is ProtoBuf.Function -> proto.getExtension(protocol.functionAnnotation)
is ProtoBuf.Property -> when (kind) {
AnnotatedCallableKind.PROPERTY -> proto.getExtension(protocol.propertyAnnotation)
AnnotatedCallableKind.PROPERTY_GETTER -> proto.getExtension(protocol.propertyGetterAnnotation)
AnnotatedCallableKind.PROPERTY_SETTER -> proto.getExtension(protocol.propertySetterAnnotation)
else -> error("Unsupported callable kind with property proto")
}
else -> error("Unknown message: $proto")
}.orEmpty()
return annotations.map { loadAnnotation(it, container.nameResolver) }
}
override fun loadPropertyBackingFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<AnnotationWithArgs> {
val annotations = protocol.propertyBackingFieldAnnotation?.let { proto.getExtension(it) }.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<AnnotationWithArgs> {
val annotations = protocol.propertyDelegatedFieldAnnotation?.let {proto.getExtension(it) }.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<AnnotationWithArgs> =
proto.getExtension(protocol.enumEntryAnnotation).orEmpty().map { loadAnnotation(it, container.nameResolver) }
override fun loadValueParameterAnnotations(
container: ProtoContainer,
callableProto: MessageLite,
kind: AnnotatedCallableKind,
parameterIndex: Int,
proto: ProtoBuf.ValueParameter
): List<AnnotationWithArgs> =
proto.getExtension(protocol.parameterAnnotation).orEmpty().map { loadAnnotation(it, container.nameResolver) }
override fun loadExtensionReceiverParameterAnnotations(
container: ProtoContainer,
proto: MessageLite,
kind: AnnotatedCallableKind
): List<AnnotationWithArgs> {
val annotations = when (proto) {
is ProtoBuf.Function -> protocol.functionExtensionReceiverAnnotation?.let { proto.getExtension(it) }
is ProtoBuf.Property -> when (kind) {
AnnotatedCallableKind.PROPERTY, AnnotatedCallableKind.PROPERTY_GETTER, AnnotatedCallableKind.PROPERTY_SETTER -> {
protocol.propertyExtensionReceiverAnnotation?.let { proto.getExtension(it) }
}
else -> error("Unsupported callable kind with property proto for receiver annotations: $kind")
}
else -> error("Unknown message: $proto")
}.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadTypeAnnotations(
proto: ProtoBuf.Type,
nameResolver: NameResolver
): List<AnnotationWithArgs> =
proto.getExtension(protocol.typeAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) }
override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<AnnotationWithArgs> =
proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) }
override fun loadAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationWithArgs { override fun loadAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationWithArgs {
val valueMap = proto.argumentList.associate { nameResolver.getName(it.nameId) to createConstantValue(it.value, nameResolver) } val valueMap = proto.argumentList.associate { nameResolver.getName(it.nameId) to createConstantValue(it.value, nameResolver) }
return AnnotationWithArgs(nameResolver.getClassId(proto.id), valueMap) return AnnotationWithArgs(nameResolver.getClassId(proto.id), valueMap)
@@ -0,0 +1,103 @@
/*
* 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.serialization.deserialization
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
abstract class AbstractAnnotationLoader<out A : Any>(
protected val protocol: SerializerExtensionProtocol,
) : AnnotationLoader<A> {
override fun loadClassAnnotations(container: ProtoContainer.Class): List<A> {
val annotations = container.classProto.getExtension(protocol.classAnnotation).orEmpty()
return annotations.map { proto -> loadAnnotation(proto, container.nameResolver) }
}
override fun loadCallableAnnotations(
container: ProtoContainer,
proto: MessageLite,
kind: AnnotatedCallableKind
): List<A> {
val annotations = when (proto) {
is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation)
is ProtoBuf.Function -> proto.getExtension(protocol.functionAnnotation)
is ProtoBuf.Property -> when (kind) {
AnnotatedCallableKind.PROPERTY -> proto.getExtension(protocol.propertyAnnotation)
AnnotatedCallableKind.PROPERTY_GETTER -> proto.getExtension(protocol.propertyGetterAnnotation)
AnnotatedCallableKind.PROPERTY_SETTER -> proto.getExtension(protocol.propertySetterAnnotation)
else -> error("Unsupported callable kind with property proto")
}
else -> error("Unknown message: $proto")
}.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadPropertyBackingFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<A> {
val annotations = protocol.propertyBackingFieldAnnotation?.let { proto.getExtension(it) }.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<A> {
val annotations = protocol.propertyDelegatedFieldAnnotation?.let { proto.getExtension(it) }.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<A> {
val annotations = proto.getExtension(protocol.enumEntryAnnotation).orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadValueParameterAnnotations(
container: ProtoContainer,
callableProto: MessageLite,
kind: AnnotatedCallableKind,
parameterIndex: Int,
proto: ProtoBuf.ValueParameter
): List<A> {
val annotations = proto.getExtension(protocol.parameterAnnotation).orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadExtensionReceiverParameterAnnotations(
container: ProtoContainer,
proto: MessageLite,
kind: AnnotatedCallableKind
): List<A> {
val annotations = when (proto) {
is ProtoBuf.Function -> protocol.functionExtensionReceiverAnnotation?.let { proto.getExtension(it) }
is ProtoBuf.Property -> when (kind) {
AnnotatedCallableKind.PROPERTY, AnnotatedCallableKind.PROPERTY_GETTER, AnnotatedCallableKind.PROPERTY_SETTER -> {
protocol.propertyExtensionReceiverAnnotation?.let { proto.getExtension(it) }
}
else -> error("Unsupported callable kind with property proto for receiver annotations: $kind")
}
else -> error("Unknown message: $proto")
}.orEmpty()
return annotations.map { annotationProto ->
loadAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadTypeAnnotations(proto: ProtoBuf.Type, nameResolver: NameResolver): List<A> {
return proto.getExtension(protocol.typeAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) }
}
override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<A> {
return proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) }
}
}
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -30,102 +29,15 @@ import org.jetbrains.kotlin.types.KotlinType
class AnnotationAndConstantLoaderImpl( class AnnotationAndConstantLoaderImpl(
module: ModuleDescriptor, module: ModuleDescriptor,
notFoundClasses: NotFoundClasses, notFoundClasses: NotFoundClasses,
private val protocol: SerializerExtensionProtocol protocol: SerializerExtensionProtocol,
) : AnnotationAndConstantLoader<AnnotationDescriptor, ConstantValue<*>> { ) : AbstractAnnotationLoader<AnnotationDescriptor>(protocol),
AnnotationAndConstantLoader<AnnotationDescriptor, ConstantValue<*>> {
private val deserializer = AnnotationDeserializer(module, notFoundClasses) private val deserializer = AnnotationDeserializer(module, notFoundClasses)
override fun loadClassAnnotations(container: ProtoContainer.Class): List<AnnotationDescriptor> {
val annotations = container.classProto.getExtension(protocol.classAnnotation).orEmpty()
return annotations.map { proto -> deserializer.deserializeAnnotation(proto, container.nameResolver) }
}
override fun loadAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor { override fun loadAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor {
return deserializer.deserializeAnnotation(proto, nameResolver) return deserializer.deserializeAnnotation(proto, nameResolver)
} }
override fun loadCallableAnnotations(
container: ProtoContainer,
proto: MessageLite,
kind: AnnotatedCallableKind
): List<AnnotationDescriptor> {
val annotations = when (proto) {
is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation)
is ProtoBuf.Function -> proto.getExtension(protocol.functionAnnotation)
is ProtoBuf.Property -> when (kind) {
AnnotatedCallableKind.PROPERTY -> proto.getExtension(protocol.propertyAnnotation)
AnnotatedCallableKind.PROPERTY_GETTER -> proto.getExtension(protocol.propertyGetterAnnotation)
AnnotatedCallableKind.PROPERTY_SETTER -> proto.getExtension(protocol.propertySetterAnnotation)
else -> error("Unsupported callable kind with property proto")
}
else -> error("Unknown message: $proto")
}.orEmpty()
return annotations.map { annotationProto ->
deserializer.deserializeAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadPropertyBackingFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<AnnotationDescriptor> {
val annotations = protocol.propertyBackingFieldAnnotation?.let { proto.getExtension(it) }.orEmpty()
return annotations.map { annotationProto ->
deserializer.deserializeAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<AnnotationDescriptor> {
val annotations = protocol.propertyDelegatedFieldAnnotation?.let {proto.getExtension(it) }.orEmpty()
return annotations.map { annotationProto ->
deserializer.deserializeAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<AnnotationDescriptor> {
val annotations = proto.getExtension(protocol.enumEntryAnnotation).orEmpty()
return annotations.map { annotationProto ->
deserializer.deserializeAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadValueParameterAnnotations(
container: ProtoContainer,
callableProto: MessageLite,
kind: AnnotatedCallableKind,
parameterIndex: Int,
proto: ProtoBuf.ValueParameter
): List<AnnotationDescriptor> {
val annotations = proto.getExtension(protocol.parameterAnnotation).orEmpty()
return annotations.map { annotationProto ->
deserializer.deserializeAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadExtensionReceiverParameterAnnotations(
container: ProtoContainer,
proto: MessageLite,
kind: AnnotatedCallableKind
): List<AnnotationDescriptor> {
val annotations = when (proto) {
is ProtoBuf.Function -> protocol.functionExtensionReceiverAnnotation?.let { proto.getExtension(it) }
is ProtoBuf.Property -> when (kind) {
AnnotatedCallableKind.PROPERTY, AnnotatedCallableKind.PROPERTY_GETTER, AnnotatedCallableKind.PROPERTY_SETTER -> {
protocol.propertyExtensionReceiverAnnotation?.let { proto.getExtension(it) }
}
else -> error("Unsupported callable kind with property proto for receiver annotations: $kind")
}
else -> error("Unknown message: $proto")
}.orEmpty()
return annotations.map { annotationProto ->
deserializer.deserializeAnnotation(annotationProto, container.nameResolver)
}
}
override fun loadTypeAnnotations(proto: ProtoBuf.Type, nameResolver: NameResolver): List<AnnotationDescriptor> {
return proto.getExtension(protocol.typeAnnotation).orEmpty().map { deserializer.deserializeAnnotation(it, nameResolver) }
}
override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<AnnotationDescriptor> {
return proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { deserializer.deserializeAnnotation(it, nameResolver) }
}
override fun loadPropertyConstant(container: ProtoContainer, proto: ProtoBuf.Property, expectedType: KotlinType): ConstantValue<*>? { override fun loadPropertyConstant(container: ProtoContainer, proto: ProtoBuf.Property, expectedType: KotlinType): ConstantValue<*>? {
val value = proto.getExtensionOrNull(protocol.compileTimeValue) ?: return null val value = proto.getExtensionOrNull(protocol.compileTimeValue) ?: return null
return deserializer.resolveValue(expectedType, value, container.nameResolver) return deserializer.resolveValue(expectedType, value, container.nameResolver)