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.KtPureClassOrObject
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.typeUtil.isTypeParameter
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 {
(bodyPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.delegateExpressionOrInitializer } +
primaryPropertiesDescriptorsMap(bindingContext()).mapValues { it.value.defaultValue })
fun TranslationContext.buildInitializersRemapping(
forClass: KtPureClassOrObject,
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.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers
@@ -44,7 +45,7 @@ class SerializableJsTranslator(
val context: TranslationContext
) : 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) {
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
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) =
clazz.getFuncDesc(name).single().let { getNameForDescriptor(it) }
getNameForDescriptor(clazz.getFuncDesc(name).single())
override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx ->
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
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 initializersMap: Map<PropertyDescriptor, KtExpression?> = context.buildInitializersRemapping(
(serializableDescriptor.findPsi() as? KtPureClassOrObject)
?: throw AssertionError("Serializable descriptor $serializableDescriptor must have source file to build initializers map")
)
val serializableSource = ((serializableDescriptor.findPsi() as? KtPureClassOrObject)
?: 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, [])
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(typeParams))
val call = JsInvocation(
JsNameRef(wBeginFunc, JsNameRef(jsFun.parameters[0].name)),
serialClassDescRef,
JsArrayLiteral(typeParams)
)
val objRef = JsNameRef(jsFun.parameters[1].name)
// output = output.writeBegin...
val localOutputName = jsFun.scope.declareFreshName("output")