From 7adb4eb8727c8ed3b4b4436887bd2c164d019ec7 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 21 Apr 2020 17:48:11 +0300 Subject: [PATCH] FIR serializer: extract annotation argument visiting to separate object --- .../FirAnnotationArgumentVisitor.kt | 140 ++++++++++++++++++ .../FirAnnotationArgumentVisitorData.kt | 15 ++ .../serialization/FirAnnotationSerializer.kt | 135 +---------------- 3 files changed, 160 insertions(+), 130 deletions(-) create mode 100644 compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitor.kt create mode 100644 compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitorData.kt diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitor.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitor.kt new file mode 100644 index 00000000000..86b8b95203f --- /dev/null +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitor.kt @@ -0,0 +1,140 @@ +/* + * Copyright 2010-2020 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.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.deserialization.Flags +import org.jetbrains.kotlin.resolve.constants.* + +object FirAnnotationArgumentVisitor : AnnotationArgumentVisitor { + override fun visitAnnotationValue(value: AnnotationValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.ANNOTATION + // TODO: annotation = serializeAnnotation(value.value) + } + + override fun visitArrayValue(value: ArrayValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.ARRAY + for (element in value.value) { + data.builder.addArrayElement(data.serializer.valueProto(element).build()) + } + } + + override fun visitBooleanValue(value: BooleanValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.BOOLEAN + data.builder.intValue = if (value.value) 1 else 0 + } + + override fun visitByteValue(value: ByteValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.BYTE + data.builder.intValue = value.value.toLong() + } + + override fun visitCharValue(value: CharValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.CHAR + data.builder.intValue = value.value.toLong() + } + + override fun visitDoubleValue(value: DoubleValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.DOUBLE + data.builder.doubleValue = value.value + } + + override fun visitEnumValue(value: EnumValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.ENUM + data.builder.classId = data.stringTable.getQualifiedClassNameIndex(value.enumClassId) + data.builder.enumValueId = data.stringTable.getStringIndex(value.enumEntryName.asString()) + } + + override fun visitErrorValue(value: ErrorValue, data: FirAnnotationArgumentVisitorData) { + throw UnsupportedOperationException("Error value: $value") + } + + override fun visitFloatValue(value: FloatValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.FLOAT + data.builder.floatValue = value.value + } + + override fun visitIntValue(value: IntValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.INT + data.builder.intValue = value.value.toLong() + } + + override fun visitKClassValue(value: KClassValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.CLASS + + when (val classValue = value.value) { + is KClassValue.Value.NormalClass -> { + data.builder.classId = data.stringTable.getQualifiedClassNameIndex(classValue.classId) + + if (classValue.arrayDimensions > 0) { + data.builder.arrayDimensionCount = classValue.arrayDimensions + } + } + is KClassValue.Value.LocalClass -> { + var arrayDimensions = 0 + var type = classValue.type + while (KotlinBuiltIns.isArray(type)) { + arrayDimensions++ + type = type.arguments.single().type + } + + //val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor + // ?: error("Type parameters are not allowed in class literal annotation arguments: $classValue") + // TODO: classId = stringTable.getFqNameIndex(descriptor) + + if (arrayDimensions > 0) { + data.builder.arrayDimensionCount = arrayDimensions + } + } + } + } + + override fun visitLongValue(value: LongValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.LONG + data.builder.intValue = value.value + } + + override fun visitNullValue(value: NullValue, data: FirAnnotationArgumentVisitorData) { + throw UnsupportedOperationException("Null should not appear in annotation arguments") + } + + override fun visitShortValue(value: ShortValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.SHORT + data.builder.intValue = value.value.toLong() + } + + override fun visitStringValue(value: StringValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.STRING + data.builder.stringValue = data.stringTable.getStringIndex(value.value) + } + + override fun visitUByteValue(value: UByteValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.BYTE + data.builder.intValue = value.value.toLong() + data.builder.flags = Flags.IS_UNSIGNED.toFlags(true) + } + + override fun visitUShortValue(value: UShortValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.SHORT + data.builder.intValue = value.value.toLong() + data.builder.flags = Flags.IS_UNSIGNED.toFlags(true) + } + + override fun visitUIntValue(value: UIntValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.INT + data.builder.intValue = value.value.toLong() + data.builder.flags = Flags.IS_UNSIGNED.toFlags(true) + } + + override fun visitULongValue(value: ULongValue, data: FirAnnotationArgumentVisitorData) { + data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.LONG + data.builder.intValue = value.value + data.builder.flags = Flags.IS_UNSIGNED.toFlags(true) + } + +} \ No newline at end of file diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitorData.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitorData.kt new file mode 100644 index 00000000000..11d430a8a5a --- /dev/null +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationArgumentVisitorData.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2020 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.metadata.ProtoBuf + +class FirAnnotationArgumentVisitorData( + val serializer: FirAnnotationSerializer, + val builder: ProtoBuf.Annotation.Argument.Value.Builder +) { + val stringTable: FirElementAwareStringTable get() = serializer.stringTable +} \ No newline at end of file diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationSerializer.kt index 9059c9c7c6b..85594c30c36 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirAnnotationSerializer.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.fir.serialization -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirConstExpression @@ -15,10 +13,9 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.metadata.ProtoBuf -import org.jetbrains.kotlin.metadata.deserialization.Flags import org.jetbrains.kotlin.resolve.constants.* -class FirAnnotationSerializer(private val session: FirSession, private val stringTable: FirElementAwareStringTable) { +class FirAnnotationSerializer(private val session: FirSession, internal val stringTable: FirElementAwareStringTable) { fun serializeAnnotation(annotation: FirAnnotationCall): ProtoBuf.Annotation = ProtoBuf.Annotation.newBuilder().apply { val annotationSymbol = annotation.typeRef.coneTypeSafe()?.lookupTag?.toSymbol(session) val annotationClass = annotationSymbol?.fir ?: error("Annotation type is not a class: ${annotationSymbol?.fir}") @@ -37,131 +34,9 @@ class FirAnnotationSerializer(private val session: FirSession, private val strin fun valueProto(constant: ConstantValue<*>): ProtoBuf.Annotation.Argument.Value.Builder = ProtoBuf.Annotation.Argument.Value.newBuilder().apply { - constant.accept(object : AnnotationArgumentVisitor { - override fun visitAnnotationValue(value: AnnotationValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.ANNOTATION - // TODO: annotation = serializeAnnotation(value.value) - } - - override fun visitArrayValue(value: ArrayValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.ARRAY - for (element in value.value) { - addArrayElement(valueProto(element).build()) - } - } - - override fun visitBooleanValue(value: BooleanValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.BOOLEAN - intValue = if (value.value) 1 else 0 - } - - override fun visitByteValue(value: ByteValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.BYTE - intValue = value.value.toLong() - } - - override fun visitCharValue(value: CharValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.CHAR - intValue = value.value.toLong() - } - - override fun visitDoubleValue(value: DoubleValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.DOUBLE - doubleValue = value.value - } - - override fun visitEnumValue(value: EnumValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.ENUM - classId = stringTable.getQualifiedClassNameIndex(value.enumClassId) - enumValueId = stringTable.getStringIndex(value.enumEntryName.asString()) - } - - override fun visitErrorValue(value: ErrorValue, data: Unit) { - throw UnsupportedOperationException("Error value: $value") - } - - override fun visitFloatValue(value: FloatValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.FLOAT - floatValue = value.value - } - - override fun visitIntValue(value: IntValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.INT - intValue = value.value.toLong() - } - - override fun visitKClassValue(value: KClassValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.CLASS - - when (val classValue = value.value) { - is KClassValue.Value.NormalClass -> { - classId = stringTable.getQualifiedClassNameIndex(classValue.classId) - - if (classValue.arrayDimensions > 0) { - arrayDimensionCount = classValue.arrayDimensions - } - } - is KClassValue.Value.LocalClass -> { - var arrayDimensions = 0 - var type = classValue.type - while (KotlinBuiltIns.isArray(type)) { - arrayDimensions++ - type = type.arguments.single().type - } - - //val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor - // ?: error("Type parameters are not allowed in class literal annotation arguments: $classValue") - // TODO: classId = stringTable.getFqNameIndex(descriptor) - - if (arrayDimensions > 0) { - arrayDimensionCount = arrayDimensions - } - } - } - } - - override fun visitLongValue(value: LongValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.LONG - intValue = value.value - } - - override fun visitNullValue(value: NullValue, data: Unit) { - throw UnsupportedOperationException("Null should not appear in annotation arguments") - } - - override fun visitShortValue(value: ShortValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.SHORT - intValue = value.value.toLong() - } - - override fun visitStringValue(value: StringValue, data: Unit) { - type = ProtoBuf.Annotation.Argument.Value.Type.STRING - stringValue = stringTable.getStringIndex(value.value) - } - - override fun visitUByteValue(value: UByteValue, data: Unit?) { - type = ProtoBuf.Annotation.Argument.Value.Type.BYTE - intValue = value.value.toLong() - flags = Flags.IS_UNSIGNED.toFlags(true) - } - - override fun visitUShortValue(value: UShortValue, data: Unit?) { - type = ProtoBuf.Annotation.Argument.Value.Type.SHORT - intValue = value.value.toLong() - flags = Flags.IS_UNSIGNED.toFlags(true) - } - - override fun visitUIntValue(value: UIntValue, data: Unit?) { - type = ProtoBuf.Annotation.Argument.Value.Type.INT - intValue = value.value.toLong() - flags = Flags.IS_UNSIGNED.toFlags(true) - } - - override fun visitULongValue(value: ULongValue, data: Unit?) { - type = ProtoBuf.Annotation.Argument.Value.Type.LONG - intValue = value.value - flags = Flags.IS_UNSIGNED.toFlags(true) - } - }, Unit) + constant.accept( + FirAnnotationArgumentVisitor, + FirAnnotationArgumentVisitorData(this@FirAnnotationSerializer, this) + ) } } \ No newline at end of file