From 0f7a356af84370576eaf875542b5b232961b7a83 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Wed, 15 Nov 2017 12:33:36 +0300 Subject: [PATCH] Extension points for synthetic function contributions Pass real type arguments serializers to runtime lib --- .../backend/js/SerializerJsTranslator.kt | 10 ++++++++-- .../backend/jvm/SerializerCodegenImpl.kt | 19 +++++++++++++++---- .../SerializationResolveExtension.kt | 7 +++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt index 4e715929db2..c744c2b10e7 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt @@ -123,9 +123,12 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject, val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef()) // output.writeBegin(desc, []) + val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ -> + JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef()) + } val call = JsInvocation(JsNameRef(wBeginFunc, JsNameRef(jsFun.parameters[0].name)), serialClassDescRef, - JsArrayLiteral()) + JsArrayLiteral(typeParams)) val objRef = JsNameRef(jsFun.parameters[1].name) // output = output.writeBegin... val localOutputName = jsFun.scope.declareFreshName("output") @@ -229,10 +232,13 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject, +JsVars(localProps.map { JsVars.JsVar(it.name) }, true) //input = input.readBegin(...) + val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ -> + JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef()) + } val inputVar = JsNameRef(jsFun.scope.declareFreshName("input")) val readBeginF = inputClass.getFuncDesc("readBegin").single() val call = JsInvocation(JsNameRef(context.getNameForDescriptor(readBeginF), JsNameRef(jsFun.parameters[0].name)), - serialClassDescRef, JsArrayLiteral()) + serialClassDescRef, JsArrayLiteral(typeParams)) +JsVars(JsVars.JsVar(inputVar.name, call)) // while(true) { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt index d66a2dc29d8..069b40026bc 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt @@ -140,8 +140,7 @@ class SerializerCodegenImpl( // output = output.writeBegin(classDesc, new KSerializer[0]) load(outputVar, kOutputType) load(descVar, descType) - iconst(0) - newarray(kSerializerType) // todo: use some predefined empty array + genArrayOfTypeParametersSerializers() invokevirtual(kOutputType.internalName, "writeBegin", "(" + descType.descriptor + kSerializerArrayType.descriptor + ")" + kOutputType.descriptor, false) @@ -184,6 +183,19 @@ class SerializerCodegenImpl( } } + internal fun InstructionAdapter.genArrayOfTypeParametersSerializers() { + val size = serializableDescriptor.declaredTypeParameters.size + iconst(size) + newarray(kSerializerType) // todo: use some predefined empty array, if size is 0 + for (i in 0 until size) { + dup() // array + iconst(i) // index + load(0, kSerializerType) // this.serialTypeI + getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$i", kSerializerType.descriptor) + astore(kSerializerType) + } + } + override fun generateLoad( function: FunctionDescriptor ) { @@ -218,8 +230,7 @@ class SerializerCodegenImpl( // input = input.readBegin(classDesc, new KSerializer[0]) load(inputVar, kInputType) load(descVar, descType) - iconst(0) - newarray(kSerializerType) // todo: use some predefined empty array + genArrayOfTypeParametersSerializers() invokevirtual(kInputType.internalName, "readBegin", "(" + descType.descriptor + kSerializerArrayType.descriptor + ")" + kInputType.descriptor, false) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt index 3f5997f8ba2..bea2c55e825 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.lazy.LazyClassContext import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver +import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable import org.jetbrains.kotlinx.serialization.compiler.resolve.serialInfoFqName import java.util.* @@ -37,6 +38,12 @@ class SerializationResolveExtension : SyntheticResolveExtension { else -> listOf() } + override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List = when { + thisDescriptor.isCompanionObject && getSerializableClassDescriptorByCompanion(thisDescriptor) != null -> + listOf(KSerializerDescriptorResolver.SERIALIZER_PROVIDER_NAME) + else -> emptyList() + } + override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name, ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, result: MutableSet) { if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == KSerializerDescriptorResolver.IMPL_NAME) result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx))