Fix serialization of type parameters inner generic class

The call to `createTopLevel` instead of `create` (which creates
serializers for outer classes properly, with correct type parameter
contexts) caused MetadataSerializer to write type parameter metadata
incorrectly.  For example, in the following case:

    class A<E> {
        inner class B<T, E> { ... }
    }

A's type parameter E would get id 0, and B's type parameters T and E
would get ids 0 and 1. This is a problem because ids are supposed to be
unique for each class including its outer classes, and deserializer,
decompiler and stub builder rely on this assumption.

JVM metadata is unaffected because `create` is called correctly there,
see MemberCodegen#generateKotlinClassMetadataAnnotation

 #KT-24944 Fixed
This commit is contained in:
Alexander Udalov
2018-06-19 15:55:46 +02:00
parent c05285a23c
commit 9309570752
11 changed files with 97 additions and 39 deletions
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.js
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isPreRelease
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -197,15 +196,16 @@ object KotlinJavascriptSerializationUtil {
}
val fileRegistry = KotlinFileRegistry()
val serializerExtension = KotlinJavascriptSerializerExtension(fileRegistry)
val serializer = DescriptorSerializer.createTopLevel(serializerExtension)
val extension = KotlinJavascriptSerializerExtension(fileRegistry)
val classDescriptors = scope.filterIsInstance<ClassDescriptor>().sortedBy { it.fqNameSafe.asString() }
fun serializeClasses(descriptors: Collection<DeclarationDescriptor>) {
fun serializeClass(classDescriptor: ClassDescriptor) {
if (skip(classDescriptor)) return
val classProto = serializer.classProto(classDescriptor).build() ?: error("Class not serialized: $classDescriptor")
val classProto =
DescriptorSerializer.create(classDescriptor, extension).classProto(classDescriptor).build()
?: error("Class not serialized: $classDescriptor")
builder.addClass_(classProto)
serializeClasses(classDescriptor.unsubstitutedInnerClassesScope.getContributedDescriptors())
}
@@ -219,10 +219,10 @@ object KotlinJavascriptSerializationUtil {
serializeClasses(classDescriptors)
val stringTable = serializerExtension.stringTable
val stringTable = extension.stringTable
val members = scope.filterNot(skip)
builder.`package` = serializer.packagePartProto(fqName, members).build()
builder.`package` = DescriptorSerializer.createTopLevel(extension).packagePartProto(fqName, members).build()
builder.setExtension(
JsProtoBuf.packageFragmentFiles,