J2K serialization: fix compilation and prettify

This commit is contained in:
Alexander Udalov
2016-06-07 15:42:07 +03:00
parent 6692aca5f3
commit 0c0a451d20
5 changed files with 161 additions and 231 deletions
@@ -25,66 +25,62 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value.Typ
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
class AnnotationSerializer(private val stringTable: StringTable) { class AnnotationSerializer(private val stringTable: StringTable) {
fun serializeAnnotation(annotation: AnnotationDescriptor): ProtoBuf.Annotation { fun serializeAnnotation(annotation: AnnotationDescriptor): ProtoBuf.Annotation = ProtoBuf.Annotation.newBuilder().apply {
return with(ProtoBuf.Annotation.newBuilder()) { val annotationClass = annotation.type.constructor.declarationDescriptor as? ClassDescriptor
val annotationClass = annotation.type.constructor.declarationDescriptor as? ClassDescriptor ?: error("Annotation type is not a class: ${annotation.type}")
?: error("Annotation type is not a class: ${annotation.type}") if (ErrorUtils.isError(annotationClass)) {
if (ErrorUtils.isError(annotationClass)) { error("Unresolved annotation type: ${annotation.type}")
error("Unresolved annotation type: ${annotation.type}")
}
setId(stringTable.getFqNameIndex(annotationClass))
for ((parameter, value) in annotation.allValueArguments) {
val argument = ProtoBuf.Annotation.Argument.newBuilder()
argument.setNameId(stringTable.getStringIndex(parameter.name.asString()))
argument.setValue(valueProto(value))
addArgument(argument)
}
build()
} }
}
fun valueProto(constant: ConstantValue<*>): Value.Builder = with(Value.newBuilder()) { id = stringTable.getFqNameIndex(annotationClass)
for ((parameter, value) in annotation.allValueArguments) {
val argument = ProtoBuf.Annotation.Argument.newBuilder()
argument.nameId = stringTable.getStringIndex(parameter.name.asString())
argument.setValue(valueProto(value))
addArgument(argument)
}
}.build()
fun valueProto(constant: ConstantValue<*>): Value.Builder = Value.newBuilder().apply {
constant.accept(object : AnnotationArgumentVisitor<Unit, Unit> { constant.accept(object : AnnotationArgumentVisitor<Unit, Unit> {
override fun visitAnnotationValue(value: AnnotationValue, data: Unit) { override fun visitAnnotationValue(value: AnnotationValue, data: Unit) {
setType(Type.ANNOTATION) type = Type.ANNOTATION
setAnnotation(serializeAnnotation(value.value)) annotation = serializeAnnotation(value.value)
} }
override fun visitArrayValue(value: ArrayValue, data: Unit) { override fun visitArrayValue(value: ArrayValue, data: Unit) {
setType(Type.ARRAY) type = Type.ARRAY
for (element in value.value) { for (element in value.value) {
addArrayElement(valueProto(element).build()) addArrayElement(valueProto(element).build())
} }
} }
override fun visitBooleanValue(value: BooleanValue, data: Unit) { override fun visitBooleanValue(value: BooleanValue, data: Unit) {
setType(Type.BOOLEAN) type = Type.BOOLEAN
setIntValue(if (value.value) 1 else 0) setIntValue(if (value.value) 1 else 0)
} }
override fun visitByteValue(value: ByteValue, data: Unit) { override fun visitByteValue(value: ByteValue, data: Unit) {
setType(Type.BYTE) type = Type.BYTE
setIntValue(value.value.toLong()) intValue = value.value.toLong()
} }
override fun visitCharValue(value: CharValue, data: Unit) { override fun visitCharValue(value: CharValue, data: Unit) {
setType(Type.CHAR) type = Type.CHAR
setIntValue(value.value.toLong()) intValue = value.value.toLong()
} }
override fun visitDoubleValue(value: DoubleValue, data: Unit) { override fun visitDoubleValue(value: DoubleValue, data: Unit) {
setType(Type.DOUBLE) type = Type.DOUBLE
setDoubleValue(value.value) doubleValue = value.value
} }
override fun visitEnumValue(value: EnumValue, data: Unit) { override fun visitEnumValue(value: EnumValue, data: Unit) {
setType(Type.ENUM) type = Type.ENUM
val enumEntry = value.value val enumEntry = value.value
setClassId(stringTable.getFqNameIndex(enumEntry.containingDeclaration as ClassDescriptor)) classId = stringTable.getFqNameIndex(enumEntry.containingDeclaration as ClassDescriptor)
setEnumValueId(stringTable.getStringIndex(enumEntry.name.asString())) enumValueId = stringTable.getStringIndex(enumEntry.name.asString())
} }
override fun visitErrorValue(value: ErrorValue, data: Unit) { override fun visitErrorValue(value: ErrorValue, data: Unit) {
@@ -92,13 +88,13 @@ class AnnotationSerializer(private val stringTable: StringTable) {
} }
override fun visitFloatValue(value: FloatValue, data: Unit) { override fun visitFloatValue(value: FloatValue, data: Unit) {
setType(Type.FLOAT) type = Type.FLOAT
setFloatValue(value.value) floatValue = value.value
} }
override fun visitIntValue(value: IntValue, data: Unit) { override fun visitIntValue(value: IntValue, data: Unit) {
setType(Type.INT) type = Type.INT
setIntValue(value.value.toLong()) intValue = value.value.toLong()
} }
override fun visitKClassValue(value: KClassValue?, data: Unit?) { override fun visitKClassValue(value: KClassValue?, data: Unit?) {
@@ -107,8 +103,8 @@ class AnnotationSerializer(private val stringTable: StringTable) {
} }
override fun visitLongValue(value: LongValue, data: Unit) { override fun visitLongValue(value: LongValue, data: Unit) {
setType(Type.LONG) type = Type.LONG
setIntValue(value.value) intValue = value.value
} }
override fun visitNullValue(value: NullValue, data: Unit) { override fun visitNullValue(value: NullValue, data: Unit) {
@@ -116,16 +112,14 @@ class AnnotationSerializer(private val stringTable: StringTable) {
} }
override fun visitShortValue(value: ShortValue, data: Unit) { override fun visitShortValue(value: ShortValue, data: Unit) {
setType(Type.SHORT) type = Type.SHORT
setIntValue(value.value.toLong()) intValue = value.value.toLong()
} }
override fun visitStringValue(value: StringValue, data: Unit) { override fun visitStringValue(value: StringValue, data: Unit) {
setType(Type.STRING) type = Type.STRING
setStringValue(stringTable.getStringIndex(value.value)) stringValue = stringTable.getStringIndex(value.value)
} }
}, Unit) }, Unit)
this
} }
} }
@@ -27,9 +27,7 @@ import org.jetbrains.kotlin.resolve.MemberComparator
import org.jetbrains.kotlin.resolve.constants.NullValue import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.Interner import org.jetbrains.kotlin.utils.Interner
import org.jetbrains.kotlin.utils.rethrow
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.* import java.util.*
class DescriptorSerializer private constructor( class DescriptorSerializer private constructor(
@@ -37,38 +35,30 @@ class DescriptorSerializer private constructor(
private val typeParameters: Interner<TypeParameterDescriptor>, private val typeParameters: Interner<TypeParameterDescriptor>,
private val extension: SerializerExtension, private val extension: SerializerExtension,
private val typeTable: MutableTypeTable, private val typeTable: MutableTypeTable,
private val serializeTypeTableToFunction: Boolean) { private val serializeTypeTableToFunction: Boolean
) {
fun serialize(message: MessageLite): ByteArray { fun serialize(message: MessageLite): ByteArray {
try { return ByteArrayOutputStream().apply {
val result = ByteArrayOutputStream() stringTable.serializeTo(this)
stringTable.serializeTo(result) message.writeTo(this)
message.writeTo(result) }.toByteArray()
return result.toByteArray()
}
catch (e: IOException) {
throw rethrow(e)
}
} }
private fun createChildSerializer(callable: CallableDescriptor): DescriptorSerializer { private fun createChildSerializer(callable: CallableDescriptor): DescriptorSerializer =
return DescriptorSerializer(callable, Interner(typeParameters), extension, typeTable, false) DescriptorSerializer(callable, Interner(typeParameters), extension, typeTable, serializeTypeTableToFunction = false)
}
val stringTable: StringTable val stringTable: StringTable
get() = extension.stringTable get() = extension.stringTable
private fun useTypeTable(): Boolean { private fun useTypeTable(): Boolean = extension.shouldUseTypeTable()
return extension.shouldUseTypeTable()
}
fun classProto(classDescriptor: ClassDescriptor): ProtoBuf.Class.Builder { fun classProto(classDescriptor: ClassDescriptor): ProtoBuf.Class.Builder {
val builder = ProtoBuf.Class.newBuilder() val builder = ProtoBuf.Class.newBuilder()
val flags = Flags.getClassFlags(hasAnnotations(classDescriptor), classDescriptor.visibility, classDescriptor.modality, val flags = Flags.getClassFlags(
classDescriptor.kind, classDescriptor.isInner, classDescriptor.isCompanionObject, hasAnnotations(classDescriptor), classDescriptor.visibility, classDescriptor.modality, classDescriptor.kind,
classDescriptor.isData) classDescriptor.isInner, classDescriptor.isCompanionObject, classDescriptor.isData
)
if (flags != builder.flags) { if (flags != builder.flags) {
builder.flags = flags builder.flags = flags
} }
@@ -99,11 +89,9 @@ class DescriptorSerializer private constructor(
if (descriptor is CallableMemberDescriptor) { if (descriptor is CallableMemberDescriptor) {
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
if (descriptor is PropertyDescriptor) { when (descriptor) {
builder.addProperty(propertyProto(descriptor)) is PropertyDescriptor -> builder.addProperty(propertyProto(descriptor))
} is FunctionDescriptor -> builder.addFunction(functionProto(descriptor))
else if (descriptor is FunctionDescriptor) {
builder.addFunction(functionProto(descriptor))
} }
} }
} }
@@ -149,37 +137,32 @@ class DescriptorSerializer private constructor(
val isConst = descriptor.isConst val isConst = descriptor.isConst
val compileTimeConstant = descriptor.compileTimeInitializer val compileTimeConstant = descriptor.compileTimeInitializer
val hasConstant = !(compileTimeConstant == null || compileTimeConstant is NullValue) val hasConstant = compileTimeConstant != null && compileTimeConstant !is NullValue
val hasAnnotations = !descriptor.annotations.getAllAnnotations().isEmpty() val hasAnnotations = descriptor.annotations.getAllAnnotations().isNotEmpty()
val propertyFlags = Flags.getAccessorFlags( val propertyFlags = Flags.getAccessorFlags(hasAnnotations, descriptor.visibility, descriptor.modality, false, false)
hasAnnotations,
descriptor.visibility,
descriptor.modality,
false,
false)
val getter = descriptor.getGetter() val getter = descriptor.getter
if (getter != null) { if (getter != null) {
hasGetter = true hasGetter = true
val accessorFlags = getAccessorFlags(getter!!) val accessorFlags = getAccessorFlags(getter)
if (accessorFlags != propertyFlags) { if (accessorFlags != propertyFlags) {
builder.getterFlags = accessorFlags builder.getterFlags = accessorFlags
} }
} }
val setter = descriptor.getSetter() val setter = descriptor.setter
if (setter != null) { if (setter != null) {
hasSetter = true hasSetter = true
val accessorFlags = getAccessorFlags(setter!!) val accessorFlags = getAccessorFlags(setter)
if (accessorFlags != propertyFlags) { if (accessorFlags != propertyFlags) {
builder.setterFlags = accessorFlags builder.setterFlags = accessorFlags
} }
if (!setter!!.isDefault()) { if (!setter.isDefault) {
val setterLocal = local.createChildSerializer(setter!!) val setterLocal = local.createChildSerializer(setter)
for (valueParameterDescriptor in setter!!.getValueParameters()) { for (valueParameterDescriptor in setter.valueParameters) {
builder.setSetterValueParameter(setterLocal.valueParameter(valueParameterDescriptor)) builder.setSetterValueParameter(setterLocal.valueParameter(valueParameterDescriptor))
} }
} }
@@ -187,7 +170,8 @@ class DescriptorSerializer private constructor(
val flags = Flags.getPropertyFlags( val flags = Flags.getPropertyFlags(
hasAnnotations, descriptor.visibility, descriptor.modality, descriptor.kind, descriptor.isVar, hasAnnotations, descriptor.visibility, descriptor.modality, descriptor.kind, descriptor.isVar,
hasGetter, hasSetter, hasConstant, isConst, lateInit) hasGetter, hasSetter, hasConstant, isConst, lateInit
)
if (flags != builder.flags) { if (flags != builder.flags) {
builder.flags = flags builder.flags = flags
} }
@@ -226,9 +210,8 @@ class DescriptorSerializer private constructor(
val local = createChildSerializer(descriptor) val local = createChildSerializer(descriptor)
val flags = Flags.getFunctionFlags( val flags = Flags.getFunctionFlags(
hasAnnotations(descriptor), descriptor.visibility, descriptor.modality, descriptor.kind, hasAnnotations(descriptor), descriptor.visibility, descriptor.modality, descriptor.kind, descriptor.isOperator,
descriptor.isOperator, descriptor.isInfix, descriptor.isInline, descriptor.isTailrec, descriptor.isInfix, descriptor.isInline, descriptor.isTailrec, descriptor.isExternal, descriptor.isSuspend
descriptor.isExternal, descriptor.isSuspend
) )
if (flags != builder.flags) { if (flags != builder.flags) {
builder.flags = flags builder.flags = flags
@@ -237,11 +220,9 @@ class DescriptorSerializer private constructor(
builder.name = getSimpleNameIndex(descriptor.name) builder.name = getSimpleNameIndex(descriptor.name)
if (useTypeTable()) { if (useTypeTable()) {
//noinspection ConstantConditions
builder.returnTypeId = local.typeId(descriptor.returnType!!) builder.returnTypeId = local.typeId(descriptor.returnType!!)
} }
else { else {
//noinspection ConstantConditions
builder.setReturnType(local.type(descriptor.returnType!!)) builder.setReturnType(local.type(descriptor.returnType!!))
} }
@@ -337,8 +318,10 @@ class DescriptorSerializer private constructor(
private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder { private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder {
val builder = ProtoBuf.ValueParameter.newBuilder() val builder = ProtoBuf.ValueParameter.newBuilder()
val flags = Flags.getValueParameterFlags(hasAnnotations(descriptor), descriptor.declaresDefaultValue(), val flags = Flags.getValueParameterFlags(
descriptor.isCrossinline, descriptor.isNoinline, descriptor.isCoroutine) hasAnnotations(descriptor), descriptor.declaresDefaultValue(),
descriptor.isCrossinline, descriptor.isNoinline, descriptor.isCoroutine
)
if (flags != builder.flags) { if (flags != builder.flags) {
builder.flags = flags builder.flags = flags
} }
@@ -399,9 +382,7 @@ class DescriptorSerializer private constructor(
return builder return builder
} }
private fun typeId(type: KotlinType): Int { private fun typeId(type: KotlinType): Int = typeTable[type(type)]
return typeTable[type(type)]
}
private fun type(type: KotlinType): ProtoBuf.Type.Builder { private fun type(type: KotlinType): ProtoBuf.Type.Builder {
val builder = ProtoBuf.Type.newBuilder() val builder = ProtoBuf.Type.newBuilder()
@@ -416,7 +397,7 @@ class DescriptorSerializer private constructor(
val lowerBound = type(flexibleType.lowerBound) val lowerBound = type(flexibleType.lowerBound)
val upperBound = type(flexibleType.upperBound) val upperBound = type(flexibleType.upperBound)
extension.serializeFlexibleType(flexibleType, lowerBound, upperBound); extension.serializeFlexibleType(flexibleType, lowerBound, upperBound)
if (useTypeTable()) { if (useTypeTable()) {
lowerBound.flexibleUpperBoundId = typeTable[upperBound] lowerBound.flexibleUpperBoundId = typeTable[upperBound]
} }
@@ -427,24 +408,21 @@ class DescriptorSerializer private constructor(
} }
val descriptor = type.constructor.declarationDescriptor val descriptor = type.constructor.declarationDescriptor
if (descriptor is ClassDescriptor) { when (descriptor) {
val possiblyInnerType = type.buildPossiblyInnerType() ?: error("possiblyInnerType should not be null in case of class") is ClassDescriptor, is TypeAliasDescriptor -> {
val possiblyInnerType = type.buildPossiblyInnerType() ?: error("possiblyInnerType should not be null: $type")
fillFromPossiblyInnerType(builder, possiblyInnerType) fillFromPossiblyInnerType(builder, possiblyInnerType)
}
else if (descriptor is TypeParameterDescriptor) {
if (descriptor.containingDeclaration === containingDeclaration) {
builder.typeParameterName = getSimpleNameIndex(descriptor.name)
}
else {
builder.typeParameter = getTypeParameterId(descriptor)
} }
is TypeParameterDescriptor -> {
if (descriptor.containingDeclaration === containingDeclaration) {
builder.typeParameterName = getSimpleNameIndex(descriptor.name)
}
else {
builder.typeParameter = getTypeParameterId(descriptor)
}
assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: " + descriptor } assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: $descriptor" }
} }
else if (descriptor is TypeAliasDescriptor) {
val possiblyInnerType = type.buildPossiblyInnerType() ?: error("possiblyInnerType should not be null in case of type alias")
fillFromPossiblyInnerType(builder, possiblyInnerType)
} }
if (type.isMarkedNullable != builder.nullable) { if (type.isMarkedNullable != builder.nullable) {
@@ -466,16 +444,12 @@ class DescriptorSerializer private constructor(
return builder return builder
} }
private fun fillFromPossiblyInnerType( private fun fillFromPossiblyInnerType(builder: ProtoBuf.Type.Builder, type: PossiblyInnerType) {
builder: ProtoBuf.Type.Builder,
type: PossiblyInnerType) {
val classifierDescriptor = type.classifierDescriptor val classifierDescriptor = type.classifierDescriptor
val classifierId = getClassifierId(classifierDescriptor) val classifierId = getClassifierId(classifierDescriptor)
if (classifierDescriptor is ClassDescriptor) { when (classifierDescriptor) {
builder.className = classifierId is ClassDescriptor -> builder.className = classifierId
} is TypeAliasDescriptor -> builder.typeAliasName = classifierId
else if (classifierDescriptor is TypeAliasDescriptor) {
builder.typeAliasName = classifierId
} }
for (projection in type.arguments) { for (projection in type.arguments) {
@@ -491,7 +465,6 @@ class DescriptorSerializer private constructor(
else { else {
builder.setOuterType(outerBuilder) builder.setOuterType(outerBuilder)
} }
} }
} }
@@ -519,24 +492,22 @@ class DescriptorSerializer private constructor(
return builder return builder
} }
@JvmOverloads fun packageProto( @JvmOverloads
fragments: Collection<PackageFragmentDescriptor>, fun packageProto(
skip: Function1<DeclarationDescriptor, Boolean>? = null): ProtoBuf.Package.Builder { fragments: Collection<PackageFragmentDescriptor>, skip: ((DeclarationDescriptor) -> Boolean)? = null
): ProtoBuf.Package.Builder {
val builder = ProtoBuf.Package.newBuilder() val builder = ProtoBuf.Package.newBuilder()
val members = ArrayList<DeclarationDescriptor>() val members = fragments.flatMap { fragment ->
for (fragment in fragments) { DescriptorUtils.getAllDescriptors(fragment.getMemberScope())
members.addAll(DescriptorUtils.getAllDescriptors(fragment.getMemberScope()))
} }
for (declaration in sort(members)) { for (declaration in sort(members)) {
if (skip != null && skip.invoke(declaration)) continue if (skip?.invoke(declaration) == true) continue
if (declaration is PropertyDescriptor) { when (declaration) {
builder.addProperty(propertyProto(declaration)) is PropertyDescriptor -> builder.addProperty(propertyProto(declaration))
} is FunctionDescriptor -> builder.addFunction(functionProto(declaration))
else if (declaration is FunctionDescriptor) {
builder.addFunction(functionProto(declaration))
} }
} }
@@ -554,14 +525,10 @@ class DescriptorSerializer private constructor(
val builder = ProtoBuf.Package.newBuilder() val builder = ProtoBuf.Package.newBuilder()
for (declaration in sort(members)) { for (declaration in sort(members)) {
if (declaration is PropertyDescriptor) { when (declaration) {
builder.addProperty(propertyProto(declaration)) is PropertyDescriptor -> builder.addProperty(propertyProto(declaration))
} is FunctionDescriptor -> builder.addFunction(functionProto(declaration))
else if (declaration is FunctionDescriptor) { is TypeAliasDescriptor -> builder.addTypeAlias(typeAliasProto(declaration))
builder.addFunction(functionProto(declaration))
}
else if (declaration is TypeAliasDescriptor) {
builder.addTypeAlias(typeAliasProto(declaration))
} }
} }
@@ -575,27 +542,24 @@ class DescriptorSerializer private constructor(
return builder return builder
} }
private fun getClassifierId(descriptor: ClassifierDescriptorWithTypeParameters): Int { private fun getClassifierId(descriptor: ClassifierDescriptorWithTypeParameters): Int =
return stringTable.getFqNameIndex(descriptor) stringTable.getFqNameIndex(descriptor)
}
private fun getSimpleNameIndex(name: Name): Int { private fun getSimpleNameIndex(name: Name): Int =
return stringTable.getStringIndex(name.asString()) stringTable.getStringIndex(name.asString())
}
private fun getTypeParameterId(descriptor: TypeParameterDescriptor): Int { private fun getTypeParameterId(descriptor: TypeParameterDescriptor): Int =
return typeParameters.intern(descriptor) typeParameters.intern(descriptor)
}
companion object { companion object {
@JvmStatic @JvmStatic
fun createTopLevel(extension: SerializerExtension): DescriptorSerializer { fun createTopLevel(extension: SerializerExtension): DescriptorSerializer {
return DescriptorSerializer(null, Interner<TypeParameterDescriptor>(), extension, MutableTypeTable(), false) return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), serializeTypeTableToFunction = false)
} }
@JvmStatic @JvmStatic
fun createForLambda(extension: SerializerExtension): DescriptorSerializer { fun createForLambda(extension: SerializerExtension): DescriptorSerializer {
return DescriptorSerializer(null, Interner<TypeParameterDescriptor>(), extension, MutableTypeTable(), true) return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), serializeTypeTableToFunction = true)
} }
@JvmStatic @JvmStatic
@@ -614,7 +578,8 @@ class DescriptorSerializer private constructor(
Interner(parentSerializer.typeParameters), Interner(parentSerializer.typeParameters),
parentSerializer.extension, parentSerializer.extension,
MutableTypeTable(), MutableTypeTable(),
false) serializeTypeTableToFunction = false
)
for (typeParameter in descriptor.declaredTypeParameters) { for (typeParameter in descriptor.declaredTypeParameters) {
serializer.typeParameters.intern(typeParameter) serializer.typeParameters.intern(typeParameter)
} }
@@ -627,37 +592,28 @@ class DescriptorSerializer private constructor(
accessor.visibility, accessor.visibility,
accessor.modality, accessor.modality,
!accessor.isDefault, !accessor.isDefault,
accessor.isExternal) accessor.isExternal
)
} }
private fun variance(variance: Variance): ProtoBuf.TypeParameter.Variance { private fun variance(variance: Variance): ProtoBuf.TypeParameter.Variance = when (variance) {
when (variance) { Variance.INVARIANT -> ProtoBuf.TypeParameter.Variance.INV
Variance.INVARIANT -> return ProtoBuf.TypeParameter.Variance.INV Variance.IN_VARIANCE -> ProtoBuf.TypeParameter.Variance.IN
Variance.IN_VARIANCE -> return ProtoBuf.TypeParameter.Variance.IN Variance.OUT_VARIANCE -> ProtoBuf.TypeParameter.Variance.OUT
Variance.OUT_VARIANCE -> return ProtoBuf.TypeParameter.Variance.OUT
}
throw IllegalStateException("Unknown variance: " + variance)
} }
private fun projection(projectionKind: Variance): ProtoBuf.Type.Argument.Projection { private fun projection(projectionKind: Variance): ProtoBuf.Type.Argument.Projection = when (projectionKind) {
when (projectionKind) { Variance.INVARIANT -> ProtoBuf.Type.Argument.Projection.INV
Variance.INVARIANT -> return ProtoBuf.Type.Argument.Projection.INV Variance.IN_VARIANCE -> ProtoBuf.Type.Argument.Projection.IN
Variance.IN_VARIANCE -> return ProtoBuf.Type.Argument.Projection.IN Variance.OUT_VARIANCE -> ProtoBuf.Type.Argument.Projection.OUT
Variance.OUT_VARIANCE -> return ProtoBuf.Type.Argument.Projection.OUT
}
throw IllegalStateException("Unknown projectionKind: " + projectionKind)
} }
private fun hasAnnotations(descriptor: Annotated): Boolean { private fun hasAnnotations(descriptor: Annotated): Boolean = !descriptor.annotations.isEmpty()
return !descriptor.annotations.isEmpty()
}
fun <T : DeclarationDescriptor> sort(descriptors: Collection<T>): List<T> { fun <T : DeclarationDescriptor> sort(descriptors: Collection<T>): List<T> =
val result = ArrayList(descriptors) ArrayList(descriptors).apply {
//NOTE: the exact comparator does matter here //NOTE: the exact comparator does matter here
Collections.sort(result, MemberComparator.INSTANCE) Collections.sort(this, MemberComparator.INSTANCE)
return result }
}
} }
} }
@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.types.KotlinType
abstract class SerializerExtension { abstract class SerializerExtension {
abstract val stringTable: StringTable abstract val stringTable: StringTable
open fun shouldUseTypeTable(): Boolean { open fun shouldUseTypeTable(): Boolean = false
return false
}
open fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { open fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
} }
@@ -58,6 +56,6 @@ abstract class SerializerExtension {
} }
open fun serializeErrorType(type: KotlinType, builder: ProtoBuf.Type.Builder) { open fun serializeErrorType(type: KotlinType, builder: ProtoBuf.Type.Builder) {
throw IllegalStateException("Cannot serialize error type: " + type) throw IllegalStateException("Cannot serialize error type: $type")
} }
} }
@@ -21,11 +21,9 @@ import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensionProtocol) : SerializerExtension() { open class KotlinSerializerExtensionBase(private val protocol: SerializerExtensionProtocol) : SerializerExtension() {
private val stringTable = StringTableImpl() override final val stringTable = StringTableImpl()
private val annotationSerializer = AnnotationSerializer(stringTable) private val annotationSerializer = AnnotationSerializer(stringTable)
override fun getStringTable(): StringTableImpl = stringTable
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) { override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
for (annotation in descriptor.annotations) { for (annotation in descriptor.annotations) {
proto.addExtension(protocol.classAnnotation, annotationSerializer.serializeAnnotation(annotation)) proto.addExtension(protocol.classAnnotation, annotationSerializer.serializeAnnotation(annotation))
@@ -18,22 +18,16 @@ package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.utils.*
import org.jetbrains.kotlin.utils.Interner
import java.io.IOException
import java.io.OutputStream
import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.utils.Interner
import java.io.OutputStream
class StringTableImpl : StringTable { class StringTableImpl : StringTable {
private class FqNameProto(val fqName: QualifiedName.Builder) { private class FqNameProto(val fqName: QualifiedName.Builder) {
override fun hashCode(): Int { override fun hashCode(): Int {
var result = 13 var result = 13
result = 31 * result + fqName.parentQualifiedName result = 31 * result + fqName.parentQualifiedName
@@ -42,47 +36,43 @@ class StringTableImpl : StringTable {
return result return result
} }
override fun equals(obj: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (obj == null || javaClass != obj.javaClass) return false if (other == null || other !is FqNameProto) return false
val other = (obj as FqNameProto).fqName val otherFqName = other.fqName
return fqName.parentQualifiedName == other.parentQualifiedName return fqName.parentQualifiedName == otherFqName.parentQualifiedName
&& fqName.shortName == other.shortName && fqName.shortName == otherFqName.shortName
&& fqName.kind == other.kind && fqName.kind == otherFqName.kind
} }
} }
private val strings = Interner<String>() private val strings = Interner<String>()
private val qualifiedNames = Interner<FqNameProto>() private val qualifiedNames = Interner<FqNameProto>()
fun getSimpleNameIndex(name: Name): Int { fun getSimpleNameIndex(name: Name): Int = getStringIndex(name.asString())
return getStringIndex(name.asString())
}
override fun getStringIndex(string: String): Int { override fun getStringIndex(string: String): Int = strings.intern(string)
return strings.intern(string)
}
override fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int { override fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int {
if (ErrorUtils.isError(descriptor)) { if (ErrorUtils.isError(descriptor)) {
throw IllegalStateException("Cannot get FQ name of error class: " + descriptor) throw IllegalStateException("Cannot get FQ name of error class: $descriptor")
} }
val builder = QualifiedName.newBuilder() val builder = QualifiedName.newBuilder()
builder.kind = QualifiedName.Kind.CLASS builder.kind = QualifiedName.Kind.CLASS
val containingDeclaration = descriptor.containingDeclaration val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is PackageFragmentDescriptor) { when (containingDeclaration) {
val packageFqName = containingDeclaration.fqName is PackageFragmentDescriptor -> {
if (!packageFqName.isRoot) { val packageFqName = containingDeclaration.fqName
builder.parentQualifiedName = getPackageFqNameIndex(packageFqName) if (!packageFqName.isRoot) {
builder.parentQualifiedName = getPackageFqNameIndex(packageFqName)
}
} }
} is ClassDescriptor -> {
else if (containingDeclaration is ClassDescriptor) { builder.parentQualifiedName = getFqNameIndex(containingDeclaration)
builder.parentQualifiedName = getFqNameIndex(containingDeclaration) }
} else -> throw IllegalStateException("Cannot get FQ name of local class: " + descriptor)
else {
throw IllegalStateException("Cannot get FQ name of local class: " + descriptor)
} }
builder.shortName = getStringIndex(descriptor.name.asString()) builder.shortName = getStringIndex(descriptor.name.asString())
@@ -118,14 +108,8 @@ class StringTableImpl : StringTable {
} }
override fun serializeTo(output: OutputStream) { override fun serializeTo(output: OutputStream) {
try { val (strings, qualifiedNames) = buildProto()
val protos = buildProto() strings.writeDelimitedTo(output)
protos.first.writeDelimitedTo(output) qualifiedNames.writeDelimitedTo(output)
protos.second.writeDelimitedTo(output)
}
catch (e: IOException) {
throw rethrow(e)
}
} }
} }