Fix impossibility to make @Optional field in a class hierarchy on JS

This commit is contained in:
Leonid Startsev
2019-02-12 14:38:24 +03:00
parent 18667a5a34
commit 66272bfa74
3 changed files with 25 additions and 13 deletions
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap
@@ -172,7 +173,13 @@ internal fun SerializerJsTranslator.serializerInstance(
} }
} }
fun TranslationContext.buildInitializersRemapping(forClass: KtPureClassOrObject): Map<PropertyDescriptor, KtExpression?> = forClass.run { fun TranslationContext.buildInitializersRemapping(
(bodyPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } + forClass: KtPureClassOrObject,
primaryPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.defaultValue }) superClass: ClassDescriptor?
): Map<PropertyDescriptor, KtExpression?> {
val myMap = (forClass.bodyPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } +
forClass.primaryPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.defaultValue })
val parentPsi = superClass?.takeIf { it.isInternalSerializable }?.findPsi() as? KtPureClassOrObject ?: return myMap
val parentMap = buildInitializersRemapping(parentPsi, superClass.getSuperClassNotAny())
return myMap + parentMap
} }
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers
@@ -44,7 +45,7 @@ class SerializableJsTranslator(
val context: TranslationContext val context: TranslationContext
) : SerializableCodegen(descriptor, context.bindingContext()) { ) : SerializableCodegen(descriptor, context.bindingContext()) {
private val initMap: Map<PropertyDescriptor, KtExpression?> = context.buildInitializersRemapping(declaration) private val initMap: Map<PropertyDescriptor, KtExpression?> = context.buildInitializersRemapping(declaration, descriptor.getSuperClassNotAny())
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) { override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) {
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo
@@ -131,26 +132,29 @@ class SerializerJsTranslator(descriptor: ClassDescriptor,
} }
private fun TranslationContext.referenceMethod(clazz: ClassDescriptor, name: String) = private fun TranslationContext.referenceMethod(clazz: ClassDescriptor, name: String) =
clazz.getFuncDesc(name).single().let { getNameForDescriptor(it) } getNameForDescriptor(clazz.getFuncDesc(name).single())
override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx -> override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx ->
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS) val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS) val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
val wBeginFunc = ctx.getNameForDescriptor( val wBeginFunc = ctx.getNameForDescriptor(
encoderClass.getFuncDesc(CallingConventions.begin).single { it.valueParameters.size == 2 }) encoderClass.getFuncDesc(CallingConventions.begin).single { it.valueParameters.size == 2 })
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(anySerialDescProperty!!), JsThisRef()) val serialClassDescRef = JsNameRef(context.getNameForDescriptor(anySerialDescProperty!!), JsThisRef())
val initializersMap: Map<PropertyDescriptor, KtExpression?> = context.buildInitializersRemapping(
(serializableDescriptor.findPsi() as? KtPureClassOrObject) val serializableSource = ((serializableDescriptor.findPsi() as? KtPureClassOrObject)
?: throw AssertionError("Serializable descriptor $serializableDescriptor must have source file to build initializers map") ?: throw AssertionError("Serializable descriptor $serializableDescriptor must have source file to build initializers map"))
) val initializersMap: Map<PropertyDescriptor, KtExpression?> =
context.buildInitializersRemapping(serializableSource, serializableDescriptor.getSuperClassNotAny())
// output.writeBegin(desc, []) // output.writeBegin(desc, [])
val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ -> val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ ->
JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef()) JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef())
} }
val call = JsInvocation(JsNameRef(wBeginFunc, JsNameRef(jsFun.parameters[0].name)), val call = JsInvocation(
serialClassDescRef, JsNameRef(wBeginFunc, JsNameRef(jsFun.parameters[0].name)),
JsArrayLiteral(typeParams)) serialClassDescRef,
JsArrayLiteral(typeParams)
)
val objRef = JsNameRef(jsFun.parameters[1].name) val objRef = JsNameRef(jsFun.parameters[1].name)
// output = output.writeBegin... // output = output.writeBegin...
val localOutputName = jsFun.scope.declareFreshName("output") val localOutputName = jsFun.scope.declareFreshName("output")