Use EnumSerializer for explicitly serializable enum instead of auto-generated
Resolves Kotlin/kotlinx.serialization#683 Kotlin/kotlinx.serialization#1372
This commit is contained in:
+4
-1
@@ -33,7 +33,10 @@ abstract class SerializableCompanionCodegen(
|
|||||||
"probably clash with user-defined function has occurred"
|
"probably clash with user-defined function has occurred"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (serializableDescriptor.isSerializableObject || serializableDescriptor.isAbstractOrSealedSerializableClass()) {
|
if (serializableDescriptor.isSerializableObject
|
||||||
|
|| serializableDescriptor.isAbstractOrSealedSerializableClass()
|
||||||
|
|| serializableDescriptor.isSerializableEnum()
|
||||||
|
) {
|
||||||
generateLazySerializerGetter(serializerGetterDescriptor)
|
generateLazySerializerGetter(serializerGetterDescriptor)
|
||||||
} else {
|
} else {
|
||||||
generateSerializerGetter(serializerGetterDescriptor)
|
generateSerializerGetter(serializerGetterDescriptor)
|
||||||
|
|||||||
+1
-1
@@ -225,7 +225,7 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
|
|||||||
|
|
||||||
fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||||
val classDescriptor = kType.toClassDescriptor ?: return null
|
val classDescriptor = kType.toClassDescriptor ?: return null
|
||||||
return if (classDescriptor.kind == ClassKind.ENUM_CLASS && !classDescriptor.isInternallySerializableEnum())
|
return if (classDescriptor.kind == ClassKind.ENUM_CLASS && !classDescriptor.isEnumWithLegacyGeneratedSerializer())
|
||||||
module.findClassAcrossModuleDependencies(enumSerializerId)
|
module.findClassAcrossModuleDependencies(enumSerializerId)
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-6
@@ -52,6 +52,12 @@ interface IrBuilderExtension {
|
|||||||
private val throwMissedFieldExceptionArrayFunc
|
private val throwMissedFieldExceptionArrayFunc
|
||||||
get() = compilerContext.referenceFunctions(SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_FQ).singleOrNull()
|
get() = compilerContext.referenceFunctions(SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_FQ).singleOrNull()
|
||||||
|
|
||||||
|
private val enumSerializerFactoryFunc
|
||||||
|
get() = compilerContext.referenceFunctions(SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_FQ).singleOrNull()
|
||||||
|
|
||||||
|
private val markedEnumSerializerFactoryFunc
|
||||||
|
get() = compilerContext.referenceFunctions(SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_FQ).singleOrNull()
|
||||||
|
|
||||||
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
||||||
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
||||||
}
|
}
|
||||||
@@ -1041,13 +1047,55 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
enumSerializerId -> {
|
enumSerializerId -> {
|
||||||
serializerClass = module.getClassFromInternalSerializationPackage(SpecialBuiltins.enumSerializer)
|
serializerClass = module.getClassFromInternalSerializationPackage(SpecialBuiltins.enumSerializer)
|
||||||
args = kType.toClassDescriptor!!.let { enumDesc ->
|
val enumDescriptor = kType.toClassDescriptor!!
|
||||||
listOf(
|
|
||||||
irString(enumDesc.serialName()),
|
|
||||||
irCall(findEnumValuesMethod(enumDesc))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
typeArgs = listOf(thisIrType)
|
typeArgs = listOf(thisIrType)
|
||||||
|
// instantiate serializer only inside enum Companion
|
||||||
|
if (enclosingGenerator !is SerializableCompanionIrGenerator) {
|
||||||
|
// otherwise call Companion.serializer()
|
||||||
|
callSerializerFromCompanion(thisIrType, typeArgs, emptyList())?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
val enumArgs = mutableListOf(
|
||||||
|
irString(enumDescriptor.serialName()),
|
||||||
|
irCall(findEnumValuesMethod(enumDescriptor)),
|
||||||
|
)
|
||||||
|
|
||||||
|
val enumSerializerFactoryFunc = enumSerializerFactoryFunc
|
||||||
|
val markedEnumSerializerFactoryFunc = markedEnumSerializerFactoryFunc
|
||||||
|
if (enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null) {
|
||||||
|
// runtime contains enum serializer factory functions
|
||||||
|
val factoryFunc: IrSimpleFunctionSymbol = if (enumDescriptor.isEnumWithSerialInfoAnnotation()) {
|
||||||
|
// need to store SerialInfo annotation in descriptor
|
||||||
|
val enumEntries = enumDescriptor.enumEntries()
|
||||||
|
val entriesNames = enumEntries.map { it.annotations.serialNameValue?.let { n -> irString(n) } ?: irNull() }
|
||||||
|
val entriesAnnotations = enumEntries.map {
|
||||||
|
val annotationConstructors = it.annotations.mapNotNull { a ->
|
||||||
|
compilerContext.typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(a)
|
||||||
|
}
|
||||||
|
val annotationsConstructors = copyAnnotationsFrom(annotationConstructors)
|
||||||
|
if (annotationsConstructors.isEmpty()) {
|
||||||
|
irNull()
|
||||||
|
} else {
|
||||||
|
createArrayOfExpression(compilerContext.irBuiltIns.annotationType, annotationsConstructors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val annotationArrayType =
|
||||||
|
compilerContext.irBuiltIns.arrayClass.typeWith(compilerContext.irBuiltIns.annotationType.makeNullable())
|
||||||
|
|
||||||
|
enumArgs += createArrayOfExpression(compilerContext.irBuiltIns.stringType.makeNullable(), entriesNames)
|
||||||
|
enumArgs += createArrayOfExpression(annotationArrayType, entriesAnnotations)
|
||||||
|
|
||||||
|
markedEnumSerializerFactoryFunc
|
||||||
|
} else {
|
||||||
|
enumSerializerFactoryFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
val factoryReturnType = factoryFunc.owner.returnType.substitute(factoryFunc.owner.typeParameters, typeArgs)
|
||||||
|
return irInvoke(null, factoryFunc, typeArgs, enumArgs, factoryReturnType)
|
||||||
|
} else {
|
||||||
|
// support legacy serializer instantiation by constructor for old runtimes
|
||||||
|
args = enumArgs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
args = kType.arguments.map {
|
args = kType.arguments.map {
|
||||||
|
|||||||
+1
-1
@@ -566,7 +566,7 @@ open class SerializerIrGenerator(
|
|||||||
) {
|
) {
|
||||||
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
|
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
|
||||||
val generator = when {
|
val generator = when {
|
||||||
serializableDesc.isInternallySerializableEnum() -> SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
serializableDesc.isEnumWithLegacyGeneratedSerializer() -> SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
||||||
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
|
||||||
else -> SerializerIrGenerator(irClass, context, bindingContext, metadataPlugin, serialInfoJvmGenerator)
|
else -> SerializerIrGenerator(irClass, context, bindingContext, metadataPlugin, serialInfoJvmGenerator)
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-11
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor
|
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor
|
||||||
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
|
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
@@ -165,18 +166,65 @@ internal fun AbstractSerialGenerator.serializerInstance(
|
|||||||
serializerClass.classId == contextSerializerId || serializerClass.classId == polymorphicSerializerId -> listOf(
|
serializerClass.classId == contextSerializerId || serializerClass.classId == polymorphicSerializerId -> listOf(
|
||||||
ExpressionVisitor.getObjectKClass(context, kType.toClassDescriptor!!)
|
ExpressionVisitor.getObjectKClass(context, kType.toClassDescriptor!!)
|
||||||
)
|
)
|
||||||
serializerClass.classId == enumSerializerId -> listOf(
|
serializerClass.classId == enumSerializerId -> {
|
||||||
JsStringLiteral(kType.serialName()),
|
val enumDescriptor = kType.toClassDescriptor!!
|
||||||
// EnumClass.values() invocation
|
|
||||||
JsInvocation(
|
val enumArgs = mutableListOf(
|
||||||
context.getInnerNameForDescriptor(
|
JsStringLiteral(enumDescriptor.serialName()),
|
||||||
DescriptorUtils.getFunctionByName(
|
// EnumClass.values() invocation
|
||||||
kType.toClassDescriptor!!.staticScope,
|
JsInvocation(
|
||||||
StandardNames.ENUM_VALUES
|
context.getInnerNameForDescriptor(
|
||||||
)
|
DescriptorUtils.getFunctionByName(
|
||||||
).makeRef()
|
enumDescriptor.staticScope,
|
||||||
|
StandardNames.ENUM_VALUES
|
||||||
|
)
|
||||||
|
).makeRef()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
val packageScope = context.currentModule.getPackage(SerializationPackages.internalPackageFqName).memberScope
|
||||||
|
val enumSerializerFactoryFunc = DescriptorUtils.getFunctionByNameOrNull(
|
||||||
|
packageScope,
|
||||||
|
SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||||
|
)
|
||||||
|
val markedEnumSerializerFactoryFunc = DescriptorUtils.getFunctionByNameOrNull(
|
||||||
|
packageScope,
|
||||||
|
SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||||
|
)
|
||||||
|
if (enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null) {
|
||||||
|
// runtime contains enum serializer factory functions
|
||||||
|
val factoryFunc = if (enumDescriptor.isEnumWithSerialInfoAnnotation()) {
|
||||||
|
val enumEntries = enumDescriptor.enumEntries()
|
||||||
|
val entriesNames =
|
||||||
|
enumEntries.map { it.annotations.serialNameValue?.let { n -> JsStringLiteral(n) } ?: JsNullLiteral() }
|
||||||
|
|
||||||
|
val entriesAnnotations = enumEntries.map {
|
||||||
|
val annotationsConstructors = it.annotationsWithArguments().map { (annotationClass, args, _) ->
|
||||||
|
val argExprs = args.map { arg ->
|
||||||
|
Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
|
||||||
|
}
|
||||||
|
val classRef = context.translateQualifiedReference(annotationClass)
|
||||||
|
JsNew(classRef, argExprs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotationsConstructors.isEmpty()) {
|
||||||
|
JsNullLiteral()
|
||||||
|
} else {
|
||||||
|
JsArrayLiteral(annotationsConstructors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumArgs += JsArrayLiteral(entriesNames)
|
||||||
|
enumArgs += JsArrayLiteral(entriesAnnotations)
|
||||||
|
markedEnumSerializerFactoryFunc
|
||||||
|
} else {
|
||||||
|
enumSerializerFactoryFunc
|
||||||
|
}
|
||||||
|
return JsInvocation(context.getInnerReference(factoryFunc), enumArgs)
|
||||||
|
} else {
|
||||||
|
// support legacy serializer instantiation by constructor for old runtimes
|
||||||
|
enumArgs
|
||||||
|
}
|
||||||
|
}
|
||||||
serializerClass.classId == objectSerializerId -> listOf(
|
serializerClass.classId == objectSerializerId -> listOf(
|
||||||
JsStringLiteral(kType.serialName()),
|
JsStringLiteral(kType.serialName()),
|
||||||
context.serializerObjectGetter(kType.toClassDescriptor!!)
|
context.serializerObjectGetter(kType.toClassDescriptor!!)
|
||||||
|
|||||||
+1
-1
@@ -373,7 +373,7 @@ open class SerializerJsTranslator(
|
|||||||
metadataPlugin: SerializationDescriptorSerializerPlugin?
|
metadataPlugin: SerializationDescriptorSerializerPlugin?
|
||||||
) {
|
) {
|
||||||
val serializableDesc = getSerializableClassDescriptorBySerializer(descriptor) ?: return
|
val serializableDesc = getSerializableClassDescriptorBySerializer(descriptor) ?: return
|
||||||
if (serializableDesc.isInternallySerializableEnum()) {
|
if (serializableDesc.isEnumWithLegacyGeneratedSerializer()) {
|
||||||
SerializerForEnumsTranslator(descriptor, translator, context).generate()
|
SerializerForEnumsTranslator(descriptor, translator, context).generate()
|
||||||
} else {
|
} else {
|
||||||
SerializerJsTranslator(descriptor, translator, context, metadataPlugin).generate()
|
SerializerJsTranslator(descriptor, translator, context, metadataPlugin).generate()
|
||||||
|
|||||||
+132
-25
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
|||||||
import org.jetbrains.kotlin.load.kotlin.internalName
|
import org.jetbrains.kotlin.load.kotlin.internalName
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.ValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
@@ -38,7 +39,10 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUMS_FILE
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.PLUGIN_EXCEPTIONS_FILE
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.PLUGIN_EXCEPTIONS_FILE
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_CTOR_MARKER_NAME
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_CTOR_MARKER_NAME
|
||||||
@@ -68,7 +72,9 @@ internal val kOutputType = Type.getObjectType("kotlinx/serialization/encoding/$S
|
|||||||
internal val encoderType = Type.getObjectType("kotlinx/serialization/encoding/$ENCODER_CLASS")
|
internal val encoderType = Type.getObjectType("kotlinx/serialization/encoding/$ENCODER_CLASS")
|
||||||
internal val decoderType = Type.getObjectType("kotlinx/serialization/encoding/$DECODER_CLASS")
|
internal val decoderType = Type.getObjectType("kotlinx/serialization/encoding/$DECODER_CLASS")
|
||||||
internal val kInputType = Type.getObjectType("kotlinx/serialization/encoding/$STRUCTURE_DECODER_CLASS")
|
internal val kInputType = Type.getObjectType("kotlinx/serialization/encoding/$STRUCTURE_DECODER_CLASS")
|
||||||
|
|
||||||
internal val pluginUtilsType = Type.getObjectType("kotlinx/serialization/internal/${PLUGIN_EXCEPTIONS_FILE}Kt")
|
internal val pluginUtilsType = Type.getObjectType("kotlinx/serialization/internal/${PLUGIN_EXCEPTIONS_FILE}Kt")
|
||||||
|
internal val enumFactoriesType = Type.getObjectType("kotlinx/serialization/internal/${ENUMS_FILE}Kt")
|
||||||
|
|
||||||
internal val jvmLambdaType = Type.getObjectType("kotlin/jvm/internal/Lambda")
|
internal val jvmLambdaType = Type.getObjectType("kotlin/jvm/internal/Lambda")
|
||||||
internal val kotlinLazyType = Type.getObjectType("kotlin/Lazy")
|
internal val kotlinLazyType = Type.getObjectType("kotlin/Lazy")
|
||||||
@@ -84,6 +90,12 @@ internal val serializationExceptionName = "kotlinx/serialization/$SERIAL_EXC"
|
|||||||
internal val serializationExceptionMissingFieldName = "kotlinx/serialization/$MISSING_FIELD_EXC"
|
internal val serializationExceptionMissingFieldName = "kotlinx/serialization/$MISSING_FIELD_EXC"
|
||||||
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC"
|
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC"
|
||||||
|
|
||||||
|
private val annotationType = Type.getObjectType("java/lang/annotation/Annotation")
|
||||||
|
private val annotationArrayType = Type.getObjectType("[${annotationType.descriptor}")
|
||||||
|
private val doubleAnnotationArrayType = Type.getObjectType("[${annotationArrayType.descriptor}")
|
||||||
|
private val stringType = AsmTypes.JAVA_STRING_TYPE
|
||||||
|
private val stringArrayType = Type.getObjectType("[${stringType.descriptor}")
|
||||||
|
|
||||||
internal val descriptorGetterName = JvmAbi.getterName(SERIAL_DESC_FIELD)
|
internal val descriptorGetterName = JvmAbi.getterName(SERIAL_DESC_FIELD)
|
||||||
internal val getLazyValueName = JvmAbi.getterName("value")
|
internal val getLazyValueName = JvmAbi.getterName("value")
|
||||||
|
|
||||||
@@ -114,8 +126,8 @@ fun InstructionAdapter.genKOutputMethodCall(
|
|||||||
) {
|
) {
|
||||||
val propertyType = classCodegen.typeMapper.mapType(property.type)
|
val propertyType = classCodegen.typeMapper.mapType(property.type)
|
||||||
val sti = generator.getSerialTypeInfo(property, propertyType)
|
val sti = generator.getSerialTypeInfo(property, propertyType)
|
||||||
val useSerializer = if (fromClassStartVar == null) stackValueSerializerInstanceFromSerializer(classCodegen, sti, generator)
|
val useSerializer = if (fromClassStartVar == null) stackValueSerializerInstanceFromSerializer(expressionCodegen, classCodegen, sti, generator)
|
||||||
else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar, generator)
|
else stackValueSerializerInstanceFromClass(expressionCodegen, classCodegen, sti, fromClassStartVar, generator)
|
||||||
val actualType = ImplementationBodyCodegen.genPropertyOnStack(
|
val actualType = ImplementationBodyCodegen.genPropertyOnStack(
|
||||||
this,
|
this,
|
||||||
expressionCodegen.context,
|
expressionCodegen.context,
|
||||||
@@ -179,14 +191,16 @@ internal val contextSerializerId = ClassId(packageFqName, Name.identifier(Specia
|
|||||||
|
|
||||||
|
|
||||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
||||||
codegen: ClassBodyCodegen,
|
expressionCodegen: ExpressionCodegen,
|
||||||
|
classCodegen: ClassBodyCodegen,
|
||||||
sti: JVMSerialTypeInfo,
|
sti: JVMSerialTypeInfo,
|
||||||
varIndexStart: Int,
|
varIndexStart: Int,
|
||||||
serializerCodegen: AbstractSerialGenerator
|
serializerCodegen: AbstractSerialGenerator
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val serializer = sti.serializer
|
val serializer = sti.serializer
|
||||||
return serializerCodegen.stackValueSerializerInstance(
|
return serializerCodegen.stackValueSerializerInstance(
|
||||||
codegen,
|
expressionCodegen,
|
||||||
|
classCodegen,
|
||||||
sti.property.module,
|
sti.property.module,
|
||||||
sti.property.type,
|
sti.property.type,
|
||||||
serializer,
|
serializer,
|
||||||
@@ -198,6 +212,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializerWithoutSti(
|
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializerWithoutSti(
|
||||||
|
expressionCodegen: ExpressionCodegen,
|
||||||
codegen: ClassBodyCodegen,
|
codegen: ClassBodyCodegen,
|
||||||
property: SerializableProperty,
|
property: SerializableProperty,
|
||||||
serializerCodegen: AbstractSerialGenerator
|
serializerCodegen: AbstractSerialGenerator
|
||||||
@@ -210,6 +225,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializerWithou
|
|||||||
property.descriptor.findPsi()
|
property.descriptor.findPsi()
|
||||||
) else null
|
) else null
|
||||||
return serializerCodegen.stackValueSerializerInstance(
|
return serializerCodegen.stackValueSerializerInstance(
|
||||||
|
expressionCodegen,
|
||||||
codegen,
|
codegen,
|
||||||
property.module,
|
property.module,
|
||||||
property.type,
|
property.type,
|
||||||
@@ -222,9 +238,14 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializerWithou
|
|||||||
}.also { if (it && property.type.isMarkedNullable) wrapStackValueIntoNullableSerializer() }
|
}.also { if (it && property.type.isMarkedNullable) wrapStackValueIntoNullableSerializer() }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, serializerCodegen: AbstractSerialGenerator): Boolean {
|
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(
|
||||||
|
expressionCodegen: ExpressionCodegen,
|
||||||
|
codegen: ClassBodyCodegen,
|
||||||
|
sti: JVMSerialTypeInfo,
|
||||||
|
serializerCodegen: AbstractSerialGenerator
|
||||||
|
): Boolean {
|
||||||
return serializerCodegen.stackValueSerializerInstance(
|
return serializerCodegen.stackValueSerializerInstance(
|
||||||
codegen, sti.property.module, sti.property.type,
|
expressionCodegen, codegen, sti.property.module, sti.property.type,
|
||||||
sti.serializer, this, sti.property.genericIndex
|
sti.serializer, this, sti.property.genericIndex
|
||||||
) { idx, _ ->
|
) { idx, _ ->
|
||||||
load(0, kSerializerType)
|
load(0, kSerializerType)
|
||||||
@@ -234,7 +255,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codeg
|
|||||||
|
|
||||||
// returns false is cannot not use serializer
|
// returns false is cannot not use serializer
|
||||||
// use iv == null to check only (do not emit serializer onto stack)
|
// use iv == null to check only (do not emit serializer onto stack)
|
||||||
internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCodegen: ExpressionCodegen, classCodegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||||
iv: InstructionAdapter?,
|
iv: InstructionAdapter?,
|
||||||
genericIndex: Int? = null,
|
genericIndex: Int? = null,
|
||||||
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null
|
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null
|
||||||
@@ -248,7 +269,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
if (serializer.kind == ClassKind.OBJECT) {
|
if (serializer.kind == ClassKind.OBJECT) {
|
||||||
// singleton serializer -- just get it
|
// singleton serializer -- just get it
|
||||||
if (iv != null)
|
if (iv != null)
|
||||||
StackValue.singleton(serializer, codegen.typeMapper).put(kSerializerType, iv)
|
StackValue.singleton(serializer, classCodegen.typeMapper).put(kSerializerType, iv)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// serializer is not singleton object and shall be instantiated
|
// serializer is not singleton object and shall be instantiated
|
||||||
@@ -256,12 +277,13 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
// bail out from stackValueSerializerInstance if any type argument is not serializable
|
// bail out from stackValueSerializerInstance if any type argument is not serializable
|
||||||
val argType = projection.type
|
val argType = projection.type
|
||||||
val argSerializer = if (argType.isTypeParameter()) null else {
|
val argSerializer = if (argType.isTypeParameter()) null else {
|
||||||
findTypeSerializerOrContext(module, argType, sourceElement = codegen.descriptor.findPsi())
|
findTypeSerializerOrContext(module, argType, sourceElement = classCodegen.descriptor.findPsi())
|
||||||
?: return false
|
?: return false
|
||||||
}
|
}
|
||||||
// check if it can be properly serialized with its args recursively
|
// check if it can be properly serialized with its args recursively
|
||||||
if (!stackValueSerializerInstance(
|
if (!stackValueSerializerInstance(
|
||||||
codegen,
|
expressionCodegen,
|
||||||
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
argType,
|
argType,
|
||||||
argSerializer,
|
argSerializer,
|
||||||
@@ -275,7 +297,65 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
}
|
}
|
||||||
// new serializer if needed
|
// new serializer if needed
|
||||||
iv?.apply {
|
iv?.apply {
|
||||||
val serializerType = codegen.typeMapper.mapClass(serializer)
|
val serializerType = classCodegen.typeMapper.mapClass(serializer)
|
||||||
|
val classDescriptor = kType.toClassDescriptor!!
|
||||||
|
if (serializer.classId == enumSerializerId && !classDescriptor.useGeneratedEnumSerializer) {
|
||||||
|
// runtime contains enum serializer factory functions
|
||||||
|
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
||||||
|
val enumJavaType = classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||||
|
val serialName = classDescriptor.serialName()
|
||||||
|
|
||||||
|
if (classDescriptor.isEnumWithSerialInfoAnnotation()) {
|
||||||
|
aconst(serialName)
|
||||||
|
invokestatic(enumJavaType.internalName, "values", "()[${enumJavaType.descriptor}", false)
|
||||||
|
checkcast(javaEnumArray)
|
||||||
|
|
||||||
|
val entries = classDescriptor.enumEntries()
|
||||||
|
fillArray(stringType, entries) { _, entry ->
|
||||||
|
entry.annotations.serialNameValue.let {
|
||||||
|
if (it == null) {
|
||||||
|
aconst(null)
|
||||||
|
} else {
|
||||||
|
aconst(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkcast(stringArrayType)
|
||||||
|
|
||||||
|
fillArray(annotationArrayType, entries) { _, entry ->
|
||||||
|
val annotations = entry.annotationsWithArguments()
|
||||||
|
if (annotations.isEmpty()) {
|
||||||
|
aconst(null)
|
||||||
|
} else {
|
||||||
|
fillArray(annotationType, annotations) { _, annotation ->
|
||||||
|
val (annotationClass, args, consParams) = annotation
|
||||||
|
expressionCodegen.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkcast(doubleAnnotationArrayType)
|
||||||
|
|
||||||
|
invokestatic(
|
||||||
|
enumFactoriesType.internalName,
|
||||||
|
MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(),
|
||||||
|
"(${stringType.descriptor}${javaEnumArray.descriptor}${stringArrayType.descriptor}${doubleAnnotationArrayType.descriptor})${kSerializerType.descriptor}",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
aconst(serialName)
|
||||||
|
invokestatic(enumJavaType.internalName, "values", "()[${enumJavaType.descriptor}", false)
|
||||||
|
checkcast(javaEnumArray)
|
||||||
|
|
||||||
|
invokestatic(
|
||||||
|
enumFactoriesType.internalName,
|
||||||
|
ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(),
|
||||||
|
"(${stringType.descriptor}${javaEnumArray.descriptor})${kSerializerType.descriptor}",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// todo: support static factory methods for serializers for shorter bytecode
|
// todo: support static factory methods for serializers for shorter bytecode
|
||||||
anew(serializerType)
|
anew(serializerType)
|
||||||
dup()
|
dup()
|
||||||
@@ -286,7 +366,8 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
val (argType, argSerializer) = typeArgument
|
val (argType, argSerializer) = typeArgument
|
||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
codegen,
|
expressionCodegen,
|
||||||
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
argType,
|
argType,
|
||||||
argSerializer,
|
argSerializer,
|
||||||
@@ -303,9 +384,10 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
val serialName = kType.serialName()
|
val serialName = kType.serialName()
|
||||||
when (serializer.classId) {
|
when (serializer.classId) {
|
||||||
enumSerializerId -> {
|
enumSerializerId -> {
|
||||||
|
// support legacy serializer instantiation by constructor for old runtimes
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
val enumJavaType = codegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
val enumJavaType = classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||||
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
||||||
invokestatic(enumJavaType.internalName, "values","()[${enumJavaType.descriptor}", false)
|
invokestatic(enumJavaType.internalName, "values","()[${enumJavaType.descriptor}", false)
|
||||||
checkcast(javaEnumArray)
|
checkcast(javaEnumArray)
|
||||||
@@ -314,7 +396,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
contextSerializerId, polymorphicSerializerId -> {
|
contextSerializerId, polymorphicSerializerId -> {
|
||||||
// a special way to instantiate enum -- need a enum KClass reference
|
// a special way to instantiate enum -- need a enum KClass reference
|
||||||
// GENERIC_ARGUMENT forces boxing in order to obtain KClass
|
// GENERIC_ARGUMENT forces boxing in order to obtain KClass
|
||||||
aconst(codegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
if (serializer.classId == contextSerializerId && serializer.constructors.any { it.valueParameters.size == 3 }) {
|
if (serializer.classId == contextSerializerId && serializer.constructors.any { it.valueParameters.size == 3 }) {
|
||||||
@@ -334,7 +416,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
}
|
}
|
||||||
referenceArraySerializerId -> {
|
referenceArraySerializerId -> {
|
||||||
// a special way to instantiate reference array serializer -- need an element KClass reference
|
// a special way to instantiate reference array serializer -- need an element KClass reference
|
||||||
aconst(codegen.typeMapper.mapType(kType.arguments[0].type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(kType.arguments[0].type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
// Reference array serializer still needs serializer for its argument type
|
// Reference array serializer still needs serializer for its argument type
|
||||||
@@ -343,13 +425,13 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
sealedSerializerId -> {
|
sealedSerializerId -> {
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
aconst(codegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
val (subClasses, subSerializers) = allSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
val (subClasses, subSerializers) = allSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
||||||
// KClasses vararg
|
// KClasses vararg
|
||||||
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type ->
|
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type ->
|
||||||
aconst(codegen.typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
}
|
}
|
||||||
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
||||||
@@ -358,7 +440,8 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
val (argType, argSerializer) = subClasses[i] to serializer
|
val (argType, argSerializer) = subClasses[i] to serializer
|
||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
codegen,
|
expressionCodegen,
|
||||||
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
argType,
|
argType,
|
||||||
argSerializer,
|
argSerializer,
|
||||||
@@ -368,7 +451,8 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
// if we encountered generic type parameter in one of subclasses of sealed class, use polymorphism from upper bound
|
// if we encountered generic type parameter in one of subclasses of sealed class, use polymorphism from upper bound
|
||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
codegen,
|
expressionCodegen,
|
||||||
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound,
|
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound,
|
||||||
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
||||||
@@ -384,7 +468,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
objectSerializerId -> {
|
objectSerializerId -> {
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
StackValue.singleton(kType.toClassDescriptor!!, codegen.typeMapper).put(Type.getType("Ljava/lang/Object;"), iv)
|
StackValue.singleton(kType.toClassDescriptor!!, classCodegen.typeMapper).put(Type.getType("Ljava/lang/Object;"), iv)
|
||||||
signature.append("Ljava/lang/Object;")
|
signature.append("Ljava/lang/Object;")
|
||||||
}
|
}
|
||||||
// all serializers get arguments with serializers of their generic types
|
// all serializers get arguments with serializers of their generic types
|
||||||
@@ -397,6 +481,29 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun ExpressionCodegen.generateSyntheticAnnotationOnStack(
|
||||||
|
annotationClass: ClassDescriptor,
|
||||||
|
args: List<ValueArgument>,
|
||||||
|
ctorParams: List<ValueParameterDescriptor>
|
||||||
|
) {
|
||||||
|
val implType = typeMapper.mapType(annotationClass).internalName + "\$" + SerialEntityNames.IMPL_NAME.identifier
|
||||||
|
with(v) {
|
||||||
|
// new Annotation$Impl(...)
|
||||||
|
anew(Type.getObjectType(implType))
|
||||||
|
dup()
|
||||||
|
val sb = StringBuilder("(")
|
||||||
|
for (i in ctorParams.indices) {
|
||||||
|
val decl = args[i]
|
||||||
|
val desc = ctorParams[i]
|
||||||
|
val valAsmType = typeMapper.mapType(desc.type)
|
||||||
|
this@generateSyntheticAnnotationOnStack.gen(decl.getArgumentExpression(), valAsmType)
|
||||||
|
sb.append(valAsmType.descriptor)
|
||||||
|
}
|
||||||
|
sb.append(")V")
|
||||||
|
invokespecial(implType, "<init>", sb.toString(), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun InstructionAdapter.wrapStackValueIntoNullableSerializer() =
|
fun InstructionAdapter.wrapStackValueIntoNullableSerializer() =
|
||||||
invokestatic(
|
invokestatic(
|
||||||
"kotlinx/serialization/builtins/BuiltinSerializersKt", "getNullable",
|
"kotlinx/serialization/builtins/BuiltinSerializersKt", "getNullable",
|
||||||
@@ -406,10 +513,10 @@ fun InstructionAdapter.wrapStackValueIntoNullableSerializer() =
|
|||||||
fun <T> InstructionAdapter.fillArray(type: Type, args: List<T>, onEach: (Int, T) -> Unit) {
|
fun <T> InstructionAdapter.fillArray(type: Type, args: List<T>, onEach: (Int, T) -> Unit) {
|
||||||
iconst(args.size)
|
iconst(args.size)
|
||||||
newarray(type)
|
newarray(type)
|
||||||
args.forEachIndexed { i, serializer ->
|
args.forEachIndexed { i, arg ->
|
||||||
dup()
|
dup()
|
||||||
iconst(i)
|
iconst(i)
|
||||||
onEach(i, serializer)
|
onEach(i, arg)
|
||||||
astore(type)
|
astore(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,7 +617,7 @@ internal fun createSingletonLambda(
|
|||||||
lambdaName: String,
|
lambdaName: String,
|
||||||
outerClassCodegen: ImplementationBodyCodegen,
|
outerClassCodegen: ImplementationBodyCodegen,
|
||||||
resultSimpleType: SimpleType,
|
resultSimpleType: SimpleType,
|
||||||
block: InstructionAdapter.(ImplementationBodyCodegen) -> Unit
|
block: InstructionAdapter.(ImplementationBodyCodegen, ExpressionCodegen) -> Unit
|
||||||
): Type {
|
): Type {
|
||||||
val lambdaType = Type.getObjectType("${outerClassCodegen.className}\$$lambdaName")
|
val lambdaType = Type.getObjectType("${outerClassCodegen.className}\$$lambdaName")
|
||||||
|
|
||||||
@@ -631,8 +738,8 @@ internal fun createSingletonLambda(
|
|||||||
DescriptorVisibilities.PUBLIC
|
DescriptorVisibilities.PUBLIC
|
||||||
)
|
)
|
||||||
|
|
||||||
lambdaCodegen.generateMethod(invokeFunction) { _, _ ->
|
lambdaCodegen.generateMethod(invokeFunction) { _, expressionCodegen ->
|
||||||
block(lambdaCodegen)
|
block(lambdaCodegen, expressionCodegen)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bridgeInvokeFunction = SimpleFunctionDescriptorImpl.create(
|
val bridgeInvokeFunction = SimpleFunctionDescriptorImpl.create(
|
||||||
|
|||||||
+9
-1
@@ -103,7 +103,15 @@ class SerializableCodegenImpl(
|
|||||||
superTypeArguments.forEach {
|
superTypeArguments.forEach {
|
||||||
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(it).let { if (it == -1) null else it }
|
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(it).let { if (it == -1) null else it }
|
||||||
val serial = findTypeSerializerOrContext(serializableDescriptor.module, it.type)
|
val serial = findTypeSerializerOrContext(serializableDescriptor.module, it.type)
|
||||||
stackValueSerializerInstance(classCodegen, serializableDescriptor.module, it.type, serial, this, genericIdx) { i, _ ->
|
stackValueSerializerInstance(
|
||||||
|
exprCodegen,
|
||||||
|
classCodegen,
|
||||||
|
serializableDescriptor.module,
|
||||||
|
it.type,
|
||||||
|
serial,
|
||||||
|
this,
|
||||||
|
genericIdx
|
||||||
|
) { i, _ ->
|
||||||
load(offsetI + i, kSerializerType)
|
load(offsetI + i, kSerializerType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -57,7 +57,11 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
|||||||
|
|
||||||
// create singleton lambda class
|
// create singleton lambda class
|
||||||
val lambdaType =
|
val lambdaType =
|
||||||
createSingletonLambda("serializer\$1", classCodegen, companionDescriptor.getKSerializer().defaultType) { lambdaCodegen ->
|
createSingletonLambda(
|
||||||
|
"serializer\$1",
|
||||||
|
classCodegen,
|
||||||
|
companionDescriptor.getKSerializer().defaultType
|
||||||
|
) { lambdaCodegen, expressionCodegen ->
|
||||||
val serializerDescriptor = requireNotNull(
|
val serializerDescriptor = requireNotNull(
|
||||||
findTypeSerializer(
|
findTypeSerializer(
|
||||||
serializableDescriptor.module,
|
serializableDescriptor.module,
|
||||||
@@ -65,6 +69,7 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
|
expressionCodegen,
|
||||||
lambdaCodegen,
|
lambdaCodegen,
|
||||||
serializableDescriptor.module,
|
serializableDescriptor.module,
|
||||||
serializableDescriptor.defaultType,
|
serializableDescriptor.defaultType,
|
||||||
@@ -106,8 +111,9 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
|||||||
serializableDescriptor.toSimpleType()
|
serializableDescriptor.toSimpleType()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
classCodegen.generateMethod(methodDescriptor) { _, _ ->
|
classCodegen.generateMethod(methodDescriptor) { _, expressionCodegen ->
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
|
expressionCodegen,
|
||||||
classCodegen,
|
classCodegen,
|
||||||
serializableDescriptor.module,
|
serializableDescriptor.module,
|
||||||
serializableDescriptor.defaultType,
|
serializableDescriptor.defaultType,
|
||||||
|
|||||||
+7
-30
@@ -8,7 +8,6 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
|||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||||
import org.jetbrains.kotlin.psi.ValueArgument
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
||||||
@@ -37,7 +36,7 @@ open class SerializerCodegenImpl(
|
|||||||
companion object {
|
companion object {
|
||||||
fun generateSerializerExtensions(codegen: ImplementationBodyCodegen, metadataPlugin: SerializationDescriptorSerializerPlugin?) {
|
fun generateSerializerExtensions(codegen: ImplementationBodyCodegen, metadataPlugin: SerializationDescriptorSerializerPlugin?) {
|
||||||
val serializableClass = getSerializableClassDescriptorBySerializer(codegen.descriptor) ?: return
|
val serializableClass = getSerializableClassDescriptorBySerializer(codegen.descriptor) ?: return
|
||||||
val serializerCodegen = if (serializableClass.isInternallySerializableEnum()) {
|
val serializerCodegen = if (serializableClass.isEnumWithLegacyGeneratedSerializer()) {
|
||||||
SerializerForEnumsCodegen(codegen, serializableClass)
|
SerializerForEnumsCodegen(codegen, serializableClass)
|
||||||
} else {
|
} else {
|
||||||
SerializerCodegenImpl(codegen, serializableClass, metadataPlugin)
|
SerializerCodegenImpl(codegen, serializableClass, metadataPlugin)
|
||||||
@@ -144,30 +143,6 @@ open class SerializerCodegenImpl(
|
|||||||
expr.generateSerialDescriptor(0, true)
|
expr.generateSerialDescriptor(0, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ExpressionCodegen.generateSyntheticAnnotationOnStack(
|
|
||||||
annotationClass: ClassDescriptor,
|
|
||||||
args: List<ValueArgument>,
|
|
||||||
ctorParams: List<ValueParameterDescriptor>
|
|
||||||
) {
|
|
||||||
val implType =
|
|
||||||
codegen.typeMapper.mapType(annotationClass).internalName + "\$" + SerialEntityNames.IMPL_NAME.identifier
|
|
||||||
with(v) {
|
|
||||||
// new Annotation$Impl(...)
|
|
||||||
anew(Type.getObjectType(implType))
|
|
||||||
dup()
|
|
||||||
val sb = StringBuilder("(")
|
|
||||||
for (i in ctorParams.indices) {
|
|
||||||
val decl = args[i]
|
|
||||||
val desc = ctorParams[i]
|
|
||||||
val valAsmType = codegen.typeMapper.mapType(desc.type)
|
|
||||||
this@generateSyntheticAnnotationOnStack.gen(decl.getArgumentExpression(), valAsmType)
|
|
||||||
sb.append(valAsmType.descriptor)
|
|
||||||
}
|
|
||||||
sb.append(")V")
|
|
||||||
invokespecial(implType, "<init>", sb.toString(), false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use null to put value on stack, use number to store it to var
|
// use null to put value on stack, use number to store it to var
|
||||||
protected fun InstructionAdapter.stackSerialClassDesc(classDescVar: Int?) {
|
protected fun InstructionAdapter.stackSerialClassDesc(classDescVar: Int?) {
|
||||||
if (staticDescriptor)
|
if (staticDescriptor)
|
||||||
@@ -192,7 +167,7 @@ open class SerializerCodegenImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun generateChildSerializersGetter(function: FunctionDescriptor) {
|
override fun generateChildSerializersGetter(function: FunctionDescriptor) {
|
||||||
codegen.generateMethod(function) { _, _ ->
|
codegen.generateMethod(function) { _, expressionCodegen ->
|
||||||
val size = serializableProperties.size
|
val size = serializableProperties.size
|
||||||
iconst(size)
|
iconst(size)
|
||||||
newarray(kSerializerType)
|
newarray(kSerializerType)
|
||||||
@@ -202,6 +177,7 @@ open class SerializerCodegenImpl(
|
|||||||
val prop = serializableProperties[i]
|
val prop = serializableProperties[i]
|
||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstanceFromSerializerWithoutSti(
|
stackValueSerializerInstanceFromSerializerWithoutSti(
|
||||||
|
expressionCodegen,
|
||||||
codegen,
|
codegen,
|
||||||
prop,
|
prop,
|
||||||
this@SerializerCodegenImpl
|
this@SerializerCodegenImpl
|
||||||
@@ -335,7 +311,7 @@ open class SerializerCodegenImpl(
|
|||||||
propVar = propsStartVar
|
propVar = propsStartVar
|
||||||
for ((index, property) in serializableProperties.withIndex()) {
|
for ((index, property) in serializableProperties.withIndex()) {
|
||||||
val propertyType = codegen.typeMapper.mapType(property.type)
|
val propertyType = codegen.typeMapper.mapType(property.type)
|
||||||
callReadProperty(property, propertyType, index, inputVar, descVar, propVar)
|
callReadProperty(expressionCodegen, property, propertyType, index, inputVar, descVar, propVar)
|
||||||
propVar += propertyType.size
|
propVar += propertyType.size
|
||||||
}
|
}
|
||||||
// set all bit masks to true
|
// set all bit masks to true
|
||||||
@@ -373,7 +349,7 @@ open class SerializerCodegenImpl(
|
|||||||
if (!property.transient) {
|
if (!property.transient) {
|
||||||
// labelI:
|
// labelI:
|
||||||
visitLabel(labels[labelNum + 1])
|
visitLabel(labels[labelNum + 1])
|
||||||
callReadProperty(property, propertyType, index, inputVar, descVar, propVar)
|
callReadProperty(expressionCodegen, property, propertyType, index, inputVar, descVar, propVar)
|
||||||
|
|
||||||
// mark read bit in mask
|
// mark read bit in mask
|
||||||
// bitMask = bitMask | 1 << index
|
// bitMask = bitMask | 1 << index
|
||||||
@@ -449,6 +425,7 @@ open class SerializerCodegenImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun InstructionAdapter.callReadProperty(
|
private fun InstructionAdapter.callReadProperty(
|
||||||
|
expressionCodegen: ExpressionCodegen,
|
||||||
property: SerializableProperty,
|
property: SerializableProperty,
|
||||||
propertyType: Type,
|
propertyType: Type,
|
||||||
index: Int,
|
index: Int,
|
||||||
@@ -462,7 +439,7 @@ open class SerializerCodegenImpl(
|
|||||||
iconst(index)
|
iconst(index)
|
||||||
|
|
||||||
val sti = getSerialTypeInfo(property, propertyType)
|
val sti = getSerialTypeInfo(property, propertyType)
|
||||||
val useSerializer = stackValueSerializerInstanceFromSerializer(codegen, sti, this@SerializerCodegenImpl)
|
val useSerializer = stackValueSerializerInstanceFromSerializer(expressionCodegen, codegen, sti, this@SerializerCodegenImpl)
|
||||||
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
|
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
|
||||||
if (unknownSer) {
|
if (unknownSer) {
|
||||||
aconst(codegen.typeMapper.mapType(property.type))
|
aconst(codegen.typeMapper.mapType(property.type))
|
||||||
|
|||||||
+10
-3
@@ -36,6 +36,8 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
|||||||
internal val SERIALIZABLE_PROPERTIES: WritableSlice<ClassDescriptor, SerializableProperties> = Slices.createSimpleSlice()
|
internal val SERIALIZABLE_PROPERTIES: WritableSlice<ClassDescriptor, SerializableProperties> = Slices.createSimpleSlice()
|
||||||
|
|
||||||
open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
||||||
|
private var useLegacyEnumSerializerCached: Boolean? = null
|
||||||
|
|
||||||
final override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
final override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||||
if (descriptor !is ClassDescriptor) return
|
if (descriptor !is ClassDescriptor) return
|
||||||
|
|
||||||
@@ -139,8 +141,13 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ClassDescriptor.useLegacyGeneratedEnumSerializer(): Boolean {
|
||||||
|
return useLegacyEnumSerializerCached ?: useGeneratedEnumSerializer.also { useLegacyEnumSerializerCached = it }
|
||||||
|
}
|
||||||
|
|
||||||
private fun canBeSerializedInternally(descriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace): Boolean {
|
private fun canBeSerializedInternally(descriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace): Boolean {
|
||||||
if (descriptor.isSerializableEnumWithMissingSerializer()) {
|
// if enum has meta or SerialInfo annotation on a class or entries and used plugin-generated serializer
|
||||||
|
if (descriptor.isSerializableEnumWithMissingSerializer() && descriptor.useLegacyGeneratedEnumSerializer()) {
|
||||||
val declarationToReport = declaration.modifierList ?: declaration
|
val declarationToReport = declaration.modifierList ?: declaration
|
||||||
trace.report(SerializationErrors.EXPLICIT_SERIALIZABLE_IS_REQUIRED.on(declarationToReport))
|
trace.report(SerializationErrors.EXPLICIT_SERIALIZABLE_IS_REQUIRED.on(declarationToReport))
|
||||||
return false
|
return false
|
||||||
@@ -187,7 +194,7 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check that we can instantiate supertype
|
// check that we can instantiate supertype
|
||||||
if (!descriptor.isSerializableEnum()) { // enums are inherited from java.lang.Enum and can't be inherited from other classes
|
if (descriptor.kind != ClassKind.ENUM_CLASS) { // enums are inherited from java.lang.Enum and can't be inherited from other classes
|
||||||
val superClass = descriptor.getSuperClassOrAny()
|
val superClass = descriptor.getSuperClassOrAny()
|
||||||
if (!superClass.isInternalSerializable && superClass.constructors.singleOrNull { it.valueParameters.size == 0 } == null) {
|
if (!superClass.isInternalSerializable && superClass.constructors.singleOrNull { it.valueParameters.size == 0 } == null) {
|
||||||
trace.reportOnSerializableOrMetaAnnotation(descriptor, SerializationErrors.NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR)
|
trace.reportOnSerializableOrMetaAnnotation(descriptor, SerializationErrors.NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR)
|
||||||
@@ -429,4 +436,4 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal val ClassDescriptor.serializableAnnotationIsUseless: Boolean
|
internal val ClassDescriptor.serializableAnnotationIsUseless: Boolean
|
||||||
get() = hasSerializableOrMetaAnnotationWithoutArgs && !isInternalSerializable && !hasCompanionObjectAsSerializer && !isSerializableEnum() && !isSealedSerializableInterface
|
get() = hasSerializableOrMetaAnnotationWithoutArgs && !isInternalSerializable && !hasCompanionObjectAsSerializer && kind != ClassKind.ENUM_CLASS && !isSealedSerializableInterface
|
||||||
|
|||||||
+20
-1
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
|||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.inheritableSerialInfoFqName
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.inheritableSerialInfoFqName
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.metaSerializableAnnotationFqName
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.metaSerializableAnnotationFqName
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
|
||||||
@@ -124,11 +126,20 @@ internal val ClassDescriptor.isInternalSerializable: Boolean //todo normal check
|
|||||||
|
|
||||||
internal fun ClassDescriptor.isSerializableEnum(): Boolean = kind == ClassKind.ENUM_CLASS && hasSerializableOrMetaAnnotation
|
internal fun ClassDescriptor.isSerializableEnum(): Boolean = kind == ClassKind.ENUM_CLASS && hasSerializableOrMetaAnnotation
|
||||||
|
|
||||||
|
internal fun ClassDescriptor.isEnumWithLegacyGeneratedSerializer(): Boolean = isInternallySerializableEnum() && useGeneratedEnumSerializer
|
||||||
|
|
||||||
internal fun ClassDescriptor.isInternallySerializableEnum(): Boolean =
|
internal fun ClassDescriptor.isInternallySerializableEnum(): Boolean =
|
||||||
kind == ClassKind.ENUM_CLASS && hasSerializableOrMetaAnnotationWithoutArgs
|
kind == ClassKind.ENUM_CLASS && hasSerializableOrMetaAnnotationWithoutArgs
|
||||||
|
|
||||||
internal val ClassDescriptor.shouldHaveGeneratedSerializer: Boolean
|
internal val ClassDescriptor.shouldHaveGeneratedSerializer: Boolean
|
||||||
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) || isInternallySerializableEnum()
|
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
||||||
|
|| isEnumWithLegacyGeneratedSerializer()
|
||||||
|
|
||||||
|
internal val ClassDescriptor.useGeneratedEnumSerializer: Boolean
|
||||||
|
get() {
|
||||||
|
val functions = module.getPackage(SerializationPackages.internalPackageFqName).memberScope.getFunctionNames()
|
||||||
|
return !functions.contains(ENUM_SERIALIZER_FACTORY_FUNC_NAME) || !functions.contains(MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
|
internal fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
|
||||||
check(this.kind == ClassKind.ENUM_CLASS)
|
check(this.kind == ClassKind.ENUM_CLASS)
|
||||||
@@ -138,6 +149,13 @@ internal fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
|
|||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check enum or its elements has any SerialInfo annotation
|
||||||
|
internal fun ClassDescriptor.isEnumWithSerialInfoAnnotation(): Boolean {
|
||||||
|
if (kind != ClassKind.ENUM_CLASS) return false
|
||||||
|
if (annotations.hasAnySerialAnnotation) return true
|
||||||
|
return enumEntries().any { (it.annotations.hasAnySerialAnnotation) }
|
||||||
|
}
|
||||||
|
|
||||||
internal val Annotations.hasAnySerialAnnotation: Boolean
|
internal val Annotations.hasAnySerialAnnotation: Boolean
|
||||||
get() = serialNameValue != null || any { it.annotationClass?.isSerialInfoAnnotation == true }
|
get() = serialNameValue != null || any { it.annotationClass?.isSerialInfoAnnotation == true }
|
||||||
|
|
||||||
@@ -242,6 +260,7 @@ internal fun ClassDescriptor.needSerializerFactory(): Boolean {
|
|||||||
if (!(this.platform?.isNative() == true || this.platform.isJs())) return false
|
if (!(this.platform?.isNative() == true || this.platform.isJs())) return false
|
||||||
val serializableClass = getSerializableClassDescriptorByCompanion(this) ?: return false
|
val serializableClass = getSerializableClassDescriptorByCompanion(this) ?: return false
|
||||||
if (serializableClass.isSerializableObject) return true
|
if (serializableClass.isSerializableObject) return true
|
||||||
|
if (serializableClass.isSerializableEnum()) return true
|
||||||
if (serializableClass.isAbstractOrSealedSerializableClass()) return true
|
if (serializableClass.isAbstractOrSealedSerializableClass()) return true
|
||||||
if (serializableClass.isSealedSerializableInterface) return true
|
if (serializableClass.isSealedSerializableInterface) return true
|
||||||
if (serializableClass.declaredTypeParameters.isEmpty()) return false
|
if (serializableClass.declaredTypeParameters.isEmpty()) return false
|
||||||
|
|||||||
+6
@@ -78,6 +78,7 @@ object SerialEntityNames {
|
|||||||
const val SERIAL_DESCRIPTOR_FOR_INLINE = "InlineClassDescriptor"
|
const val SERIAL_DESCRIPTOR_FOR_INLINE = "InlineClassDescriptor"
|
||||||
|
|
||||||
const val PLUGIN_EXCEPTIONS_FILE = "PluginExceptions"
|
const val PLUGIN_EXCEPTIONS_FILE = "PluginExceptions"
|
||||||
|
const val ENUMS_FILE = "Enums"
|
||||||
|
|
||||||
//exceptions
|
//exceptions
|
||||||
const val SERIAL_EXC = "SerializationException"
|
const val SERIAL_EXC = "SerializationException"
|
||||||
@@ -94,11 +95,16 @@ object SerialEntityNames {
|
|||||||
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
|
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
|
||||||
val SINGLE_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwMissingFieldException")
|
val SINGLE_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwMissingFieldException")
|
||||||
val ARRAY_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwArrayMissingFieldException")
|
val ARRAY_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwArrayMissingFieldException")
|
||||||
|
val ENUM_SERIALIZER_FACTORY_FUNC_NAME = Name.identifier("createSimpleEnumSerializer")
|
||||||
|
val MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME = Name.identifier("createMarkedEnumSerializer")
|
||||||
val SINGLE_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(SINGLE_MASK_FIELD_MISSING_FUNC_NAME)
|
val SINGLE_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(SINGLE_MASK_FIELD_MISSING_FUNC_NAME)
|
||||||
val ARRAY_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ARRAY_MASK_FIELD_MISSING_FUNC_NAME)
|
val ARRAY_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ARRAY_MASK_FIELD_MISSING_FUNC_NAME)
|
||||||
val CACHED_SERIALIZER_PROPERTY_NAME = Name.identifier(CACHED_SERIALIZER_PROPERTY)
|
val CACHED_SERIALIZER_PROPERTY_NAME = Name.identifier(CACHED_SERIALIZER_PROPERTY)
|
||||||
val CACHED_DESCRIPTOR_FIELD_NAME = Name.identifier(CACHED_DESCRIPTOR_FIELD)
|
val CACHED_DESCRIPTOR_FIELD_NAME = Name.identifier(CACHED_DESCRIPTOR_FIELD)
|
||||||
|
|
||||||
|
val ENUM_SERIALIZER_FACTORY_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||||
|
val MARKED_ENUM_SERIALIZER_FACTORY_FUNC_FQ = SerializationPackages.internalPackageFqName.child(MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
val dummyParamName = Name.identifier("serializationConstructorMarker")
|
val dummyParamName = Name.identifier("serializationConstructorMarker")
|
||||||
internal const val typeArgPrefix = "typeSerial"
|
internal const val typeArgPrefix = "typeSerial"
|
||||||
|
|||||||
Reference in New Issue
Block a user