From 2d10877fdad4ecfac6b7731369135e0ac0ef5319 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Tue, 24 Oct 2023 11:59:19 +0300 Subject: [PATCH] [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 --- .../AnnotationLoaderForStubBuilderImpl.kt | 84 +------------- .../AbstractAnnotationLoader.kt | 103 ++++++++++++++++++ .../AnnotationAndConstantLoaderImpl.kt | 94 +--------------- 3 files changed, 108 insertions(+), 173 deletions(-) create mode 100644 core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractAnnotationLoader.kt diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt index afada744ec0..c54fc1fbf72 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt @@ -8,93 +8,13 @@ package org.jetbrains.kotlin.analysis.decompiler.stub.file import org.jetbrains.kotlin.analysis.decompiler.stub.AnnotationWithArgs import org.jetbrains.kotlin.metadata.ProtoBuf 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.serialization.SerializerExtensionProtocol import org.jetbrains.kotlin.serialization.deserialization.* class AnnotationLoaderForStubBuilderImpl( - private val protocol: SerializerExtensionProtocol -) : AnnotationLoader { - - override fun loadClassAnnotations(container: ProtoContainer.Class): List = - container.classProto.getExtension(protocol.classAnnotation).orEmpty() - .map { loadAnnotation(it, container.nameResolver) } - - override fun loadCallableAnnotations( - container: ProtoContainer, - proto: MessageLite, - kind: AnnotatedCallableKind - ): List { - 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 { - 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 { - 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 = - 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 = - proto.getExtension(protocol.parameterAnnotation).orEmpty().map { loadAnnotation(it, container.nameResolver) } - - override fun loadExtensionReceiverParameterAnnotations( - container: ProtoContainer, - proto: MessageLite, - kind: AnnotatedCallableKind - ): List { - 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 = - proto.getExtension(protocol.typeAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) } - - override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List = - proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) } - + protocol: SerializerExtensionProtocol, +) : AbstractAnnotationLoader(protocol) { override fun loadAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationWithArgs { val valueMap = proto.argumentList.associate { nameResolver.getName(it.nameId) to createConstantValue(it.value, nameResolver) } return AnnotationWithArgs(nameResolver.getClassId(proto.id), valueMap) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractAnnotationLoader.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractAnnotationLoader.kt new file mode 100644 index 00000000000..ce7c3e00dbf --- /dev/null +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractAnnotationLoader.kt @@ -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( + protected val protocol: SerializerExtensionProtocol, +) : AnnotationLoader { + override fun loadClassAnnotations(container: ProtoContainer.Class): List { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + return proto.getExtension(protocol.typeAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) } + } + + override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List { + return proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { loadAnnotation(it, nameResolver) } + } +} diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt index d1733cf7ffc..68d5ff150c2 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull -import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol import org.jetbrains.kotlin.types.KotlinType @@ -30,102 +29,15 @@ import org.jetbrains.kotlin.types.KotlinType class AnnotationAndConstantLoaderImpl( module: ModuleDescriptor, notFoundClasses: NotFoundClasses, - private val protocol: SerializerExtensionProtocol -) : AnnotationAndConstantLoader> { + protocol: SerializerExtensionProtocol, +) : AbstractAnnotationLoader(protocol), + AnnotationAndConstantLoader> { private val deserializer = AnnotationDeserializer(module, notFoundClasses) - override fun loadClassAnnotations(container: ProtoContainer.Class): List { - 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 { return deserializer.deserializeAnnotation(proto, nameResolver) } - override fun loadCallableAnnotations( - container: ProtoContainer, - proto: MessageLite, - kind: AnnotatedCallableKind - ): List { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - return proto.getExtension(protocol.typeAnnotation).orEmpty().map { deserializer.deserializeAnnotation(it, nameResolver) } - } - - override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List { - return proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { deserializer.deserializeAnnotation(it, nameResolver) } - } - override fun loadPropertyConstant(container: ProtoContainer, proto: ProtoBuf.Property, expectedType: KotlinType): ConstantValue<*>? { val value = proto.getExtensionOrNull(protocol.compileTimeValue) ?: return null return deserializer.resolveValue(expectedType, value, container.nameResolver)