[KTX.SERIALIZATION] Refactor plugin once again

This commit is contained in:
Roman Artemev
2020-04-29 20:08:33 +03:00
committed by romanart
parent d41bbbae0d
commit 1949b11bb2
6 changed files with 233 additions and 229 deletions
@@ -11,29 +11,19 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.generators.DeclarationGenerator
import org.jetbrains.kotlin.psi2ir.generators.FunctionGenerator
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
@@ -48,53 +38,11 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
interface IrBuilderExtension {
val compilerContext: SerializationPluginContext
private fun IrClass.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction {
fun IrClass.contributeFunction(descriptor: FunctionDescriptor, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) {
val functionSymbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor)
val function = if (functionSymbol.isBound) functionSymbol.owner else {
compilerContext.symbolTable.declareSimpleFunction(
startOffset,
endOffset,
SERIALIZABLE_PLUGIN_ORIGIN,
descriptor
).also {
it.parent = this
addMember(it)
}
}
return function.also { f ->
f.overriddenSymbols = descriptor.overriddenDescriptors.map {
compilerContext.symbolTable.referenceSimpleFunction(it.original)
}
}
}
private fun createFunctionGenerator(): FunctionGenerator = with(compilerContext) {
return FunctionGenerator(
DeclarationGenerator(
GeneratorContext(
Psi2IrConfiguration(),
moduleDescriptor,
bindingContext,
languageVersionSettings,
symbolTable,
GeneratorExtensions(),
typeTranslator,
typeTranslator.constantValueGenerator,
irBuiltIns
)
)
)
}
fun IrClass.contributeFunction(
descriptor: FunctionDescriptor,
bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit
) {
val f: IrSimpleFunction = declareSimpleFunctionWithExternalOverrides(descriptor)
f.buildWithScope {
createFunctionGenerator().generateFunctionParameterDeclarationsAndReturnType(f, null, null)
}
assert(functionSymbol.isBound)
val f: IrSimpleFunction = functionSymbol.owner
// TODO: default parameters
f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(
this.startOffset,
this.endOffset
@@ -108,27 +56,10 @@ interface IrBuilderExtension {
bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit
) {
val ctorSymbol = compilerContext.symbolTable.referenceConstructor(descriptor)
val c = if (ctorSymbol.isBound) {
ctorSymbol.owner
} else {
compilerContext.symbolTable.declareConstructor(
this.startOffset,
this.endOffset,
SERIALIZABLE_PLUGIN_ORIGIN,
descriptor
).also {
it.parent = this
addMember(it)
}
}
assert(ctorSymbol.isBound)
val c = ctorSymbol.owner
c.returnType = descriptor.returnType.toIrType()
if (declareNew || overwriteValueParameters)
c.createParameterDeclarations(
receiver = null,
overwriteValueParameters = overwriteValueParameters,
copyTypeParameters = false
)
c.body = DeclarationIrBuilder(compilerContext, c.symbol, this.startOffset, this.endOffset).irBlockBody(
this.startOffset,
this.endOffset
@@ -141,7 +72,8 @@ interface IrBuilderExtension {
vararg args: IrExpression,
typeHint: IrType? = null
): IrMemberAccessExpression {
val returnType = typeHint ?: callee.run { if (isBound) owner.returnType else descriptor.returnType!!.toIrType() }
assert(callee.isBound) { "Symbol $callee expected to be bound" }
val returnType = typeHint ?: callee.run { owner.returnType }
val call = irCall(callee, type = returnType)
call.dispatchReceiver = dispatchReceiver
args.forEachIndexed(call::putValueArgument)
@@ -167,7 +99,7 @@ interface IrBuilderExtension {
arrayElements: List<IrExpression>
): IrExpression {
val arrayType = compilerContext.symbols.array.typeWith(arrayElementType)
val arrayType = compilerContext.irBuiltIns.arrayClass.typeWith(arrayElementType)
val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements)
val typeArguments = listOf(arrayElementType)
@@ -203,7 +135,7 @@ interface IrBuilderExtension {
fun <T : IrDeclaration> T.buildWithScope(builder: (T) -> Unit): T =
also { irDeclaration ->
compilerContext.symbolTable.withScope(irDeclaration.descriptor) {
compilerContext.symbolTable.withReferenceScope(irDeclaration.descriptor) {
builder(irDeclaration)
}
}
@@ -253,12 +185,12 @@ interface IrBuilderExtension {
*/
fun IrBuilderWithScope.generateAnySuperConstructorCall(toBuilder: IrBlockBodyBuilder) {
val anyConstructor = compilerContext.builtIns.any.constructors.single()
val anyConstructor = compilerContext.irBuiltIns.anyClass.owner.declarations.single { it is IrConstructor } as IrConstructor
with(toBuilder) {
+IrDelegatingConstructorCallImpl(
startOffset, endOffset,
compilerContext.irBuiltIns.unitType,
compilerContext.symbolTable.referenceConstructor(anyConstructor)
anyConstructor.symbol
)
}
}
@@ -266,26 +198,29 @@ interface IrBuilderExtension {
fun generateSimplePropertyWithBackingField(
ownerSymbol: IrValueSymbol,
propertyDescriptor: PropertyDescriptor,
propertyParent: IrClass
propertyParent: IrClass,
declare: Boolean
): IrProperty {
val symbol = compilerContext.symbolTable.referenceProperty(propertyDescriptor)
val irProperty = if (symbol.isBound) symbol.owner else {
compilerContext.symbolTable.declareProperty(propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, propertyDescriptor) {
IrPropertyImpl(propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, it)
}.also {
val irPropertySymbol = compilerContext.symbolTable.referenceProperty(propertyDescriptor)
assert(irPropertySymbol.isBound || declare)
if (declare) {
IrPropertyImpl(propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irPropertySymbol).also {
it.parent = propertyParent
propertyParent.addMember(it)
}
}
val irProperty = irPropertySymbol.owner
irProperty.backingField = generatePropertyBackingField(propertyDescriptor, irProperty).apply {
parent = propertyParent
correspondingPropertySymbol = irProperty.symbol
correspondingPropertySymbol = irPropertySymbol
}
val fieldSymbol = irProperty.backingField!!.symbol
irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(it, fieldSymbol) }
?.apply { parent = propertyParent; correspondingPropertySymbol = irProperty.symbol }
irProperty.setter = propertyDescriptor.setter?.let { generatePropertyAccessor(it, fieldSymbol) }
?.apply { parent = propertyParent; correspondingPropertySymbol = irProperty.symbol }
irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(it, fieldSymbol, declare) }
?.apply { parent = propertyParent }
irProperty.setter = propertyDescriptor.setter?.let { generatePropertyAccessor(it, fieldSymbol, declare) }
?.apply { parent = propertyParent }
return irProperty
}
@@ -293,34 +228,47 @@ interface IrBuilderExtension {
propertyDescriptor: PropertyDescriptor,
originProperty: IrProperty
): IrField {
return compilerContext.symbolTable.declareField(
originProperty.startOffset,
originProperty.endOffset,
SERIALIZABLE_PLUGIN_ORIGIN,
propertyDescriptor,
propertyDescriptor.type.toIrType()
)
val fieldSymbol = compilerContext.symbolTable.referenceField(propertyDescriptor)
if (fieldSymbol.isBound) return fieldSymbol.owner
return originProperty.run {
// TODO: type parameters
IrFieldImpl(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, fieldSymbol, propertyDescriptor.type.toIrType())
}
}
fun generatePropertyAccessor(
descriptor: PropertyAccessorDescriptor,
fieldSymbol: IrFieldSymbol
fieldSymbol: IrFieldSymbol,
declare: Boolean
): IrSimpleFunction {
val symbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor)
assert(symbol.isBound || declare)
val declaration = if (symbol.isBound) symbol.owner.also { generateOverriddenFunctionSymbols(it, compilerContext.symbolTable) } else compilerContext.symbolTable.declareSimpleFunctionWithOverrides(fieldSymbol.owner.startOffset,
if (declare) {
IrFunctionImpl(
fieldSymbol.owner.startOffset,
fieldSymbol.owner.endOffset,
SERIALIZABLE_PLUGIN_ORIGIN, descriptor)
return declaration.buildWithScope { irAccessor ->
irAccessor.createParameterDeclarations(receiver = null)
irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType()
irAccessor.body = when (descriptor) {
is PropertyGetterDescriptor -> generateDefaultGetterBody(descriptor, irAccessor)
is PropertySetterDescriptor -> generateDefaultSetterBody(descriptor, irAccessor)
else -> throw AssertionError("Should be getter or setter: $descriptor")
SERIALIZABLE_PLUGIN_ORIGIN,
symbol,
descriptor.returnType!!.toIrType()
).also { f ->
generateOverriddenFunctionSymbols(f, compilerContext.symbolTable)
f.createParameterDeclarations(receiver = null)
f.returnType = descriptor.returnType!!.toIrType()
f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol
}
}
val irAccessor = symbol.owner
irAccessor.body = when (descriptor) {
is PropertyGetterDescriptor -> generateDefaultGetterBody(descriptor, irAccessor)
is PropertySetterDescriptor -> generateDefaultSetterBody(descriptor, irAccessor)
else -> throw AssertionError("Should be getter or setter: $descriptor")
}
return irAccessor
}
private fun generateDefaultGetterBody(
@@ -328,6 +276,7 @@ interface IrBuilderExtension {
irAccessor: IrSimpleFunction
): IrBlockBody {
val property = getter.correspondingProperty
val irProperty = irAccessor.correspondingPropertySymbol?.owner ?: error("Expected property for $getter")
val startOffset = irAccessor.startOffset
val endOffset = irAccessor.endOffset
@@ -341,7 +290,7 @@ interface IrBuilderExtension {
irAccessor.symbol,
IrGetFieldImpl(
startOffset, endOffset,
compilerContext.symbolTable.referenceField(property),
irProperty.backingField?.symbol ?: error("Property expected to have backing field"),
property.type.toIrType(),
receiver
)
@@ -355,7 +304,7 @@ interface IrBuilderExtension {
irAccessor: IrSimpleFunction
): IrBlockBody {
val property = setter.correspondingProperty
val irProperty = irAccessor.correspondingPropertySymbol?.owner ?: error("Expected corresponding property for accessor $setter")
val startOffset = irAccessor.startOffset
val endOffset = irAccessor.endOffset
val irBody = IrBlockBodyImpl(startOffset, endOffset)
@@ -366,7 +315,7 @@ interface IrBuilderExtension {
irBody.statements.add(
IrSetFieldImpl(
startOffset, endOffset,
compilerContext.symbolTable.referenceField(property),
irProperty.backingField?.symbol ?: error("Property $property expected to have backing field"),
receiver,
IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol),
compilerContext.irBuiltIns.unitType
@@ -405,6 +354,11 @@ interface IrBuilderExtension {
it.parent = this@createParameterDeclarations
}
if (copyTypeParameters) {
assert(typeParameters.isEmpty())
copyTypeParamsFromDescriptor()
}
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter()
extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter()
@@ -412,22 +366,24 @@ interface IrBuilderExtension {
assert(valueParameters.isEmpty())
valueParameters = descriptor.valueParameters.map { it.irValueParameter() }
assert(typeParameters.isEmpty())
if (copyTypeParameters) copyTypeParamsFromDescriptor()
}
fun IrFunction.copyTypeParamsFromDescriptor() {
typeParameters += descriptor.typeParameters.map {
val newTypeParameters = descriptor.typeParameters.map {
IrTypeParameterImpl(
startOffset, endOffset,
SERIALIZABLE_PLUGIN_ORIGIN,
it
).also { typeParameter ->
typeParameter.parent = this
typeParameter.superTypes.addAll(it.upperBounds.map { it.toIrType() })
}
}
newTypeParameters.forEach { typeParameter ->
typeParameter.superTypes.addAll(typeParameter.descriptor.upperBounds.map { it.toIrType() })
}
typeParameters = newTypeParameters
}
fun kClassTypeFor(projection: TypeProjection): SimpleType {
@@ -443,7 +399,7 @@ interface IrBuilderExtension {
startOffset,
endOffset,
returnType.toIrType(),
compilerContext.symbolTable.referenceClassifier(clazz),
compilerContext.referenceClass(clazz.fqNameSafe) ?: error("Couldn't load class $clazz"),
classType.toIrType()
)
}
@@ -471,9 +427,10 @@ interface IrBuilderExtension {
fun findEnumValuesMethod(enumClass: ClassDescriptor): IrFunction {
assert(enumClass.kind == ClassKind.ENUM_CLASS)
return compilerContext.symbolTable.referenceClass(enumClass).owner.functions
.find { it.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER && it.name == Name.identifier("values") }
?: throw AssertionError("Enum class does not have .values() function")
return compilerContext.referenceClass(enumClass.fqNameSafe)?.let {
it.owner.functions.find { it.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER && it.name == Name.identifier("values") }
?: throw AssertionError("Enum class does not have .values() function")
} ?: error("Couldn't load class $enumClass")
}
private fun getEnumMembersNames(enumClass: ClassDescriptor): Sequence<String> {
@@ -490,8 +447,8 @@ interface IrBuilderExtension {
dispatchReceiverParameter: IrValueParameter,
property: SerializableProperty
): IrExpression? {
val nullableSerClass =
compilerContext.symbolTable.referenceClass(property.module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
val nullableSerializerFqn = getInternalPackageFqn(SpecialBuiltins.nullableSerializer)
val nullableSerClass = compilerContext.referenceClass(nullableSerializerFqn) ?: error("Couldn't find class $nullableSerializerFqn")
val serializer =
property.serializableWith?.toClassDescriptor
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
@@ -517,15 +474,17 @@ interface IrBuilderExtension {
nullableSerializerClass: IrClassSymbol
): IrExpression {
return if (type.isMarkedNullable) {
val nullableConstructor =
compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first())
val classDeclaration = nullableSerializerClass.owner
val nullableConstructor = classDeclaration.declarations.first { it is IrConstructor } as IrConstructor
val resultType = type.makeNotNullable()
val typeParameters = classDeclaration.typeParameters
val typeArguments = listOf(resultType.toIrType())
irInvoke(
null, nullableConstructor,
typeArguments = listOf(resultType.toIrType()),
null, nullableConstructor.symbol,
typeArguments = typeArguments,
valueArguments = listOf(expression),
// Return type should be correctly substituted
returnTypeHint = nullableConstructor.descriptor.returnType.replace(listOf(resultType.asTypeProjection())).toIrType()
returnTypeHint = nullableConstructor.returnType.substitute(typeParameters, typeArguments)
)
} else {
expression
@@ -534,8 +493,8 @@ interface IrBuilderExtension {
fun wrapIrTypeIntoKSerializerIrType(module: ModuleDescriptor, type: IrType, variance: Variance = Variance.INVARIANT): IrType {
val kSerClass =
compilerContext.symbolTable.referenceClass(module.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS))
val serializerFqn = getSerializationPackageFqn(SerialEntityNames.KSERIALIZER_CLASS)
val kSerClass = compilerContext.referenceClass(serializerFqn) ?: error("Couldn't find class $serializerFqn")
return IrSimpleTypeImpl(
kSerClass, hasQuestionMark = false, arguments = listOf(
makeTypeProjection(type, variance)
@@ -569,8 +528,8 @@ interface IrBuilderExtension {
genericIndex: Int? = null,
genericGetter: ((Int, KotlinType) -> IrExpression)? = null
): IrExpression? {
val nullableSerClass =
compilerContext.symbolTable.referenceClass(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
val nullableClassFqn = getInternalPackageFqn(SpecialBuiltins.nullableSerializer)
val nullableSerClass = compilerContext.referenceClass(nullableClassFqn) ?: error("Expecting class $nullableClassFqn")
if (serializerClassOriginal == null) {
if (genericIndex == null) return null
return genericGetter?.invoke(genericIndex, kType)
@@ -679,20 +638,48 @@ interface IrBuilderExtension {
requireNotNull(
findSerializerConstructorForTypeArgumentsSerializers(serializerClass)
) { "Generated serializer does not have constructor with required number of arguments" }
.let { compilerContext.symbolTable.referenceConstructor(it) }
} else {
compilerContext.symbolTable.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!)
compilerContext.referenceConstructors(serializerClass.fqNameSafe).single { it.owner.isPrimary }
}
// Return type should be correctly substituted
val substitutedReturnType = if (ctor.isBound) {
val ctorDecl = ctor.owner
val typeParameters = ctorDecl.parentAsClass.typeParameters
ctor.owner.returnType.substitute(typeParameters, typeArgs)
} else ctor.descriptor.returnType.replace(typeArgs.map { it.toKotlinType().asTypeProjection() }).toIrType()
assert(ctor.isBound)
val ctorDecl = ctor.owner
val typeParameters = ctorDecl.parentAsClass.typeParameters
val substitutedReturnType = ctorDecl.returnType.substitute(typeParameters, typeArgs)
return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = substitutedReturnType)
}
}
fun ReferenceSymbolTable.serializableSyntheticConstructor(forClass: ClassDescriptor): IrConstructorSymbol =
referenceConstructor(forClass.constructors.single { it.isSerializationCtor() })
}
private fun findSerializerConstructorForTypeArgumentsSerializers(serializer: ClassDescriptor): IrConstructorSymbol? {
val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializer)?.arguments
?: throw AssertionError("Serializer does not implement KSerializer??")
val typeParamsCount = serializableImplementationTypeArguments.size
if (typeParamsCount == 0) return null //don't need it
val constructors = compilerContext.referenceConstructors(serializer.fqNameSafe)
fun isKSerializer(type: IrType): Boolean {
val simpleType = type as? IrSimpleType ?: return false
val classifier = simpleType.classifier as? IrClassSymbol ?: return false
return classifier.owner.fqNameWhenAvailable == SerialEntityNames.KSERIALIZER_NAME_FQ
}
return constructors.singleOrNull {
it.owner.valueParameters.let { vps -> vps.size == typeParamsCount && vps.all { vp -> isKSerializer(vp.type) } }
}
}
private fun IrConstructor.isSerializationCtor(): Boolean {
val serialMarker =
compilerContext.referenceClass(SerializationPackages.packageFqName.child(SerialEntityNames.SERIAL_CTOR_MARKER_NAME))
return valueParameters.lastOrNull()?.run {
name == SerialEntityNames.dummyParamName && type.classifierOrNull == serialMarker
} == true
}
fun serializableSyntheticConstructor(forClass: IrClass): IrConstructorSymbol {
return forClass.declarations.filterIsInstance<IrConstructor>().single { it.isSerializationCtor() }.symbol
}
}
@@ -12,19 +12,17 @@ import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irInt
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
@@ -63,16 +61,13 @@ class SerializableCompanionIrGenerator(
)
) ?: return
val irSerializableClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).takeIf { it.isBound }?.owner ?: return
val irSerializableClass = compilerContext.referenceClass(serializableDescriptor.fqNameSafe)?.owner ?: return
val serializableWithAlreadyPresent = irSerializableClass.annotations.any {
it.symbol.descriptor.constructedClass.fqNameSafe == annotationMarkerClass.fqNameSafe
}
if (serializableWithAlreadyPresent) return
val annotationCtor = requireNotNull(annotationMarkerClass.unsubstitutedPrimaryConstructor?.let {
compilerContext.symbolTable.referenceConstructor(it)
})
val annotationCtor = compilerContext.referenceConstructors(annotationMarkerClass.fqNameSafe).single { it.owner.isPrimary }
val annotationType = annotationMarkerClass.defaultType.toIrType()
val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
val serializerType = serializer.toSimpleType(false)
@@ -124,12 +119,11 @@ class SerializableCompanionIrGenerator(
val kSerializerStarType = factory.returnType
val array = factory.valueParameters.first()
val argsSize = serializableDescriptor.declaredTypeParameters.size
val arrayGet =
compilerContext.builtIns.array.getFuncDesc("get").single()
val arrayGetSymbol = compilerContext.symbolTable.referenceFunction(arrayGet)
val arrayGet = compilerContext.irBuiltIns.arrayClass.owner.declarations.filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "get" }
val serializers: List<IrExpression> = (0 until argsSize).map {
irInvoke(irGet(array), arrayGetSymbol, irInt(it), typeHint = kSerializerStarType)
irInvoke(irGet(array), arrayGet.symbol, irInt(it), typeHint = kSerializerStarType)
}
val serializerCall = compilerContext.symbolTable.referenceSimpleFunction(getterDescriptor)
val call = irInvoke(
@@ -1,30 +1,22 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.CompilationException
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
@@ -38,26 +30,42 @@ class SerializableIrGenerator(
bindingContext: BindingContext
) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
private fun IrClass.getSuperClassOrAny(): IrClass {
val superClasses = superTypes.mapNotNull { it.classOrNull }.map { it.owner }
return superClasses.singleOrNull { it.kind == ClassKind.CLASS } ?: compilerContext.irBuiltIns.anyClass.owner
}
private fun IrClass.hasSerializableAnnotationWithoutArgs(): Boolean {
val annot = getAnnotation(SerializationAnnotations.serializableAnnotationFqName) ?: return false
for (i in 0 until annot.valueArgumentsCount) {
if (annot.getValueArgument(i) != null) return false
}
return true
}
private val IrClass.isInternalSerializable: Boolean get() = kind == ClassKind.CLASS && hasSerializableAnnotationWithoutArgs()
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) =
irClass.contributeConstructor(constructorDescriptor, overwriteValueParameters = true) { ctor ->
irClass.contributeConstructor(constructorDescriptor) { ctor ->
val transformFieldInitializer = buildInitializersRemapping(irClass)
// Missing field exception parts
val exceptionCtor =
serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC)
.unsubstitutedPrimaryConstructor!!
val exceptionCtorRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor)
val exceptionType = exceptionCtor.returnType.toIrType()
val exceptionFqn = getSerializationPackageFqn(MISSING_FIELD_EXC)
val exceptionCtorRef = compilerContext.referenceConstructors(exceptionFqn).single { it.owner.isPrimary }
val exceptionType = exceptionCtorRef.owner.returnType
val serializableProperties = properties.serializableProperties
val seenVarsOffset = serializableProperties.bitMaskSlotCount()
val seenVars = (0 until seenVarsOffset).map { ctor.valueParameters[it] }
val thiz = irClass.thisReceiver!!
val superClass = irClass.descriptor.getSuperClassOrAny()
val superClass = irClass.getSuperClassOrAny()
var startPropOffset: Int = 0
when {
KotlinBuiltIns.isAny(superClass) -> generateAnySuperConstructorCall(toBuilder = this@contributeConstructor)
superClass.symbol == compilerContext.irBuiltIns.anyClass -> generateAnySuperConstructorCall(toBuilder = this@contributeConstructor)
superClass.isInternalSerializable -> {
startPropOffset = generateSuperSerializableCall(superClass, ctor.valueParameters, seenVarsOffset)
}
@@ -108,22 +116,23 @@ class SerializableIrGenerator(
}
}
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: ClassDescriptor) {
val suitableCtor = superClass.constructors.singleOrNull { it.valueParameters.size == 0 }
?: throw IllegalArgumentException("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor")
val ctorRef = compilerContext.symbolTable.referenceConstructor(suitableCtor)
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: IrClass) {
val ctorRef = superClass.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.valueParameters.isEmpty() }
?: error("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor")
val call = IrDelegatingConstructorCallImpl(
startOffset,
endOffset,
compilerContext.irBuiltIns.unitType,
ctorRef
ctorRef.symbol
)
call.insertTypeArgumentsForSuperClass(superClass)
+call
}
private fun IrDelegatingConstructorCallImpl.insertTypeArgumentsForSuperClass(superClass: ClassDescriptor) {
val superTypeCallArguments = (irClass.superTypes.find { it.classOrNull?.descriptor == superClass } as? IrSimpleType)?.arguments
private fun IrDelegatingConstructorCallImpl.insertTypeArgumentsForSuperClass(superClass: IrClass) {
val superTypeCallArguments = (irClass.superTypes.find { it.classOrNull == superClass.symbol } as IrSimpleType?)?.arguments
superTypeCallArguments?.forEachIndexed { index, irTypeArgument ->
val argType =
irTypeArgument as? IrTypeProjection ?: throw IllegalStateException("Star projection in immediate argument for supertype")
@@ -133,13 +142,13 @@ class SerializableIrGenerator(
// returns offset in serializable properties array
private fun IrBlockBodyBuilder.generateSuperSerializableCall(
superClass: ClassDescriptor,
superClass: IrClass,
allValueParameters: List<IrValueParameter>,
propertiesStart: Int
): Int {
check(superClass.isInternalSerializable)
val superCtorRef = compilerContext.symbolTable.serializableSyntheticConstructor(superClass)
val superProperties = bindingContext.serializablePropertiesFor(superClass).serializableProperties
val superCtorRef = serializableSyntheticConstructor(superClass)
val superProperties = bindingContext.serializablePropertiesFor(superClass.descriptor).serializableProperties
val superSlots = superProperties.bitMaskSlotCount()
val arguments = allValueParameters.subList(0, superSlots) +
allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) +
@@ -9,10 +9,13 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.properties
@@ -20,6 +23,7 @@ import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
@@ -35,7 +39,7 @@ class SerializerForEnumsGenerator(
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!)
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
val encodeEnum = encoderClass.referenceMethod(CallingConventions.encodeEnum)
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
@@ -51,7 +55,7 @@ class SerializerForEnumsGenerator(
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!)
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
val decode = decoderClass.referenceMethod(CallingConventions.decodeEnum)
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
@@ -59,13 +63,14 @@ class SerializerForEnumsGenerator(
val valuesF = serializableIrClass.functions.single { it.name == DescriptorUtils.ENUM_VALUES }
val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol)
val arrayGet =
compilerContext.builtIns.array.getFuncDesc("get").single()
val arrayGetSymbol = compilerContext.symbolTable.referenceFunction(arrayGet)
val arrayGet = compilerContext.irBuiltIns.arrayClass.owner.declarations.filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "get" }
val getValueByOrdinal =
irInvoke(
getValues,
arrayGetSymbol,
arrayGet.symbol,
irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter),
typeHint = serializableIrClass.defaultType
)
@@ -78,8 +83,7 @@ class SerializerForEnumsGenerator(
): IrExpression {
val serialDescForEnums = serializerDescriptor
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_ENUM)
val ctor =
compilerContext.symbolTable.referenceConstructor(serialDescForEnums.unsubstitutedPrimaryConstructor!!)
val ctor = compilerContext.referenceConstructors(serialDescForEnums.fqNameSafe).single { it.owner.isPrimary }
return irInvoke(
null, ctor,
irString(serialName),
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrAnonymousInitializerImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
@@ -19,12 +20,11 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.ir.util.withScope
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
@@ -43,7 +43,10 @@ object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER")
open class SerializerIrGenerator(val irClass: IrClass, final override val compilerContext: SerializationPluginContext, bindingContext: BindingContext) :
SerializerCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).takeIf { it.isBound }?.owner
protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).owner
protected val irAnySerialDescProperty = anySerialDescProperty?.let { compilerContext.symbolTable.referenceProperty(it) }
override fun generateSerialDesc() {
val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return
@@ -56,23 +59,26 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
lateinit var prop: IrProperty
// how to (auto)create backing field and getter/setter?
compilerContext.symbolTable.withScope(irClass.descriptor) {
compilerContext.symbolTable.withReferenceScope(irClass.descriptor) {
introduceValueParameter(thisAsReceiverParameter)
prop = generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, desc, irClass)
prop = generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, desc, irClass, false)
// TODO: Do not use descriptors here
localSerializersFieldsDescriptors.forEach {
generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, it, irClass)
generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, it, irClass, true)
}
}
compilerContext.symbolTable.declareAnonymousInitializer(
irClass.startOffset, irClass.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irClass.descriptor
).buildWithScope { initIrBody ->
initIrBody.parent = irClass
val ctor = irClass.declarations.filterIsInstance<IrConstructor>().find { it.isPrimary }
?: throw AssertionError("Serializer must have primary constructor")
compilerContext.symbolTable.withScope(initIrBody.descriptor) {
val annonimousInit = irClass.run {
val symbol = IrAnonymousInitializerSymbolImpl(descriptor)
IrAnonymousInitializerImpl(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, symbol).also {
it.parent = this
declarations.add(it)
}
}
annonimousInit.buildWithScope { initIrBody ->
compilerContext.symbolTable.withReferenceScope(initIrBody.descriptor) {
initIrBody.body =
DeclarationIrBuilder(compilerContext, initIrBody.symbol, initIrBody.startOffset, initIrBody.endOffset).irBlockBody {
val localDesc = irTemporary(
@@ -83,7 +89,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
// add class annotations
copySerialInfoAnnotationsToDescriptor(
serializableIrClass?.annotations.orEmpty(),
serializableIrClass.annotations,
localDesc,
serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation)
)
@@ -98,7 +104,6 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
irGet(localDesc)
)
}
(ctor.body as? IrBlockBody)?.statements?.addAll(initIrBody.body.statements)
}
}
}
@@ -107,9 +112,8 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
serialDescImplClass: ClassDescriptor,
correctThis: IrExpression
): IrExpression {
val serialDescImplConstructor = serialDescImplClass
.unsubstitutedPrimaryConstructor!!
val serialClassDescImplCtor = compilerContext.symbolTable.referenceConstructor(serialDescImplConstructor)
val classConstructors = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe)
val serialClassDescImplCtor = classConstructors.single { it.owner.isPrimary }
return irInvoke(
null, serialClassDescImplCtor,
irString(serialName), if (isGeneratedSerializer) correctThis else irNull(), irInt(serializableProperties.size)
@@ -209,15 +213,16 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
/* Already implemented in .generateSerialClassDesc ? */
}
protected inline fun ClassDescriptor.referenceMethod(methodName: String, predicate: (FunctionDescriptor) -> Boolean = { true }) =
getFuncDesc(methodName).single(predicate).let { compilerContext.symbolTable.referenceFunction(it) }
protected inline fun ClassDescriptor.referenceMethod(methodName: String, predicate: (IrSimpleFunction) -> Boolean = { true }): IrFunctionSymbol {
val irClass = compilerContext.referenceClass(fqNameSafe)?.owner ?: error("Couldn't load class $this")
val simpleFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
return simpleFunctions.filter { it.name.asString() == methodName }.single { predicate(it) }.symbol
}
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
val fieldInitializer: (SerializableProperty) -> IrExpression? =
buildInitializersRemapping(
serializableIrClass ?: error("Please provide implementation of .deserialize method for external class")
).run { { invoke(it.irField) } }
buildInitializersRemapping(serializableIrClass).run { { invoke(it.irField) } }
fun irThis(): IrExpression =
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
@@ -225,7 +230,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_ENCODER_CLASS)
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(ENCODER_CLASS)
val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!) //???
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
@@ -337,7 +342,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
val inputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_DECODER_CLASS)
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(DECODER_CLASS)
val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!) //???
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
// workaround due to unavailability of labels (KT-25386)
@@ -430,10 +435,9 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
decoderCalls.forEach { (i, e) -> +IrBranchImpl(irEquals(indexVar.get(), irInt(i)), e) }
// throw exception on unknown field
val exceptionCtor =
serializableDescriptor.getClassFromSerializationPackage(UNKNOWN_FIELD_EXC)
.unsubstitutedPrimaryConstructor!!
val excClassRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor)
val exceptionFqn = getSerializationPackageFqn(UNKNOWN_FIELD_EXC)
val excClassRef = compilerContext.referenceConstructors(exceptionFqn).single { it.owner.isPrimary }
+elseBranch(
irThrow(
irInvoke(
@@ -462,9 +466,9 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
val typeArgs = (loadFunc.returnType as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
val ctor: IrConstructorSymbol = if (serializableDescriptor.isInternalSerializable) {
args = bitMasks.map { irGet(it) } + args + irNull()
compilerContext.symbolTable.serializableSyntheticConstructor(serializableDescriptor)
serializableSyntheticConstructor(serializableIrClass)
} else {
compilerContext.symbolTable.referenceConstructor(serializableDescriptor.unsubstitutedPrimaryConstructor!!)
compilerContext.referenceConstructors(serializableDescriptor.fqNameSafe).single { it.owner.isPrimary }
}
+irReturn(irInvoke(null, ctor, typeArgs, args))
@@ -63,9 +63,15 @@ internal fun Annotations.findAnnotationKotlinTypeValue(
internal fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(SerializationPackages.packageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME))!!
internal fun getInternalPackageFqn(classSimpleName: String): FqName =
SerializationPackages.internalPackageFqName.child(Name.identifier(classSimpleName))
internal fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
getFromPackage(SerializationPackages.internalPackageFqName, classSimpleName)
internal fun getSerializationPackageFqn(classSimpleName: String): FqName =
SerializationPackages.packageFqName.child(Name.identifier(classSimpleName))
internal fun ModuleDescriptor.getClassFromSerializationPackage(classSimpleName: String) =
getFromPackage(SerializationPackages.packageFqName, classSimpleName)