Extract descriptor-related behavior in StringTable to separate interface

Descriptor-related code is only needed to be able to compute
"replacement" names for local classes, which are different in JVM and JS
This commit is contained in:
Alexander Udalov
2018-03-09 17:29:06 +01:00
parent 043f4c3d01
commit acf357e9b5
12 changed files with 104 additions and 96 deletions
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.types.ErrorUtils
class AnnotationSerializer(private val stringTable: StringTable) {
class AnnotationSerializer(private val stringTable: DescriptorAwareStringTable) {
fun serializeAnnotation(annotation: AnnotationDescriptor): ProtoBuf.Annotation = ProtoBuf.Annotation.newBuilder().apply {
val annotationClass = annotation.annotationClass ?: error("Annotation type is not a class: ${annotation.type}")
if (ErrorUtils.isError(annotationClass)) {
@@ -79,7 +79,7 @@ class AnnotationSerializer(private val stringTable: StringTable) {
override fun visitEnumValue(value: EnumValue, data: Unit) {
type = Type.ENUM
classId = stringTable.getClassIdIndex(value.enumClassId)
classId = stringTable.getQualifiedClassNameIndex(value.enumClassId.asString(), value.enumClassId.isLocal)
enumValueId = stringTable.getStringIndex(value.enumEntryName.asString())
}
@@ -48,7 +48,7 @@ class DescriptorSerializer private constructor(
DescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, versionRequirementTable,
serializeTypeTableToFunction = false)
val stringTable: StringTable
val stringTable: DescriptorAwareStringTable
get() = extension.stringTable
private fun useTypeTable(): Boolean = extension.shouldUseTypeTable()
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.types.FlexibleType
import org.jetbrains.kotlin.types.KotlinType
abstract class SerializerExtension {
abstract val stringTable: StringTable
abstract val stringTable: DescriptorAwareStringTable
val annotationSerializer by lazy { AnnotationSerializer(stringTable) }
@@ -18,14 +18,33 @@ package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.ErrorUtils
import java.io.OutputStream
interface StringTable {
fun getStringIndex(string: String): Int
fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int
fun getClassIdIndex(classId: ClassId): Int
/**
* @param className the fully qualified name of some class in the format: `org/foo/bar/Test.Inner`
*/
fun getQualifiedClassNameIndex(className: String, isLocal: Boolean): Int
fun serializeTo(output: OutputStream)
}
interface DescriptorAwareStringTable : StringTable {
fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int {
if (ErrorUtils.isError(descriptor)) {
throw IllegalStateException("Cannot get FQ name of error class: $descriptor")
}
val classId = descriptor.classId
?: getLocalClassIdReplacement(descriptor)
?: throw IllegalStateException("Cannot get FQ name of local class: $descriptor")
return getQualifiedClassNameIndex(classId.asString(), classId.isLocal)
}
fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? = null
}
@@ -16,18 +16,14 @@
package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.ProtoBuf.QualifiedNameTable.QualifiedName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.utils.Interner
import java.io.OutputStream
open class StringTableImpl : StringTable {
open class StringTableImpl : DescriptorAwareStringTable {
private class FqNameProto(val fqName: QualifiedName.Builder) {
override fun hashCode(): Int {
var result = 13
@@ -50,25 +46,17 @@ open class StringTableImpl : StringTable {
private val strings = Interner<String>()
private val qualifiedNames = Interner<FqNameProto>()
fun getSimpleNameIndex(name: Name): Int = getStringIndex(name.asString())
override fun getStringIndex(string: String): Int = strings.intern(string)
override fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int {
if (ErrorUtils.isError(descriptor)) {
throw IllegalStateException("Cannot get FQ name of error class: $descriptor")
}
override fun getQualifiedClassNameIndex(className: String, isLocal: Boolean): Int =
getQualifiedClassNameIndex(ClassId.fromString(className, isLocal))
val classId = descriptor.classId ?: return getFqNameIndexOfLocalAnonymousClass(descriptor)
return getClassIdIndex(classId)
}
override fun getClassIdIndex(classId: ClassId): Int {
private fun getQualifiedClassNameIndex(classId: ClassId): Int {
val builder = QualifiedName.newBuilder()
builder.kind = QualifiedName.Kind.CLASS
builder.parentQualifiedName =
classId.outerClassId?.let(this::getClassIdIndex)
classId.outerClassId?.let(this::getQualifiedClassNameIndex)
?: getPackageFqNameIndex(classId.packageFqName)
builder.shortName = getStringIndex(classId.shortClassName.asString())
@@ -76,15 +64,11 @@ open class StringTableImpl : StringTable {
return qualifiedNames.intern(FqNameProto(builder))
}
open fun getFqNameIndexOfLocalAnonymousClass(descriptor: ClassifierDescriptorWithTypeParameters): Int {
throw IllegalStateException("Cannot get FQ name of local class: " + descriptor)
}
fun getPackageFqNameIndex(fqName: FqName): Int {
var result = -1
for (segment in fqName.pathSegments()) {
val builder = QualifiedName.newBuilder()
builder.shortName = getSimpleNameIndex(segment)
builder.shortName = getStringIndex(segment.asString())
if (result != -1) {
builder.parentQualifiedName = result
}