Introduce GeneratedSerializer and childSerializers
Descriptors passing on JVM
This commit is contained in:
committed by
Leonid Startsev
parent
f0e81c6eb8
commit
e40383b1ce
+14
@@ -42,6 +42,7 @@ abstract class SerializerCodegen(
|
|||||||
val prop = generateSerializableClassPropertyIfNeeded()
|
val prop = generateSerializableClassPropertyIfNeeded()
|
||||||
val save = generateSaveIfNeeded()
|
val save = generateSaveIfNeeded()
|
||||||
val load = generateLoadIfNeeded()
|
val load = generateLoadIfNeeded()
|
||||||
|
generateDescriptorGetterIfNeeded()
|
||||||
// if (save || load || prop)
|
// if (save || load || prop)
|
||||||
// generateSerialDesc()
|
// generateSerialDesc()
|
||||||
if (serializableDescriptor.declaredTypeParameters.isNotEmpty() && typedSerializerConstructorNotDeclared()) {
|
if (serializableDescriptor.declaredTypeParameters.isNotEmpty() && typedSerializerConstructorNotDeclared()) {
|
||||||
@@ -49,6 +50,19 @@ abstract class SerializerCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateDescriptorGetterIfNeeded(): Boolean {
|
||||||
|
val function = getMemberToGenerate(
|
||||||
|
serializerDescriptor, SerialEntityNames.GENERATED_DESCRIPTOR_GETTER.identifier,
|
||||||
|
{ true }, { true }
|
||||||
|
) ?: return false
|
||||||
|
generateChildSerializersGetter(function)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun generateChildSerializersGetter(function: FunctionDescriptor) {
|
||||||
|
// TODO()
|
||||||
|
}
|
||||||
|
|
||||||
// checks if user didn't declared constructor (KSerializer<T0>, KSerializer<T1>...) on a KSerializer<T<T0, T1...>>
|
// checks if user didn't declared constructor (KSerializer<T0>, KSerializer<T1>...) on a KSerializer<T<T0, T1...>>
|
||||||
private fun typedSerializerConstructorNotDeclared(): Boolean {
|
private fun typedSerializerConstructorNotDeclared(): Boolean {
|
||||||
val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializerDescriptor)?.arguments
|
val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializerDescriptor)?.arguments
|
||||||
|
|||||||
+54
-11
@@ -55,6 +55,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|||||||
// todo: extract packages constants too?
|
// todo: extract packages constants too?
|
||||||
internal val descType = Type.getObjectType("kotlinx/serialization/$SERIAL_DESCRIPTOR_CLASS")
|
internal val descType = Type.getObjectType("kotlinx/serialization/$SERIAL_DESCRIPTOR_CLASS")
|
||||||
internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/$SERIAL_DESCRIPTOR_CLASS_IMPL")
|
internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/$SERIAL_DESCRIPTOR_CLASS_IMPL")
|
||||||
|
internal val generatedSerializerType = Type.getObjectType("kotlinx/serialization/internal/${SerialEntityNames.GENERATED_SERIALIZER_CLASS}")
|
||||||
internal val kOutputType = Type.getObjectType("kotlinx/serialization/$STRUCTURE_ENCODER_CLASS")
|
internal val kOutputType = Type.getObjectType("kotlinx/serialization/$STRUCTURE_ENCODER_CLASS")
|
||||||
internal val encoderType = Type.getObjectType("kotlinx/serialization/$ENCODER_CLASS")
|
internal val encoderType = Type.getObjectType("kotlinx/serialization/$ENCODER_CLASS")
|
||||||
internal val decoderType = Type.getObjectType("kotlinx/serialization/$DECODER_CLASS")
|
internal val decoderType = Type.getObjectType("kotlinx/serialization/$DECODER_CLASS")
|
||||||
@@ -168,6 +169,32 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializerWithoutSti(
|
||||||
|
codegen: ClassBodyCodegen,
|
||||||
|
property: SerializableProperty,
|
||||||
|
serializerCodegen: AbstractSerialGenerator
|
||||||
|
): Boolean {
|
||||||
|
val serializer =
|
||||||
|
property.serializableWith?.toClassDescriptor
|
||||||
|
?: if (!property.type.isTypeParameter()) serializerCodegen.findTypeSerializerOrContext(
|
||||||
|
property.module,
|
||||||
|
property.type,
|
||||||
|
property.descriptor.annotations,
|
||||||
|
property.descriptor.findPsi()
|
||||||
|
) else null
|
||||||
|
return serializerCodegen.stackValueSerializerInstance(
|
||||||
|
codegen,
|
||||||
|
property.module,
|
||||||
|
property.type,
|
||||||
|
serializer,
|
||||||
|
this,
|
||||||
|
property.genericIndex
|
||||||
|
) { idx ->
|
||||||
|
load(0, kSerializerType)
|
||||||
|
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$idx", kSerializerType.descriptor)
|
||||||
|
}.also { if (it && property.type.isMarkedNullable) wrapStackValueIntoNullableSerializer() }
|
||||||
|
}
|
||||||
|
|
||||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, serializerCodegen: AbstractSerialGenerator): Boolean {
|
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, serializerCodegen: AbstractSerialGenerator): Boolean {
|
||||||
return serializerCodegen.stackValueSerializerInstance(
|
return serializerCodegen.stackValueSerializerInstance(
|
||||||
codegen, sti.property.module, sti.property.type,
|
codegen, sti.property.module, sti.property.type,
|
||||||
@@ -240,13 +267,19 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
}
|
}
|
||||||
// all serializers get arguments with serializers of their generic types
|
// all serializers get arguments with serializers of their generic types
|
||||||
argSerializers.forEach { (argType, argSerializer) ->
|
argSerializers.forEach { (argType, argSerializer) ->
|
||||||
assert(stackValueSerializerInstance(codegen, module, argType, argSerializer, this, argType.genericIndex, genericSerializerFieldGetter))
|
assert(
|
||||||
|
stackValueSerializerInstance(
|
||||||
|
codegen,
|
||||||
|
module,
|
||||||
|
argType,
|
||||||
|
argSerializer,
|
||||||
|
this,
|
||||||
|
argType.genericIndex,
|
||||||
|
genericSerializerFieldGetter
|
||||||
|
)
|
||||||
|
)
|
||||||
// wrap into nullable serializer if argType is nullable
|
// wrap into nullable serializer if argType is nullable
|
||||||
if (argType.isMarkedNullable) {
|
if (argType.isMarkedNullable) wrapStackValueIntoNullableSerializer()
|
||||||
invokestatic("kotlinx/serialization/internal/NullableSerializerKt", "makeNullable", // todo: extract?
|
|
||||||
"(" + kSerializerType.descriptor + ")" + kSerializerType.descriptor, false)
|
|
||||||
|
|
||||||
}
|
|
||||||
signature.append(kSerializerType.descriptor)
|
signature.append(kSerializerType.descriptor)
|
||||||
}
|
}
|
||||||
signature.append(")V")
|
signature.append(")V")
|
||||||
@@ -256,6 +289,12 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun InstructionAdapter.wrapStackValueIntoNullableSerializer() =
|
||||||
|
invokestatic(
|
||||||
|
"kotlinx/serialization/internal/NullableSerializerKt", "makeNullable",
|
||||||
|
"(" + kSerializerType.descriptor + ")" + kSerializerType.descriptor, false
|
||||||
|
)
|
||||||
|
|
||||||
//
|
//
|
||||||
// ======= Serializers Resolving =======
|
// ======= Serializers Resolving =======
|
||||||
//
|
//
|
||||||
@@ -291,11 +330,13 @@ fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty, ty
|
|||||||
// reference elements
|
// reference elements
|
||||||
serializer = property.module.findClassAcrossModuleDependencies(referenceArraySerializerId)
|
serializer = property.module.findClassAcrossModuleDependencies(referenceArraySerializerId)
|
||||||
}
|
}
|
||||||
// primitive elements are not supported yet
|
// primitive elements are not supported yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return JVMSerialTypeInfo(property, Type.getType("Ljava/lang/Object;"),
|
return JVMSerialTypeInfo(
|
||||||
if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
property, Type.getType("Ljava/lang/Object;"),
|
||||||
|
if (property.type.isMarkedNullable) "Nullable" else "", serializer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
OBJECT -> {
|
OBJECT -> {
|
||||||
// no explicit serializer for this property. Check other built in types
|
// no explicit serializer for this property. Check other built in types
|
||||||
@@ -312,8 +353,10 @@ fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty, ty
|
|||||||
property.descriptor.annotations,
|
property.descriptor.annotations,
|
||||||
property.descriptor.findPsi()
|
property.descriptor.findPsi()
|
||||||
)
|
)
|
||||||
return JVMSerialTypeInfo(property, Type.getType("Ljava/lang/Object;"),
|
return JVMSerialTypeInfo(
|
||||||
if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
property, Type.getType("Ljava/lang/Object;"),
|
||||||
|
if (property.type.isMarkedNullable) "Nullable" else "", serializer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> throw AssertionError("Unexpected sort for $type") // should not happen
|
else -> throw AssertionError("Unexpected sort for $type") // should not happen
|
||||||
}
|
}
|
||||||
|
|||||||
+96
-45
@@ -40,6 +40,9 @@ class SerializerCodegenImpl(
|
|||||||
private val serializerAsmType = codegen.typeMapper.mapClass(codegen.descriptor)
|
private val serializerAsmType = codegen.typeMapper.mapClass(codegen.descriptor)
|
||||||
private val serializableAsmType = codegen.typeMapper.mapClass(serializableClass)
|
private val serializableAsmType = codegen.typeMapper.mapClass(serializableClass)
|
||||||
|
|
||||||
|
// if we have type parameters, descriptor initializing must be performed in constructor
|
||||||
|
private val staticDescriptor = serializableDescriptor.declaredTypeParameters.isEmpty()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun generateSerializerExtensions(codegen: ImplementationBodyCodegen) {
|
fun generateSerializerExtensions(codegen: ImplementationBodyCodegen) {
|
||||||
val serializableClass = getSerializableClassDescriptorBySerializer(codegen.descriptor) ?: return
|
val serializableClass = getSerializableClassDescriptorBySerializer(codegen.descriptor) ?: return
|
||||||
@@ -55,64 +58,86 @@ class SerializerCodegenImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen.generateMethod(typedConstructorDescriptor) { _, _ ->
|
var locals: Int = 0
|
||||||
|
codegen.generateMethod(typedConstructorDescriptor) { _, exprGen ->
|
||||||
load(0, serializerAsmType)
|
load(0, serializerAsmType)
|
||||||
invokespecial("java/lang/Object", "<init>", "()V", false)
|
invokespecial("java/lang/Object", "<init>", "()V", false)
|
||||||
serializableDescriptor.declaredTypeParameters.forEachIndexed { i, _ ->
|
serializableDescriptor.declaredTypeParameters.forEachIndexed { i, _ ->
|
||||||
load(0, serializerAsmType)
|
load(0, serializerAsmType)
|
||||||
load(i+1, kSerializerType)
|
load(++locals, kSerializerType)
|
||||||
putfield(serializerAsmType.internalName, "$typeArgPrefix$i", kSerializerType.descriptor)
|
putfield(serializerAsmType.internalName, "$typeArgPrefix$i", kSerializerType.descriptor)
|
||||||
}
|
}
|
||||||
|
if (!staticDescriptor) exprGen.generateSerialDescriptor(++locals, false)
|
||||||
areturn(Type.VOID_TYPE)
|
areturn(Type.VOID_TYPE)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSerialDesc() {
|
private fun ExpressionCodegen.generateSerialDescriptor(descriptorVar: Int, isStatic: Boolean) = with(v) {
|
||||||
codegen.v.newField(OtherOrigin(codegen.myClass.psiOrParent), ACC_PRIVATE or ACC_STATIC or ACC_FINAL or ACC_SYNTHETIC,
|
anew(descImplType)
|
||||||
serialDescField, descType.descriptor, null, null)
|
dup()
|
||||||
// todo: lazy initialization of $$serialDesc that is performed only when save/load is invoked first time
|
aconst(serialName)
|
||||||
val expr = codegen.createOrGetClInitCodegen()
|
if (isStatic) {
|
||||||
with(expr.v) {
|
assert(serializerDescriptor.kind == ClassKind.OBJECT) { "Serializer for type without type parameters must be an object" }
|
||||||
val classDescVar = 0
|
// static descriptor means serializer is an object. it is safer to get it from correct field
|
||||||
anew(descImplType)
|
StackValue.singleton(serializerDescriptor, codegen.typeMapper).put(generatedSerializerType, this)
|
||||||
dup()
|
} else {
|
||||||
aconst(serialName)
|
load(0, serializerAsmType)
|
||||||
invokespecial(descImplType.internalName, "<init>", "(Ljava/lang/String;)V", false)
|
}
|
||||||
store(classDescVar, descImplType)
|
invokespecial(descImplType.internalName, "<init>", "(Ljava/lang/String;${generatedSerializerType.descriptor})V", false)
|
||||||
for (property in orderedProperties) {
|
store(descriptorVar, descImplType)
|
||||||
if (property.transient) continue
|
for (property in orderedProperties) {
|
||||||
load(classDescVar, descImplType)
|
if (property.transient) continue
|
||||||
aconst(property.name)
|
load(descriptorVar, descImplType)
|
||||||
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;)V", false)
|
aconst(property.name)
|
||||||
// pushing annotations
|
iconst(if (property.optional) 1 else 0)
|
||||||
for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
|
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;Z)V", false)
|
||||||
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
|
// pushing annotations
|
||||||
load(classDescVar, descImplType)
|
for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
|
||||||
expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
|
||||||
invokevirtual(
|
|
||||||
descImplType.internalName,
|
|
||||||
CallingConventions.addAnnotation,
|
|
||||||
"(Ljava/lang/annotation/Annotation;)V",
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// add annotations on class itself
|
|
||||||
for ((annotationClass, args, consParams) in serializableDescriptor.annotationsWithArguments()) {
|
|
||||||
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
|
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
|
||||||
load(classDescVar, descImplType)
|
load(descriptorVar, descImplType)
|
||||||
expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||||
invokevirtual(
|
invokevirtual(
|
||||||
descImplType.internalName,
|
descImplType.internalName,
|
||||||
CallingConventions.addClassAnnotation,
|
CallingConventions.addAnnotation,
|
||||||
"(Ljava/lang/annotation/Annotation;)V",
|
"(Ljava/lang/annotation/Annotation;)V",
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
load(classDescVar, descImplType)
|
|
||||||
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
|
||||||
}
|
}
|
||||||
|
// add annotations on class itself
|
||||||
|
for ((annotationClass, args, consParams) in serializableDescriptor.annotationsWithArguments()) {
|
||||||
|
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
|
||||||
|
load(descriptorVar, descImplType)
|
||||||
|
generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||||
|
invokevirtual(
|
||||||
|
descImplType.internalName,
|
||||||
|
CallingConventions.addClassAnnotation,
|
||||||
|
"(Ljava/lang/annotation/Annotation;)V",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (isStatic) {
|
||||||
|
load(descriptorVar, descImplType)
|
||||||
|
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
||||||
|
} else {
|
||||||
|
load(0, serializerAsmType)
|
||||||
|
load(descriptorVar, descImplType)
|
||||||
|
putfield(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateSerialDesc() {
|
||||||
|
var flags = ACC_PRIVATE or ACC_FINAL or ACC_SYNTHETIC
|
||||||
|
if (staticDescriptor) flags = flags or ACC_STATIC
|
||||||
|
codegen.v.newField(
|
||||||
|
OtherOrigin(codegen.myClass.psiOrParent), flags,
|
||||||
|
serialDescField, descType.descriptor, null, null
|
||||||
|
)
|
||||||
|
// todo: lazy initialization of $$serialDesc ?
|
||||||
|
if (!staticDescriptor) return
|
||||||
|
val expr = codegen.createOrGetClInitCodegen()
|
||||||
|
expr.generateSerialDescriptor(0, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ExpressionCodegen.generateSyntheticAnnotationOnStack(
|
private fun ExpressionCodegen.generateSyntheticAnnotationOnStack(
|
||||||
@@ -139,18 +164,44 @@ class SerializerCodegenImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InstructionAdapter.serialCLassDescToLocalVar(classDescVar: Int) {
|
// use null to put value on stack, use number to store it to var
|
||||||
getstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
private fun InstructionAdapter.stackSerialClassDesc(classDescVar: Int?) {
|
||||||
store(classDescVar, descType)
|
if (staticDescriptor)
|
||||||
|
getstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
||||||
|
else {
|
||||||
|
load(0, serializerAsmType)
|
||||||
|
getfield(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
||||||
|
}
|
||||||
|
classDescVar?.let { store(it, descType) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSerializableClassProperty(property: PropertyDescriptor) {
|
override fun generateSerializableClassProperty(property: PropertyDescriptor) {
|
||||||
codegen.generateMethod(property.getter!!) { _, _ ->
|
codegen.generateMethod(property.getter!!) { _, _ ->
|
||||||
getstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
|
stackSerialClassDesc(null)
|
||||||
areturn(descType)
|
areturn(descType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun generateChildSerializersGetter(function: FunctionDescriptor) {
|
||||||
|
codegen.generateMethod(function) { _, _ ->
|
||||||
|
val size = orderedProperties.size
|
||||||
|
iconst(size)
|
||||||
|
newarray(kSerializerType)
|
||||||
|
for (i in 0 until size) {
|
||||||
|
dup() // array
|
||||||
|
iconst(i) // index
|
||||||
|
val prop = orderedProperties[i]
|
||||||
|
stackValueSerializerInstanceFromSerializerWithoutSti(
|
||||||
|
codegen,
|
||||||
|
prop,
|
||||||
|
this@SerializerCodegenImpl
|
||||||
|
)
|
||||||
|
astore(kSerializerType)
|
||||||
|
}
|
||||||
|
areturn(kSerializerArrayType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateSave(
|
override fun generateSave(
|
||||||
function: FunctionDescriptor
|
function: FunctionDescriptor
|
||||||
) {
|
) {
|
||||||
@@ -159,7 +210,7 @@ class SerializerCodegenImpl(
|
|||||||
val outputVar = 1
|
val outputVar = 1
|
||||||
val objVar = 2
|
val objVar = 2
|
||||||
val descVar = 3
|
val descVar = 3
|
||||||
serialCLassDescToLocalVar(descVar)
|
stackSerialClassDesc(descVar)
|
||||||
val objType = signature.valueParameters[1].asmType
|
val objType = signature.valueParameters[1].asmType
|
||||||
// output = output.writeBegin(classDesc, new KSerializer[0])
|
// output = output.writeBegin(classDesc, new KSerializer[0])
|
||||||
load(outputVar, encoderType)
|
load(outputVar, encoderType)
|
||||||
@@ -236,7 +287,7 @@ class SerializerCodegenImpl(
|
|||||||
val blocksCnt = orderedProperties.size / OPT_MASK_BITS + 1
|
val blocksCnt = orderedProperties.size / OPT_MASK_BITS + 1
|
||||||
fun bitMaskOff(i: Int) = bitMaskBase + (i / OPT_MASK_BITS) * OPT_MASK_TYPE.size
|
fun bitMaskOff(i: Int) = bitMaskBase + (i / OPT_MASK_BITS) * OPT_MASK_TYPE.size
|
||||||
val propsStartVar = bitMaskBase + OPT_MASK_TYPE.size * blocksCnt
|
val propsStartVar = bitMaskBase + OPT_MASK_TYPE.size * blocksCnt
|
||||||
serialCLassDescToLocalVar(descVar)
|
stackSerialClassDesc(descVar)
|
||||||
// boolean readAll = false
|
// boolean readAll = false
|
||||||
iconst(0)
|
iconst(0)
|
||||||
store(readAllVar, Type.BOOLEAN_TYPE)
|
store(readAllVar, Type.BOOLEAN_TYPE)
|
||||||
|
|||||||
+16
-7
@@ -35,21 +35,26 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackage
|
|||||||
|
|
||||||
|
|
||||||
fun isKSerializer(type: KotlinType?): Boolean =
|
fun isKSerializer(type: KotlinType?): Boolean =
|
||||||
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, SerialEntityNames.KSERIALIZER_NAME_FQ)
|
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, SerialEntityNames.KSERIALIZER_NAME_FQ)
|
||||||
|
|
||||||
|
fun isGeneratedKSerializer(type: KotlinType?): Boolean =
|
||||||
|
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, SerialEntityNames.GENERATED_SERIALIZER_FQ)
|
||||||
|
|
||||||
fun ClassDescriptor.getKSerializerDescriptor(): ClassDescriptor =
|
fun ClassDescriptor.getKSerializerDescriptor(): ClassDescriptor =
|
||||||
module.findClassAcrossModuleDependencies(ClassId(packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!
|
module.getClassFromInternalSerializationPackage(SerialEntityNames.GENERATED_SERIALIZER_CLASS.identifier)
|
||||||
|
|
||||||
|
|
||||||
fun ClassDescriptor.getKSerializerType(argument: SimpleType): SimpleType {
|
fun ClassDescriptor.createGeneratedSerializerTypeFor(argument: SimpleType): SimpleType {
|
||||||
val projectionType = Variance.INVARIANT
|
val projectionType = Variance.INVARIANT
|
||||||
val types = listOf(TypeProjectionImpl(projectionType, argument))
|
val types = listOf(TypeProjectionImpl(projectionType, argument))
|
||||||
return KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, getKSerializerDescriptor(), types)
|
return KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, getKSerializerDescriptor(), types)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun extractKSerializerArgumentFromImplementation(implementationClass: ClassDescriptor): KotlinType? {
|
internal fun extractKSerializerArgumentFromImplementation(implementationClass: ClassDescriptor): KotlinType? {
|
||||||
val kSerializerSupertype = implementationClass.typeConstructor.supertypes
|
val supertypes = implementationClass.typeConstructor.supertypes
|
||||||
.find { isKSerializer(it) } ?: return null
|
val kSerializerSupertype = supertypes.find { isGeneratedKSerializer(it) }
|
||||||
|
?: supertypes.find { isKSerializer(it) }
|
||||||
|
?: return null
|
||||||
return kSerializerSupertype.arguments.first().type
|
return kSerializerSupertype.arguments.first().type
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +145,11 @@ fun getSerializableClassDescriptorByCompanion(thisDescriptor: ClassDescriptor):
|
|||||||
fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? {
|
fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? {
|
||||||
val serializerForClass = serializerDescriptor.annotations.serializerForClass
|
val serializerForClass = serializerDescriptor.annotations.serializerForClass
|
||||||
if (serializerForClass != null) return serializerForClass.toClassDescriptor
|
if (serializerForClass != null) return serializerForClass.toClassDescriptor
|
||||||
if (serializerDescriptor.name != SerialEntityNames.SERIALIZER_CLASS_NAME) return null
|
if (serializerDescriptor.name !in setOf(
|
||||||
|
SerialEntityNames.SERIALIZER_CLASS_NAME,
|
||||||
|
SerialEntityNames.GENERATED_SERIALIZER_CLASS
|
||||||
|
)
|
||||||
|
) return null
|
||||||
val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
|
val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
|
||||||
if (!classDescriptor.isInternalSerializable) return null
|
if (!classDescriptor.isInternalSerializable) return null
|
||||||
return classDescriptor
|
return classDescriptor
|
||||||
@@ -187,7 +196,7 @@ private fun ModuleDescriptor.getFromPackage(packageFqName: FqName, classSimpleNa
|
|||||||
Name.identifier(classSimpleName)
|
Name.identifier(classSimpleName)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) { "Can't locate class $classSimpleName" }
|
) { "Can't locate class $classSimpleName from package $packageFqName" }
|
||||||
|
|
||||||
fun ClassDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
|
fun ClassDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
|
||||||
requireNotNull(module.findClassAcrossModuleDependencies(ClassId(packageFqName, Name.identifier(classSimpleName)))) {"Can't locate class $classSimpleName"}
|
requireNotNull(module.findClassAcrossModuleDependencies(ClassId(packageFqName, Name.identifier(classSimpleName)))) {"Can't locate class $classSimpleName"}
|
||||||
|
|||||||
+9
-16
@@ -57,7 +57,7 @@ object KSerializerDescriptorResolver {
|
|||||||
fun addSerializerSupertypes(classDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
|
fun addSerializerSupertypes(classDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {
|
||||||
val serializableClassDescriptor = getSerializableClassDescriptorBySerializer(classDescriptor) ?: return
|
val serializableClassDescriptor = getSerializableClassDescriptorBySerializer(classDescriptor) ?: return
|
||||||
if (supertypes.none(::isKSerializer)) {
|
if (supertypes.none(::isKSerializer)) {
|
||||||
supertypes.add(classDescriptor.getKSerializerType(serializableClassDescriptor.defaultType))
|
supertypes.add(classDescriptor.createGeneratedSerializerTypeFor(serializableClassDescriptor.defaultType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,16 +157,15 @@ object KSerializerDescriptorResolver {
|
|||||||
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
|
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == SerialEntityNames.SAVE_NAME &&
|
val isSave = name == SerialEntityNames.SAVE_NAME &&
|
||||||
shouldAddSerializerFunction { classDescriptor.checkSaveMethodParameters(it.valueParameters) }
|
shouldAddSerializerFunction { classDescriptor.checkSaveMethodParameters(it.valueParameters) }
|
||||||
) {
|
val isLoad = name == SerialEntityNames.LOAD_NAME &&
|
||||||
result.add(createSaveFunctionDescriptor(thisDescriptor))
|
shouldAddSerializerFunction { classDescriptor.checkLoadMethodParameters(it.valueParameters) }
|
||||||
}
|
val isDescriptorGetter = name == SerialEntityNames.GENERATED_DESCRIPTOR_GETTER &&
|
||||||
|
shouldAddSerializerFunction { true /* TODO? */ }
|
||||||
|
|
||||||
if (name == SerialEntityNames.LOAD_NAME &&
|
if (isSave || isLoad || isDescriptorGetter) {
|
||||||
shouldAddSerializerFunction { classDescriptor.checkLoadMethodParameters(it.valueParameters) }
|
result.add(doCreateSerializerFunction(thisDescriptor, name))
|
||||||
) {
|
|
||||||
result.add(createLoadFunctionDescriptor(thisDescriptor))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,12 +175,6 @@ object KSerializerDescriptorResolver {
|
|||||||
): PropertyDescriptor =
|
): PropertyDescriptor =
|
||||||
doCreateSerializerProperty(companionDescriptor, classDescriptor, SerialEntityNames.SERIAL_DESC_FIELD_NAME)
|
doCreateSerializerProperty(companionDescriptor, classDescriptor, SerialEntityNames.SERIAL_DESC_FIELD_NAME)
|
||||||
|
|
||||||
fun createSaveFunctionDescriptor(companionDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
|
||||||
doCreateSerializerFunction(companionDescriptor, SerialEntityNames.SAVE_NAME)
|
|
||||||
|
|
||||||
fun createLoadFunctionDescriptor(companionDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
|
||||||
doCreateSerializerFunction(companionDescriptor, SerialEntityNames.LOAD_NAME)
|
|
||||||
|
|
||||||
private fun doCreateSerializerProperty(
|
private fun doCreateSerializerProperty(
|
||||||
companionDescriptor: ClassDescriptor,
|
companionDescriptor: ClassDescriptor,
|
||||||
classDescriptor: ClassDescriptor,
|
classDescriptor: ClassDescriptor,
|
||||||
|
|||||||
+4
@@ -38,6 +38,9 @@ object SerialEntityNames {
|
|||||||
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
|
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
|
||||||
val IMPL_NAME = Name.identifier("Impl")
|
val IMPL_NAME = Name.identifier("Impl")
|
||||||
|
|
||||||
|
val GENERATED_SERIALIZER_CLASS = Name.identifier("GeneratedSerializer")
|
||||||
|
val GENERATED_SERIALIZER_FQ = SerializationPackages.internalPackageFqName.child(GENERATED_SERIALIZER_CLASS)
|
||||||
|
|
||||||
const val ENCODER_CLASS = "Encoder"
|
const val ENCODER_CLASS = "Encoder"
|
||||||
const val STRUCTURE_ENCODER_CLASS = "CompositeEncoder"
|
const val STRUCTURE_ENCODER_CLASS = "CompositeEncoder"
|
||||||
const val DECODER_CLASS = "Decoder"
|
const val DECODER_CLASS = "Decoder"
|
||||||
@@ -58,6 +61,7 @@ object SerialEntityNames {
|
|||||||
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
|
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
|
||||||
val SAVE_NAME = Name.identifier(SAVE)
|
val SAVE_NAME = Name.identifier(SAVE)
|
||||||
val LOAD_NAME = Name.identifier(LOAD)
|
val LOAD_NAME = Name.identifier(LOAD)
|
||||||
|
val GENERATED_DESCRIPTOR_GETTER = Name.identifier("childSerializers")
|
||||||
val WRITE_SELF_NAME = Name.identifier("write\$Self")
|
val WRITE_SELF_NAME = Name.identifier("write\$Self")
|
||||||
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
|
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user