Improve hack in BuiltInsSerializerExtension for ranges

Serialize class names as qualified names in the string table, not as
simple strings. Otherwise NameResolverImpl crashes on deserialization
because it expects that all class names are indices into QualifiedName
table
This commit is contained in:
Alexander Udalov
2017-05-17 16:06:08 +03:00
parent 6d47991172
commit 7f73e9f4f7
3 changed files with 21 additions and 26 deletions
@@ -17,17 +17,19 @@
package org.jetbrains.kotlin.serialization.builtins package org.jetbrains.kotlin.serialization.builtins
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnresolvedType import org.jetbrains.kotlin.types.UnresolvedType
class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) { class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
private val shortNameToFullName = mapOf( private val shortNameToClassId = mapOf(
"IntRange" to "kotlin/ranges/IntRange", "IntRange" to "kotlin.ranges.IntRange",
"LongRange" to "kotlin/ranges/LongRange", "LongRange" to "kotlin.ranges.LongRange",
"CharRange" to "kotlin/ranges/CharRange" "CharRange" to "kotlin.ranges.CharRange"
) ).mapValues { (_, value) -> ClassId.topLevel(FqName(value)) }
override fun shouldUseTypeTable(): Boolean = true override fun shouldUseTypeTable(): Boolean = true
@@ -37,9 +39,9 @@ class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSeriali
throw UnsupportedOperationException("Error types which are not UnresolvedType instances are not supported here: $unwrapped") throw UnsupportedOperationException("Error types which are not UnresolvedType instances are not supported here: $unwrapped")
} }
val fullName = shortNameToFullName[unwrapped.presentableName] val classId = shortNameToClassId[unwrapped.presentableName]
?: throw UnsupportedOperationException("Unsupported unresolved type: $unwrapped") ?: throw UnsupportedOperationException("Unsupported unresolved type: $unwrapped")
builder.className = stringTable.getStringIndex(fullName) builder.className = stringTable.getClassIdIndex(classId)
} }
} }
@@ -16,9 +16,7 @@
package org.jetbrains.kotlin.serialization package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import java.io.OutputStream import java.io.OutputStream
interface StringTable { interface StringTable {
@@ -16,11 +16,11 @@
package org.jetbrains.kotlin.serialization package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.name.ClassId
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.resolve.descriptorUtil.classId
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.types.ErrorUtils
import org.jetbrains.kotlin.utils.Interner import org.jetbrains.kotlin.utils.Interner
@@ -58,24 +58,19 @@ open class StringTableImpl : StringTable {
throw IllegalStateException("Cannot get FQ name of error class: $descriptor") throw IllegalStateException("Cannot get FQ name of error class: $descriptor")
} }
val classId = descriptor.classId ?: return getFqNameIndexOfLocalAnonymousClass(descriptor)
return getClassIdIndex(classId)
}
fun getClassIdIndex(classId: ClassId): Int {
val builder = QualifiedName.newBuilder() val builder = QualifiedName.newBuilder()
builder.kind = QualifiedName.Kind.CLASS builder.kind = QualifiedName.Kind.CLASS
val containingDeclaration = descriptor.containingDeclaration builder.parentQualifiedName =
when (containingDeclaration) { classId.outerClassId?.let(this::getClassIdIndex)
is PackageFragmentDescriptor -> { ?: getPackageFqNameIndex(classId.packageFqName)
val packageFqName = containingDeclaration.fqName
if (!packageFqName.isRoot) {
builder.parentQualifiedName = getPackageFqNameIndex(packageFqName)
}
}
is ClassDescriptor -> {
builder.parentQualifiedName = getFqNameIndex(containingDeclaration)
}
else -> return getFqNameIndexOfLocalAnonymousClass(descriptor)
}
builder.shortName = getStringIndex(descriptor.name.asString()) builder.shortName = getStringIndex(classId.shortClassName.asString())
return qualifiedNames.intern(FqNameProto(builder)) return qualifiedNames.intern(FqNameProto(builder))
} }