Serialize SinceKotlinInfo and SinceKotlinInfoTable

This commit is contained in:
Alexander Udalov
2016-12-14 16:07:51 +03:00
parent feeed98323
commit 5c1adb1258
4 changed files with 103 additions and 49 deletions
@@ -35,6 +35,7 @@ class DescriptorSerializer private constructor(
private val typeParameters: Interner<TypeParameterDescriptor>,
private val extension: SerializerExtension,
private val typeTable: MutableTypeTable,
private val sinceKotlinInfoTable: MutableSinceKotlinInfoTable,
private val serializeTypeTableToFunction: Boolean
) {
fun serialize(message: MessageLite): ByteArray {
@@ -45,7 +46,8 @@ class DescriptorSerializer private constructor(
}
private fun createChildSerializer(descriptor: DeclarationDescriptor): DescriptorSerializer =
DescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, serializeTypeTableToFunction = false)
DescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, sinceKotlinInfoTable,
serializeTypeTableToFunction = false)
val stringTable: StringTable
get() = extension.stringTable
@@ -121,6 +123,11 @@ class DescriptorSerializer private constructor(
builder.typeTable = typeTableProto
}
val sinceKotlinInfoProto = sinceKotlinInfoTable.serialize()
if (sinceKotlinInfoProto != null) {
builder.sinceKotlinInfoTable = sinceKotlinInfoProto
}
extension.serializeClass(classDescriptor, builder)
return builder
@@ -511,6 +518,11 @@ class DescriptorSerializer private constructor(
builder.typeTable = typeTableProto
}
val sinceKotlinInfoProto = sinceKotlinInfoTable.serialize()
if (sinceKotlinInfoProto != null) {
builder.sinceKotlinInfoTable = sinceKotlinInfoProto
}
extension.serializePackage(builder)
return builder
@@ -528,12 +540,14 @@ class DescriptorSerializer private constructor(
companion object {
@JvmStatic
fun createTopLevel(extension: SerializerExtension): DescriptorSerializer {
return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), serializeTypeTableToFunction = false)
return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), MutableSinceKotlinInfoTable(),
serializeTypeTableToFunction = false)
}
@JvmStatic
fun createForLambda(extension: SerializerExtension): DescriptorSerializer {
return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), serializeTypeTableToFunction = true)
return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), MutableSinceKotlinInfoTable(),
serializeTypeTableToFunction = true)
}
@JvmStatic
@@ -552,6 +566,7 @@ class DescriptorSerializer private constructor(
Interner(parentSerializer.typeParameters),
parentSerializer.extension,
MutableTypeTable(),
MutableSinceKotlinInfoTable(),
serializeTypeTableToFunction = false
)
for (typeParameter in descriptor.declaredTypeParameters) {
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("FINITE_BOUNDS_VIOLATION_IN_JAVA")
package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
import org.jetbrains.kotlin.utils.Interner
import java.util.*
private class TableElementWrapper<Element : GeneratedMessageLite.Builder<*, Element>>(val builder: Element) {
// If you'll try to optimize it using structured equals/hashCode, pay attention to extensions present in proto messages
private val bytes: ByteArray = builder.build().toByteArray()
private val hashCode: Int = Arrays.hashCode(bytes)
override fun hashCode() = hashCode
override fun equals(other: Any?) = other is TableElementWrapper<*> && Arrays.equals(bytes, other.bytes)
}
abstract class MutableTable<Element, Table, TableBuilder>
where Element : GeneratedMessageLite.Builder<*, Element>,
Table : GeneratedMessageLite,
TableBuilder : GeneratedMessageLite.Builder<Table, TableBuilder> {
private val interner = Interner<TableElementWrapper<Element>>()
protected abstract fun createTableBuilder(): TableBuilder
protected abstract fun addElement(builder: TableBuilder, element: Element)
operator fun get(type: Element): Int =
interner.intern(TableElementWrapper(type))
@Suppress("UNCHECKED_CAST")
fun serialize(): Table? =
if (interner.isEmpty) null
else createTableBuilder().apply {
for (obj in interner.allInternedObjects) {
addElement(this, obj.builder)
}
}.build() as Table
}
class MutableTypeTable : MutableTable<ProtoBuf.Type.Builder, ProtoBuf.TypeTable, ProtoBuf.TypeTable.Builder>() {
override fun createTableBuilder(): ProtoBuf.TypeTable.Builder = ProtoBuf.TypeTable.newBuilder()
override fun addElement(builder: ProtoBuf.TypeTable.Builder, element: ProtoBuf.Type.Builder) {
builder.addType(element)
}
}
class MutableSinceKotlinInfoTable : MutableTable<ProtoBuf.SinceKotlinInfo.Builder, ProtoBuf.SinceKotlinInfoTable, ProtoBuf.SinceKotlinInfoTable.Builder>() {
override fun createTableBuilder(): ProtoBuf.SinceKotlinInfoTable.Builder = ProtoBuf.SinceKotlinInfoTable.newBuilder()
override fun addElement(builder: ProtoBuf.SinceKotlinInfoTable.Builder, element: ProtoBuf.SinceKotlinInfo.Builder) {
builder.addInfo(element)
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.utils.Interner
import java.util.*
class MutableTypeTable {
class TypeWrapper(val type: ProtoBuf.Type.Builder) {
// If you'll try to optimize it using structured equals/hashCode, pay attention to extensions present in Type messages
private val bytes: ByteArray = type.build().toByteArray()
private val hashCode: Int = Arrays.hashCode(bytes)
override fun hashCode() = hashCode
override fun equals(other: Any?) = other is TypeWrapper && Arrays.equals(bytes, other.bytes)
}
val interner = Interner<TypeWrapper>()
operator fun get(type: ProtoBuf.Type.Builder): Int =
interner.intern(TypeWrapper(type))
fun serialize(): ProtoBuf.TypeTable? =
if (interner.isEmpty) null
else ProtoBuf.TypeTable.newBuilder().apply {
for (type in interner.allInternedObjects) {
addType(type.type)
}
}.build()
}
@@ -37,10 +37,22 @@ class SinceKotlinInfo(
val errorCode: Int?,
val message: String?
) {
class Version(val major: Int, val minor: Int, val patch: Int) {
data class Version(val major: Int, val minor: Int, val patch: Int = 0) {
fun asString(): String =
if (patch == 0) "$major.$minor" else "$major.$minor.$patch"
fun encode(
writeVersion: (Int) -> Unit,
writeVersionFull: (Int) -> Unit
) {
if (major > MAJOR_MASK || minor > MINOR_MASK || patch > PATCH_MASK) {
writeVersionFull(major or (minor shl 8) or (patch shl 16))
}
else if (this != DEFAULT) {
writeVersion(major or (minor shl MAJOR_BITS) or (patch shl (MAJOR_BITS + MINOR_BITS)))
}
}
override fun toString(): String = asString()
companion object {