Support generic classes in serialization FIR plugin
This commit is contained in:
+1
-1
@@ -305,7 +305,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
property.type,
|
||||
genericIndex = property.genericIndex
|
||||
) { it, _ ->
|
||||
val (_, ir) = generator.localSerializersFieldsDescriptors[it]
|
||||
val ir = generator.localSerializersFieldsDescriptors[it]
|
||||
irGetField(irGet(dispatchReceiverParameter), ir.backingField!!)
|
||||
}?.let { expr -> wrapWithNullableSerializerIfNeeded(property.type, expr, nullableSerClass) }
|
||||
}
|
||||
|
||||
+49
-209
@@ -7,11 +7,12 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
|
||||
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME
|
||||
@@ -99,15 +99,7 @@ interface IrBuilderWithPluginContext {
|
||||
val lazyIrClass = compilerContext.referenceClass(ClassId.topLevel(LAZY_FQ))!!.owner
|
||||
val lazyIrType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType))
|
||||
|
||||
val propertyDescriptor =
|
||||
KSerializerDescriptorResolver.createValPropertyDescriptor(
|
||||
Name.identifier(name.asString() + "\$delegate"),
|
||||
containingClass.descriptor,
|
||||
lazyIrType.toKotlinType(),
|
||||
createGetter = true
|
||||
)
|
||||
|
||||
return generateSimplePropertyWithBackingField(propertyDescriptor, containingClass).apply {
|
||||
return generateSimplePropertyWithBackingField(Name.identifier(name.asString() + "\$delegate"), lazyIrType, containingClass).apply {
|
||||
val builder = DeclarationIrBuilder(compilerContext, containingClass.symbol, startOffset, endOffset)
|
||||
val initializerBody = builder.run {
|
||||
val enumElement = IrGetEnumValueImpl(
|
||||
@@ -133,11 +125,7 @@ interface IrBuilderWithPluginContext {
|
||||
name: Name,
|
||||
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
||||
): IrProperty {
|
||||
val targetKotlinType = type.toKotlinType()
|
||||
val propertyDescriptor =
|
||||
KSerializerDescriptorResolver.createValPropertyDescriptor(name, companionClass.descriptor, targetKotlinType)
|
||||
|
||||
return generateSimplePropertyWithBackingField(propertyDescriptor, companionClass, name).apply {
|
||||
return generateSimplePropertyWithBackingField(name, type, companionClass).apply {
|
||||
companionClass.contributeAnonymousInitializer {
|
||||
val irBlockBody = irBlockBody(startOffset, endOffset, initializerBuilder)
|
||||
irBlockBody.statements.dropLast(1).forEach { +it }
|
||||
@@ -292,209 +280,61 @@ interface IrBuilderWithPluginContext {
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
||||
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
||||
}
|
||||
|
||||
fun generateSimplePropertyWithBackingField(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
propertyName: Name,
|
||||
propertyType: IrType,
|
||||
propertyParent: IrClass,
|
||||
fieldName: Name = propertyDescriptor.name,
|
||||
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE
|
||||
): IrProperty = generatePropertyMissingParts(null, propertyName, propertyType, propertyParent, visibility)
|
||||
|
||||
fun generatePropertyMissingParts(
|
||||
property: IrProperty?,
|
||||
propertyName: Name,
|
||||
propertyType: IrType,
|
||||
propertyParent: IrClass,
|
||||
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE
|
||||
): IrProperty {
|
||||
val irProperty = propertyParent.searchForDeclaration(propertyDescriptor) ?: run {
|
||||
with(propertyDescriptor) {
|
||||
propertyParent.factory.createProperty(
|
||||
propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrPropertySymbolImpl(propertyDescriptor),
|
||||
name, visibility, modality, isVar, isConst, isLateInit, isDelegated, isExternal
|
||||
).also {
|
||||
it.parent = propertyParent
|
||||
propertyParent.addMember(it)
|
||||
}
|
||||
}
|
||||
val field = property?.backingField ?: propertyParent.factory.buildField {
|
||||
startOffset = propertyParent.startOffset
|
||||
endOffset = propertyParent.endOffset
|
||||
name = propertyName
|
||||
type = propertyType
|
||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||
isFinal = true
|
||||
this.visibility = DescriptorVisibilities.PRIVATE
|
||||
}.also { it.parent = propertyParent }
|
||||
|
||||
val prop = property ?: propertyParent.addProperty {
|
||||
startOffset = propertyParent.startOffset
|
||||
endOffset = propertyParent.endOffset
|
||||
name = propertyName
|
||||
this.isVar = false
|
||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||
}
|
||||
|
||||
propertyParent.generatePropertyBackingFieldIfNeeded(propertyDescriptor, irProperty, fieldName)
|
||||
val fieldSymbol = irProperty.backingField!!.symbol
|
||||
irProperty.getter = propertyDescriptor.getter?.let {
|
||||
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = true)
|
||||
}?.apply { parent = propertyParent }
|
||||
irProperty.setter = propertyDescriptor.setter?.let {
|
||||
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = false)
|
||||
}?.apply { parent = propertyParent }
|
||||
return irProperty
|
||||
}
|
||||
|
||||
fun IrType.kClassToJClassIfNeeded(): IrType = this
|
||||
|
||||
fun kClassExprToJClassIfNeeded(startOffset: Int, endOffset: Int, irExpression: IrExpression): IrExpression = irExpression
|
||||
|
||||
private fun IrClass.generatePropertyBackingFieldIfNeeded(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
originProperty: IrProperty,
|
||||
name: Name,
|
||||
) {
|
||||
if (originProperty.backingField != null) return
|
||||
|
||||
val field = with(propertyDescriptor) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class)// should be called only with old FE
|
||||
originProperty.factory.createField(
|
||||
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(),
|
||||
visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null
|
||||
)
|
||||
}
|
||||
field.apply {
|
||||
parent = this@generatePropertyBackingFieldIfNeeded
|
||||
correspondingPropertySymbol = originProperty.symbol
|
||||
prop.apply {
|
||||
field.correspondingPropertySymbol = this.symbol
|
||||
backingField = field
|
||||
}
|
||||
|
||||
originProperty.backingField = field
|
||||
}
|
||||
|
||||
private fun IrClass.generatePropertyAccessor(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
property: IrProperty,
|
||||
descriptor: PropertyAccessorDescriptor,
|
||||
fieldSymbol: IrFieldSymbol,
|
||||
isGetter: Boolean,
|
||||
): IrSimpleFunction {
|
||||
val irAccessor: IrSimpleFunction = when (isGetter) {
|
||||
true -> searchForDeclaration<IrProperty>(propertyDescriptor)?.getter
|
||||
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
|
||||
} ?: run {
|
||||
with(descriptor) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
property.factory.createFunction(
|
||||
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
|
||||
name, visibility, modality, returnType!!.toIrType(),
|
||||
isInline, isEffectivelyExternal(), isTailrec, isSuspend, isOperator, isInfix, isExpect
|
||||
)
|
||||
}.also { f ->
|
||||
generateOverriddenFunctionSymbols(f, compilerContext.symbolTable)
|
||||
f.createParameterDeclarations(descriptor)
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
f.returnType = descriptor.returnType!!.toIrType()
|
||||
f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol
|
||||
}
|
||||
val getter = prop.getter ?: prop.addGetter {
|
||||
startOffset = propertyParent.startOffset
|
||||
endOffset = propertyParent.endOffset
|
||||
returnType = propertyType
|
||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||
this.visibility = visibility
|
||||
modality = Modality.FINAL
|
||||
}
|
||||
|
||||
irAccessor.body = when (isGetter) {
|
||||
true -> generateDefaultGetterBody(irAccessor)
|
||||
false -> generateDefaultSetterBody(irAccessor)
|
||||
getter.apply {
|
||||
if (dispatchReceiverParameter == null)
|
||||
dispatchReceiverParameter = propertyParent.thisReceiver!!.copyTo(this, type = propertyParent.defaultType)
|
||||
if (body == null)
|
||||
body = compilerContext.irBuiltIns.createIrBuilder(symbol, propertyParent.startOffset, propertyParent.endOffset).irBlockBody {
|
||||
+irReturn(irGetField(irGet(dispatchReceiverParameter!!), field))
|
||||
}
|
||||
}
|
||||
|
||||
return irAccessor
|
||||
}
|
||||
|
||||
private fun generateDefaultGetterBody(
|
||||
irAccessor: IrSimpleFunction
|
||||
): IrBlockBody {
|
||||
val irProperty = irAccessor.correspondingPropertySymbol?.owner ?: error("Expected corresponding property for accessor ${irAccessor.render()}")
|
||||
|
||||
val startOffset = irAccessor.startOffset
|
||||
val endOffset = irAccessor.endOffset
|
||||
val irBody = irAccessor.factory.createBlockBody(startOffset, endOffset)
|
||||
|
||||
val receiver = generateReceiverExpressionForFieldAccess(irAccessor.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
val propertyIrType = irAccessor.returnType
|
||||
irBody.statements.add(
|
||||
IrReturnImpl(
|
||||
startOffset, endOffset, compilerContext.irBuiltIns.nothingType,
|
||||
irAccessor.symbol,
|
||||
IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
irProperty.backingField?.symbol ?: error("Property expected to have backing field"),
|
||||
propertyIrType,
|
||||
receiver
|
||||
).let {
|
||||
if (propertyIrType.isKClass()) {
|
||||
irAccessor.returnType = irAccessor.returnType.kClassToJClassIfNeeded()
|
||||
kClassExprToJClassIfNeeded(startOffset, endOffset, it)
|
||||
} else it
|
||||
}
|
||||
)
|
||||
)
|
||||
return irBody
|
||||
}
|
||||
|
||||
private fun generateDefaultSetterBody(
|
||||
irAccessor: IrSimpleFunction
|
||||
): IrBlockBody {
|
||||
val irProperty = irAccessor.correspondingPropertySymbol?.owner ?: error("Expected corresponding property for accessor ${irAccessor.render()}")
|
||||
val startOffset = irAccessor.startOffset
|
||||
val endOffset = irAccessor.endOffset
|
||||
val irBody = irAccessor.factory.createBlockBody(startOffset, endOffset)
|
||||
|
||||
val receiver = generateReceiverExpressionForFieldAccess(irAccessor.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
val irValueParameter = irAccessor.valueParameters.single()
|
||||
irBody.statements.add(
|
||||
IrSetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
irProperty.backingField?.symbol ?: error("Property ${irProperty.render()} expected to have backing field"),
|
||||
receiver,
|
||||
IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol),
|
||||
compilerContext.irBuiltIns.unitType
|
||||
)
|
||||
)
|
||||
return irBody
|
||||
}
|
||||
|
||||
fun generateReceiverExpressionForFieldAccess(
|
||||
ownerSymbol: IrValueSymbol
|
||||
): IrExpression = IrGetValueImpl(
|
||||
ownerSymbol.owner.startOffset, ownerSymbol.owner.endOffset,
|
||||
ownerSymbol
|
||||
)
|
||||
|
||||
fun IrFunction.createParameterDeclarations(
|
||||
descriptor: FunctionDescriptor,
|
||||
overwriteValueParameters: Boolean = false,
|
||||
copyTypeParameters: Boolean = true
|
||||
) {
|
||||
val function = this
|
||||
fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
factory.createValueParameter(
|
||||
function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this),
|
||||
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline,
|
||||
isHidden = false, isAssignable = false
|
||||
).also {
|
||||
it.parent = function
|
||||
}
|
||||
}
|
||||
|
||||
if (copyTypeParameters) {
|
||||
assert(typeParameters.isEmpty())
|
||||
copyTypeParamsFromDescriptor(descriptor)
|
||||
}
|
||||
|
||||
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { irValueParameter(it) }
|
||||
extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { irValueParameter(it) }
|
||||
|
||||
if (!overwriteValueParameters)
|
||||
assert(valueParameters.isEmpty())
|
||||
|
||||
valueParameters = descriptor.valueParameters.map { irValueParameter(it) }
|
||||
}
|
||||
|
||||
fun IrFunction.copyTypeParamsFromDescriptor(descriptor: FunctionDescriptor) {
|
||||
val newTypeParameters = descriptor.typeParameters.map {
|
||||
factory.createTypeParameter(
|
||||
startOffset, endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
IrTypeParameterSymbolImpl(it),
|
||||
it.name, it.index, it.isReified, it.variance
|
||||
).also { typeParameter ->
|
||||
typeParameter.parent = this
|
||||
}
|
||||
}
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
newTypeParameters.forEach { typeParameter ->
|
||||
typeParameter.superTypes = typeParameter.descriptor.upperBounds.map { it.toIrType() }
|
||||
}
|
||||
|
||||
typeParameters = newTypeParameters
|
||||
return prop
|
||||
}
|
||||
|
||||
fun createClassReference(classType: IrType, startOffset: Int, endOffset: Int): IrClassReference {
|
||||
|
||||
+2
@@ -35,6 +35,8 @@ internal fun IrType.isKSerializer(): Boolean {
|
||||
return fqName == SerialEntityNames.KSERIALIZER_NAME_FQ || fqName == SerialEntityNames.GENERATED_SERIALIZER_FQ
|
||||
}
|
||||
|
||||
internal fun IrType.isGeneratedKSerializer(): Boolean = classifierOrNull?.isClassWithFqName(SerialEntityNames.GENERATED_SERIALIZER_FQ.toUnsafe()) == true
|
||||
|
||||
internal val IrClass.isInternalSerializable: Boolean
|
||||
get() {
|
||||
if (kind != ClassKind.CLASS) return false
|
||||
|
||||
+242
-14
@@ -7,32 +7,29 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
|
||||
import org.jetbrains.kotlin.backend.common.ir.addExtensionReceiver
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.kotlinFqName
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
|
||||
@@ -115,13 +112,13 @@ class SerialInfoImplJvmIrGenerator(
|
||||
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, name))
|
||||
}
|
||||
|
||||
override fun IrType.kClassToJClassIfNeeded(): IrType = when {
|
||||
private fun IrType.kClassToJClassIfNeeded(): IrType = when {
|
||||
this.isKClass() -> javaLangType
|
||||
this.isKClassArray() -> compilerContext.irBuiltIns.arrayClass.typeWith(javaLangType)
|
||||
else -> this
|
||||
}
|
||||
|
||||
override fun kClassExprToJClassIfNeeded(startOffset: Int, endOffset: Int, irExpression: IrExpression): IrExpression {
|
||||
private fun kClassExprToJClassIfNeeded(startOffset: Int, endOffset: Int, irExpression: IrExpression): IrExpression {
|
||||
val getterSymbol = kClassJava.owner.getter!!.symbol
|
||||
return IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
@@ -149,7 +146,15 @@ class SerialInfoImplJvmIrGenerator(
|
||||
addGetter().apply {
|
||||
annotations = listOf(
|
||||
IrConstructorCallImpl.fromSymbolOwner(jvmName.typeWith(), jvmName.constructors.single()).apply {
|
||||
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, "getJavaClass"))
|
||||
putValueArgument(
|
||||
0,
|
||||
IrConstImpl.string(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
context.irBuiltIns.stringType,
|
||||
"getJavaClass"
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
addExtensionReceiver(context.irBuiltIns.kClassClass.starProjectedType)
|
||||
@@ -180,4 +185,227 @@ class SerialInfoImplJvmIrGenerator(
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
block(this)
|
||||
}.symbol
|
||||
|
||||
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
|
||||
return declarations.singleOrNull { it.descriptor == descriptor } as? T
|
||||
}
|
||||
|
||||
private fun generateSimplePropertyWithBackingField(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
propertyParent: IrClass,
|
||||
fieldName: Name = propertyDescriptor.name,
|
||||
): IrProperty {
|
||||
val irProperty = propertyParent.searchForDeclaration(propertyDescriptor) ?: run {
|
||||
with(propertyDescriptor) {
|
||||
propertyParent.factory.createProperty(
|
||||
propertyParent.startOffset,
|
||||
propertyParent.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
IrPropertySymbolImpl(propertyDescriptor),
|
||||
name,
|
||||
visibility,
|
||||
modality,
|
||||
isVar,
|
||||
isConst,
|
||||
isLateInit,
|
||||
isDelegated,
|
||||
isExternal
|
||||
).also {
|
||||
it.parent = propertyParent
|
||||
propertyParent.addMember(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propertyParent.generatePropertyBackingFieldIfNeeded(propertyDescriptor, irProperty, fieldName)
|
||||
val fieldSymbol = irProperty.backingField!!.symbol
|
||||
irProperty.getter = propertyDescriptor.getter?.let {
|
||||
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = true)
|
||||
}?.apply { parent = propertyParent }
|
||||
irProperty.setter = propertyDescriptor.setter?.let {
|
||||
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = false)
|
||||
}?.apply { parent = propertyParent }
|
||||
return irProperty
|
||||
}
|
||||
|
||||
private fun IrClass.generatePropertyBackingFieldIfNeeded(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
originProperty: IrProperty,
|
||||
name: Name,
|
||||
) {
|
||||
if (originProperty.backingField != null) return
|
||||
|
||||
val field = with(propertyDescriptor) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class)// should be called only with old FE
|
||||
originProperty.factory.createField(
|
||||
originProperty.startOffset,
|
||||
originProperty.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
IrFieldSymbolImpl(propertyDescriptor),
|
||||
name,
|
||||
type.toIrType(),
|
||||
visibility,
|
||||
!isVar,
|
||||
isEffectivelyExternal(),
|
||||
dispatchReceiverParameter == null
|
||||
)
|
||||
}
|
||||
field.apply {
|
||||
parent = this@generatePropertyBackingFieldIfNeeded
|
||||
correspondingPropertySymbol = originProperty.symbol
|
||||
}
|
||||
|
||||
originProperty.backingField = field
|
||||
}
|
||||
|
||||
private fun IrClass.generatePropertyAccessor(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
property: IrProperty,
|
||||
descriptor: PropertyAccessorDescriptor,
|
||||
fieldSymbol: IrFieldSymbol,
|
||||
isGetter: Boolean,
|
||||
): IrSimpleFunction {
|
||||
val irAccessor: IrSimpleFunction = when (isGetter) {
|
||||
true -> searchForDeclaration<IrProperty>(propertyDescriptor)?.getter
|
||||
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
|
||||
} ?: run {
|
||||
with(descriptor) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
property.factory.createFunction(
|
||||
fieldSymbol.owner.startOffset,
|
||||
fieldSymbol.owner.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
|
||||
name, visibility, modality, returnType!!.toIrType(),
|
||||
isInline, isEffectivelyExternal(), isTailrec, isSuspend, isOperator, isInfix, isExpect
|
||||
)
|
||||
}.also { f ->
|
||||
generateOverriddenFunctionSymbols(f, compilerContext.symbolTable)
|
||||
f.createParameterDeclarations(descriptor)
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
f.returnType = descriptor.returnType!!.toIrType()
|
||||
f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol
|
||||
}
|
||||
}
|
||||
|
||||
irAccessor.body = when (isGetter) {
|
||||
true -> generateDefaultGetterBody(irAccessor)
|
||||
false -> generateDefaultSetterBody(irAccessor)
|
||||
}
|
||||
|
||||
return irAccessor
|
||||
}
|
||||
|
||||
private fun generateDefaultGetterBody(
|
||||
irAccessor: IrSimpleFunction
|
||||
): IrBlockBody {
|
||||
val irProperty =
|
||||
irAccessor.correspondingPropertySymbol?.owner ?: error("Expected corresponding property for accessor ${irAccessor.render()}")
|
||||
|
||||
val startOffset = irAccessor.startOffset
|
||||
val endOffset = irAccessor.endOffset
|
||||
val irBody = irAccessor.factory.createBlockBody(startOffset, endOffset)
|
||||
|
||||
val receiver = generateReceiverExpressionForFieldAccess(irAccessor.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
val propertyIrType = irAccessor.returnType
|
||||
irBody.statements.add(
|
||||
IrReturnImpl(
|
||||
startOffset, endOffset, compilerContext.irBuiltIns.nothingType,
|
||||
irAccessor.symbol,
|
||||
IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
irProperty.backingField?.symbol ?: error("Property expected to have backing field"),
|
||||
propertyIrType,
|
||||
receiver
|
||||
).let {
|
||||
if (propertyIrType.isKClass()) {
|
||||
irAccessor.returnType = irAccessor.returnType.kClassToJClassIfNeeded()
|
||||
kClassExprToJClassIfNeeded(startOffset, endOffset, it)
|
||||
} else it
|
||||
}
|
||||
)
|
||||
)
|
||||
return irBody
|
||||
}
|
||||
|
||||
private fun generateDefaultSetterBody(
|
||||
irAccessor: IrSimpleFunction
|
||||
): IrBlockBody {
|
||||
val irProperty =
|
||||
irAccessor.correspondingPropertySymbol?.owner ?: error("Expected corresponding property for accessor ${irAccessor.render()}")
|
||||
val startOffset = irAccessor.startOffset
|
||||
val endOffset = irAccessor.endOffset
|
||||
val irBody = irAccessor.factory.createBlockBody(startOffset, endOffset)
|
||||
|
||||
val receiver = generateReceiverExpressionForFieldAccess(irAccessor.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
val irValueParameter = irAccessor.valueParameters.single()
|
||||
irBody.statements.add(
|
||||
IrSetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
irProperty.backingField?.symbol ?: error("Property ${irProperty.render()} expected to have backing field"),
|
||||
receiver,
|
||||
IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol),
|
||||
compilerContext.irBuiltIns.unitType
|
||||
)
|
||||
)
|
||||
return irBody
|
||||
}
|
||||
|
||||
private fun generateReceiverExpressionForFieldAccess(
|
||||
ownerSymbol: IrValueSymbol
|
||||
): IrExpression = IrGetValueImpl(
|
||||
ownerSymbol.owner.startOffset, ownerSymbol.owner.endOffset,
|
||||
ownerSymbol
|
||||
)
|
||||
|
||||
private fun IrFunction.createParameterDeclarations(
|
||||
descriptor: FunctionDescriptor,
|
||||
overwriteValueParameters: Boolean = false,
|
||||
copyTypeParameters: Boolean = true
|
||||
) {
|
||||
val function = this
|
||||
fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
factory.createValueParameter(
|
||||
function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this),
|
||||
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline,
|
||||
isHidden = false, isAssignable = false
|
||||
).also {
|
||||
it.parent = function
|
||||
}
|
||||
}
|
||||
|
||||
if (copyTypeParameters) {
|
||||
assert(typeParameters.isEmpty())
|
||||
copyTypeParamsFromDescriptor(descriptor)
|
||||
}
|
||||
|
||||
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { irValueParameter(it) }
|
||||
extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { irValueParameter(it) }
|
||||
|
||||
if (!overwriteValueParameters)
|
||||
assert(valueParameters.isEmpty())
|
||||
|
||||
valueParameters = descriptor.valueParameters.map { irValueParameter(it) }
|
||||
}
|
||||
|
||||
private fun IrFunction.copyTypeParamsFromDescriptor(descriptor: FunctionDescriptor) {
|
||||
val newTypeParameters = descriptor.typeParameters.map {
|
||||
factory.createTypeParameter(
|
||||
startOffset, endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
IrTypeParameterSymbolImpl(it),
|
||||
it.name, it.index, it.isReified, it.variance
|
||||
).also { typeParameter ->
|
||||
typeParameter.parent = this
|
||||
}
|
||||
}
|
||||
@OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
|
||||
newTypeParameters.forEach { typeParameter ->
|
||||
typeParameter.superTypes = typeParameter.descriptor.upperBounds.map { it.toIrType() }
|
||||
}
|
||||
|
||||
typeParameters = newTypeParameters
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ class SerializerForEnumsGenerator(
|
||||
irClass: IrClass,
|
||||
compilerContext: SerializationPluginContext,
|
||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||
) : SerializerIrGenerator(irClass, compilerContext, null, serialInfoJvmGenerator) {
|
||||
) : SerializerIrGenerator(irClass, compilerContext, null) {
|
||||
override fun generateSave(function: IrSimpleFunction) = addFunctionBody(function) { saveFunc ->
|
||||
fun irThis(): IrExpression =
|
||||
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
+1
-2
@@ -23,8 +23,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
class SerializerForInlineClassGenerator(
|
||||
irClass: IrClass,
|
||||
compilerContext: SerializationPluginContext,
|
||||
serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||
) : SerializerIrGenerator(irClass, compilerContext, null, serialInfoJvmGenerator) {
|
||||
) : SerializerIrGenerator(irClass, compilerContext, null) {
|
||||
override fun generateSave(function: IrSimpleFunction) = addFunctionBody(function) { saveFunc ->
|
||||
fun irThis(): IrExpression =
|
||||
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
|
||||
|
||||
+39
-31
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.codegen.CompilationException
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -41,6 +40,7 @@ import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPlug
|
||||
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.ENCODER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.LOAD
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SAVE
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_DECODER_CLASS
|
||||
@@ -55,14 +55,13 @@ open class SerializerIrGenerator(
|
||||
val irClass: IrClass,
|
||||
compilerContext: SerializationPluginContext,
|
||||
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
||||
private val serialInfoJvmGenerator: SerialInfoImplJvmIrGenerator,
|
||||
) : BaseIrGenerator(irClass, compilerContext) {
|
||||
protected val serializableIrClass = getSerializableClassDescriptorBySerializer(irClass)!!
|
||||
|
||||
protected val serialName: String = serializableIrClass.serialName()
|
||||
protected val properties = serializablePropertiesForIrBackend(serializableIrClass, metadataPlugin)
|
||||
protected val serializableProperties = properties.serializableProperties
|
||||
protected val isGeneratedSerializer = irClass.descriptor.typeConstructor.supertypes.any(::isGeneratedKSerializer) // TODO TODO
|
||||
protected val isGeneratedSerializer = irClass.superTypes.any(IrType::isGeneratedKSerializer)
|
||||
|
||||
protected val generatedSerialDescPropertyDescriptor = getProperty(
|
||||
SerialEntityNames.SERIAL_DESC_FIELD,
|
||||
@@ -71,7 +70,7 @@ open class SerializerIrGenerator(
|
||||
|
||||
protected val anySerialDescProperty = getProperty(
|
||||
SerialEntityNames.SERIAL_DESC_FIELD,
|
||||
) { true } // TODO REMOVE TRUE
|
||||
) { true } // remove true?
|
||||
|
||||
protected val irAnySerialDescProperty = anySerialDescProperty
|
||||
|
||||
@@ -82,18 +81,19 @@ open class SerializerIrGenerator(
|
||||
return irClass.properties.singleOrNull { it.name.asString() == name && isReturnTypeOk(it) }
|
||||
}
|
||||
|
||||
var localSerializersFieldsDescriptors: List<Pair<PropertyDescriptor, IrProperty>> = emptyList()
|
||||
protected set
|
||||
protected fun findLocalSerializersFieldDescriptors(): List<IrProperty> {
|
||||
var localSerializersFieldsDescriptors: List<IrProperty> = emptyList()
|
||||
private set
|
||||
|
||||
// null if was not found — we're in FIR
|
||||
private fun findLocalSerializersFieldDescriptors(): List<IrProperty?> {
|
||||
val count = serializableIrClass.typeParameters.size
|
||||
if (count == 0) return emptyList()
|
||||
val propNames = (0 until count).map { "${SerialEntityNames.typeArgPrefix}$it" }
|
||||
return propNames.mapNotNull { name ->
|
||||
return propNames.map { name ->
|
||||
getProperty(name) { it.getter!!.returnType.isKSerializer() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected open val serialDescImplClass: IrClassSymbol =
|
||||
compilerContext.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL)
|
||||
|
||||
@@ -106,11 +106,13 @@ open class SerializerIrGenerator(
|
||||
|
||||
// how to (auto)create backing field and getter/setter?
|
||||
compilerContext.symbolTable.withReferenceScope(irClass) {
|
||||
prop = generateSimplePropertyWithBackingField(desc.descriptor, irClass)
|
||||
prop = generatePropertyMissingParts(desc, desc.name, serialDescImplClass.starProjectedType, irClass, desc.visibility)
|
||||
|
||||
// TODO: Do not use descriptors here
|
||||
localSerializersFieldsDescriptors = findLocalSerializersFieldDescriptors().map { prop ->
|
||||
prop.descriptor to generateSimplePropertyWithBackingField(prop.descriptor, irClass)
|
||||
localSerializersFieldsDescriptors = findLocalSerializersFieldDescriptors().mapIndexed { i, prop ->
|
||||
generatePropertyMissingParts(
|
||||
prop, Name.identifier("${SerialEntityNames.typeArgPrefix}$i"),
|
||||
compilerContext.getClassFromRuntime(KSERIALIZER_CLASS).starProjectedType, irClass
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +143,8 @@ open class SerializerIrGenerator(
|
||||
|
||||
// save local descriptor to field
|
||||
+irSetField(
|
||||
generateReceiverExpressionForFieldAccess(
|
||||
IrGetValueImpl(
|
||||
startOffset, endOffset,
|
||||
thisAsReceiverParameter.symbol
|
||||
),
|
||||
prop.backingField!!,
|
||||
@@ -218,11 +221,9 @@ open class SerializerIrGenerator(
|
||||
// store type arguments serializers in fields
|
||||
val thisAsReceiverParameter = irClass.thisReceiver!!
|
||||
ctor.valueParameters.forEachIndexed { index, param ->
|
||||
val localSerial = localSerializersFieldsDescriptors[index].second.backingField!!
|
||||
val localSerial = localSerializersFieldsDescriptors[index].backingField!!
|
||||
+irSetField(
|
||||
generateReceiverExpressionForFieldAccess(
|
||||
thisAsReceiverParameter.symbol
|
||||
), localSerial, irGet(param)
|
||||
IrGetValueImpl(startOffset, endOffset, thisAsReceiverParameter.symbol), localSerial, irGet(param)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -243,7 +244,7 @@ open class SerializerIrGenerator(
|
||||
val typeParams = serializableIrClass.typeParameters.mapIndexed { idx, _ ->
|
||||
irGetField(
|
||||
irGet(irFun.dispatchReceiverParameter!!),
|
||||
localSerializersFieldsDescriptors[idx].second.backingField!!
|
||||
localSerializersFieldsDescriptors[idx].backingField!!
|
||||
)
|
||||
}
|
||||
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type
|
||||
@@ -268,7 +269,8 @@ open class SerializerIrGenerator(
|
||||
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
||||
|
||||
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
|
||||
val beginFunc = encoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||
val beginFunc =
|
||||
encoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||
|
||||
val call = irCall(beginFunc, type = kOutputClass.defaultType).mapValueParametersIndexed { _, _ ->
|
||||
irGet(localSerialDesc)
|
||||
@@ -283,9 +285,9 @@ open class SerializerIrGenerator(
|
||||
if (writeSelfFunction != null) {
|
||||
// extract Tx from KSerializer<Tx> list
|
||||
val typeArgs =
|
||||
localSerializersFieldsDescriptors.map { (_, ir) -> ir.backingField!!.type.cast<IrSimpleType>().arguments.single().typeOrNull }
|
||||
localSerializersFieldsDescriptors.map { ir -> ir.backingField!!.type.cast<IrSimpleType>().arguments.single().typeOrNull }
|
||||
val args = mutableListOf<IrExpression>(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc))
|
||||
args.addAll(localSerializersFieldsDescriptors.map { (_, ir) ->
|
||||
args.addAll(localSerializersFieldsDescriptors.map { ir ->
|
||||
irGetField(
|
||||
irGet(saveFunc.dispatchReceiverParameter!!),
|
||||
ir.backingField!!
|
||||
@@ -304,7 +306,7 @@ open class SerializerIrGenerator(
|
||||
serializableProperties, objectToSerialize, localOutput,
|
||||
localSerialDesc, kOutputClass, ignoreIndexTo = -1, initializerAdapter
|
||||
) { it, _ ->
|
||||
val (_, ir) = localSerializersFieldsDescriptors[it]
|
||||
val ir = localSerializersFieldsDescriptors[it]
|
||||
irGetField(irGet(saveFunc.dispatchReceiverParameter!!), ir.backingField!!)
|
||||
}
|
||||
}
|
||||
@@ -327,7 +329,7 @@ open class SerializerIrGenerator(
|
||||
whenHaveSerializer,
|
||||
whenDoNot,
|
||||
{ it, _ ->
|
||||
val (_, ir) = localSerializersFieldsDescriptors[it]
|
||||
val ir = localSerializersFieldsDescriptors[it]
|
||||
irGetField(irGet(dispatchReceiver), ir.backingField!!)
|
||||
},
|
||||
returnTypeHint
|
||||
@@ -401,7 +403,8 @@ open class SerializerIrGenerator(
|
||||
}
|
||||
|
||||
//input = input.beginStructure(...)
|
||||
val beginFunc = decoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||
val beginFunc =
|
||||
decoderClass.functions.single { it.owner.name.asString() == CallingConventions.begin && it.owner.valueParameters.size == 1 }
|
||||
val call = irInvoke(
|
||||
irGet(loadFunc.valueParameters[0]),
|
||||
beginFunc,
|
||||
@@ -422,7 +425,7 @@ open class SerializerIrGenerator(
|
||||
} to listOf(
|
||||
localSerialDesc.get(), irInt(index), innerSerial, serialPropertiesMap.getValue(property.ir).get()
|
||||
)
|
||||
}, {sti ->
|
||||
}, { sti ->
|
||||
inputClass.functions.single {
|
||||
it.owner.name.asString() == "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}" &&
|
||||
it.owner.valueParameters.size == 2
|
||||
@@ -461,7 +464,12 @@ open class SerializerIrGenerator(
|
||||
|
||||
// throw exception on unknown field
|
||||
|
||||
val excClassRef = compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(UNKNOWN_FIELD_EXC)))
|
||||
val excClassRef = compilerContext.referenceConstructors(
|
||||
ClassId(
|
||||
SerializationPackages.packageFqName,
|
||||
Name.identifier(UNKNOWN_FIELD_EXC)
|
||||
)
|
||||
)
|
||||
.single { it.owner.valueParameters.singleOrNull()?.type?.isInt() == true }
|
||||
+elseBranch(
|
||||
irThrow(
|
||||
@@ -594,7 +602,8 @@ open class SerializerIrGenerator(
|
||||
val save = irClass.findPluginGeneratedMethod(SAVE)?.let { generateSave(it); true } ?: false
|
||||
val load = irClass.findPluginGeneratedMethod(LOAD)?.let { generateLoad(it); true } ?: false
|
||||
irClass.findPluginGeneratedMethod(SerialEntityNames.CHILD_SERIALIZERS_GETTER.identifier)?.let { generateChildSerializersGetter(it) }
|
||||
irClass.findPluginGeneratedMethod(SerialEntityNames.TYPE_PARAMS_SERIALIZERS_GETTER.identifier)?.let { generateTypeParamsSerializersGetter(it) }
|
||||
irClass.findPluginGeneratedMethod(SerialEntityNames.TYPE_PARAMS_SERIALIZERS_GETTER.identifier)
|
||||
?.let { generateTypeParamsSerializersGetter(it) }
|
||||
if (!prop && (save || load))
|
||||
generateSerialDesc()
|
||||
if (serializableIrClass.typeParameters.isNotEmpty()) {
|
||||
@@ -605,7 +614,6 @@ open class SerializerIrGenerator(
|
||||
}
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
fun generate(
|
||||
irClass: IrClass,
|
||||
@@ -620,8 +628,8 @@ open class SerializerIrGenerator(
|
||||
context,
|
||||
serialInfoJvmGenerator
|
||||
)
|
||||
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context, serialInfoJvmGenerator)
|
||||
else -> SerializerIrGenerator(irClass, context, metadataPlugin, serialInfoJvmGenerator)
|
||||
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context)
|
||||
else -> SerializerIrGenerator(irClass, context, metadataPlugin)
|
||||
}
|
||||
generator.generate()
|
||||
irClass.addDefaultConstructorIfAbsent(context)
|
||||
|
||||
+44
-30
@@ -6,53 +6,40 @@
|
||||
package org.jetbrains.kotlinx.serialization.compiler.fir
|
||||
|
||||
import org.jetbrains.kotlin.GeneratedDeclarationKey
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildPrimaryConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.origin
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.addDefaultBoundIfNecessary
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.fir.types.constructClassLikeType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
|
||||
|
||||
// FIXME KT-53096: this has to be shared (copied from plugin example)
|
||||
@OptIn(SymbolInternals::class)
|
||||
fun FirDeclarationGenerationExtension.buildConstructor(classId: ClassId, isInner: Boolean, key: GeneratedDeclarationKey): FirConstructor {
|
||||
fun FirDeclarationGenerationExtension.buildPrimaryConstructor(owner: FirClassSymbol<*>, isInner: Boolean, key: GeneratedDeclarationKey, status: FirDeclarationStatus): FirConstructor {
|
||||
val classId = owner.classId
|
||||
val lookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||
return buildPrimaryConstructor {
|
||||
moduleData = session.moduleData
|
||||
origin = key.origin
|
||||
returnTypeRef = buildResolvedTypeRef {
|
||||
type = ConeClassLikeTypeImpl(
|
||||
lookupTag,
|
||||
emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.Public
|
||||
)
|
||||
returnTypeRef = owner.defaultType().newRef()
|
||||
this.status = status
|
||||
symbol = FirConstructorSymbol(classId)
|
||||
if (isInner && classId.isNestedClass) {
|
||||
dispatchReceiverType = classId.parentClassId?.let {
|
||||
@@ -63,4 +50,31 @@ fun FirDeclarationGenerationExtension.buildConstructor(classId: ClassId, isInner
|
||||
}.also {
|
||||
it.containingClassForStaticMemberAttr = lookupTag
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.newRef(): FirResolvedTypeRef = buildResolvedTypeRef {
|
||||
type = this@newRef
|
||||
}
|
||||
|
||||
fun newSimpleTypeParameter(firSession: FirSession, containingDeclarationSymbol: FirBasedSymbol<*>, name: Name) = buildTypeParameter {
|
||||
moduleData = firSession.moduleData
|
||||
origin = SerializationPluginKey.origin
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
variance = Variance.INVARIANT
|
||||
this.name = name
|
||||
symbol = FirTypeParameterSymbol()
|
||||
this.containingDeclarationSymbol = containingDeclarationSymbol
|
||||
isReified = false
|
||||
addDefaultBoundIfNecessary()
|
||||
}
|
||||
|
||||
fun newSimpleValueParameter(firSession: FirSession, typeRef: FirResolvedTypeRef, name: Name) = buildValueParameter {
|
||||
moduleData = firSession.moduleData
|
||||
origin = SerializationPluginKey.origin
|
||||
this.name = name
|
||||
this.symbol = FirValueParameterSymbol(this.name)
|
||||
returnTypeRef = typeRef
|
||||
isCrossinline = false
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
+58
-37
@@ -14,24 +14,22 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
|
||||
import org.jetbrains.kotlin.fir.copy
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.origin
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.addDefaultBoundIfNecessary
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
|
||||
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.constructClassLikeType
|
||||
@@ -170,13 +168,24 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
dispatchReceiverType = owner.defaultType()
|
||||
|
||||
// TODO: handle serializable objects
|
||||
val serializableType =
|
||||
val serializableClassSymbol =
|
||||
(owner.getContainingDeclarationSymbol(session) as? FirClassSymbol<*>) ?: error("Can't get outer class for $owner")
|
||||
|
||||
// TODO: Add value parameters & type parameters for parameterized classes
|
||||
typeParameters.addAll(serializableClassSymbol.typeParameterSymbols.map { newSimpleTypeParameter(session, symbol, it.name) })
|
||||
val parametersAsArguments = typeParameters.map { it.toConeType() }.toTypedArray<ConeTypeProjection>()
|
||||
|
||||
valueParameters.addAll(List(serializableClassSymbol.typeParameterSymbols.size) { i ->
|
||||
newSimpleValueParameter(
|
||||
session,
|
||||
kSerializerClassId.constructClassLikeType(arrayOf(parametersAsArguments[i]), false).newRef(),
|
||||
Name.identifier("${SerialEntityNames.typeArgPrefix}$i")
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
returnTypeRef = buildResolvedTypeRef {
|
||||
type = kSerializerClassId.constructClassLikeType(
|
||||
arrayOf(serializableType.defaultType().toTypeProjection(Variance.INVARIANT)),
|
||||
arrayOf(serializableClassSymbol.constructType(parametersAsArguments, false)),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
@@ -217,8 +226,37 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
}
|
||||
|
||||
override fun generateConstructors(context: MemberGenerationContext): List<FirConstructorSymbol> {
|
||||
val constructor = buildConstructor(context.owner.classId, isInner = false, SerializationPluginKey)
|
||||
return listOf(constructor.symbol)
|
||||
val owner = context.owner
|
||||
val defaultObjectConstructor = buildPrimaryConstructor(
|
||||
owner, isInner = false, SerializationPluginKey, status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Private,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.PrivateInClass
|
||||
)
|
||||
)
|
||||
if (owner.name == SerialEntityNames.SERIALIZER_CLASS_NAME && owner.typeParameterSymbols.isNotEmpty()) {
|
||||
val parameterizedConstructor = buildConstructor {
|
||||
moduleData = session.moduleData
|
||||
origin = SerializationPluginKey.origin
|
||||
returnTypeRef = defaultObjectConstructor.returnTypeRef
|
||||
symbol = FirConstructorSymbol(owner.classId)
|
||||
dispatchReceiverType = defaultObjectConstructor.dispatchReceiverType
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Private,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.PrivateInFile // accessed from a companion
|
||||
)
|
||||
valueParameters.addAll(owner.typeParameterSymbols.mapIndexed { i, typeParam ->
|
||||
newSimpleValueParameter(
|
||||
session,
|
||||
kSerializerClassId.constructClassLikeType(arrayOf(typeParam.toConeType()), false).newRef(),
|
||||
Name.identifier("${SerialEntityNames.typeArgPrefix}$i")
|
||||
)
|
||||
})
|
||||
}
|
||||
return listOf(defaultObjectConstructor.symbol, parameterizedConstructor.symbol)
|
||||
}
|
||||
return listOf(defaultObjectConstructor.symbol)
|
||||
}
|
||||
|
||||
fun addSerializerImplClass(
|
||||
@@ -244,36 +282,19 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
|
||||
|
||||
typeParameters.addAll(owner.typeParameterSymbols.map { param ->
|
||||
buildTypeParameter {
|
||||
moduleData = session.moduleData
|
||||
origin = SerializationPluginKey.origin
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
variance = Variance.INVARIANT
|
||||
name = param.name
|
||||
symbol = FirTypeParameterSymbol()
|
||||
containingDeclarationSymbol = this@buildRegularClass.symbol
|
||||
isReified = false
|
||||
addDefaultBoundIfNecessary() // there should be KSerializer but whatever
|
||||
}
|
||||
newSimpleTypeParameter(session, symbol, param.name)
|
||||
})
|
||||
|
||||
superTypeRefs += buildResolvedTypeRef {
|
||||
type = generatedSerializerClassId.constructClassLikeType(arrayOf(owner.constructStarProjectedType()), isNullable = false)
|
||||
}
|
||||
val parametersAsArguments = typeParameters.map { it.toConeType() }.toTypedArray<ConeTypeProjection>()
|
||||
superTypeRefs += generatedSerializerClassId.constructClassLikeType(
|
||||
arrayOf(
|
||||
owner.constructType(
|
||||
parametersAsArguments,
|
||||
isNullable = false
|
||||
)
|
||||
), isNullable = false
|
||||
).newRef()
|
||||
}
|
||||
// TODO: add typed constructor
|
||||
// val secondaryCtors =
|
||||
// if (!hasTypeParams)
|
||||
// emptyList()
|
||||
// else
|
||||
// listOf(
|
||||
// KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor(
|
||||
// serializerFirClass,
|
||||
// thisDescriptor,
|
||||
// typeParameters
|
||||
// )
|
||||
// )
|
||||
// serializerFirClass.secondaryConstructors = secondaryCtors
|
||||
return serializerFirClass.symbol
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -31,6 +31,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/classWithCompanionObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classWithGenericParameters.kt")
|
||||
public void testClassWithGenericParameters() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/classWithGenericParameters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultProperties.kt")
|
||||
public void testDefaultProperties() throws Exception {
|
||||
|
||||
+6
@@ -30,6 +30,12 @@ public class SerializationFirMembersTestGenerated extends AbstractSerializationF
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/classWithCompanionObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classWithGenericParameters.kt")
|
||||
public void testClassWithGenericParameters() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/classWithGenericParameters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultProperties.kt")
|
||||
public void testDefaultProperties() throws Exception {
|
||||
|
||||
+30
-12
@@ -1,7 +1,7 @@
|
||||
public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public final static ListOfUsers$$serializer INSTANCE
|
||||
|
||||
public final static kotlinx.serialization.descriptors.SerialDescriptor descriptor
|
||||
private final static kotlinx.serialization.internal.PluginGeneratedSerialDescriptor descriptor
|
||||
|
||||
static void <clinit>() {
|
||||
NEW (ListOfUsers$$serializer)
|
||||
@@ -23,8 +23,7 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
|
||||
ICONST_0
|
||||
INVOKEVIRTUAL (kotlinx/serialization/internal/PluginGeneratedSerialDescriptor, addElement, (Ljava/lang/String;Z)V)
|
||||
ALOAD (0)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
PUTSTATIC (ListOfUsers$$serializer, descriptor, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
PUTSTATIC (ListOfUsers$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
LABEL (L1)
|
||||
LINENUMBER (13)
|
||||
RETURN
|
||||
@@ -164,7 +163,14 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor()
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() {
|
||||
LABEL (L0)
|
||||
LINENUMBER (12)
|
||||
GETSTATIC (ListOfUsers$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public void serialize(kotlinx.serialization.encoding.Encoder encoder, ListOfUsers value) {
|
||||
LABEL (L0)
|
||||
@@ -320,7 +326,7 @@ public final class ListOfUsers : java/lang/Object {
|
||||
public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public final static OptionalUser$$serializer INSTANCE
|
||||
|
||||
public final static kotlinx.serialization.descriptors.SerialDescriptor descriptor
|
||||
private final static kotlinx.serialization.internal.PluginGeneratedSerialDescriptor descriptor
|
||||
|
||||
static void <clinit>() {
|
||||
NEW (OptionalUser$$serializer)
|
||||
@@ -342,8 +348,7 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
|
||||
ICONST_1
|
||||
INVOKEVIRTUAL (kotlinx/serialization/internal/PluginGeneratedSerialDescriptor, addElement, (Ljava/lang/String;Z)V)
|
||||
ALOAD (0)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
PUTSTATIC (OptionalUser$$serializer, descriptor, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
PUTSTATIC (OptionalUser$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
LABEL (L1)
|
||||
LINENUMBER (10)
|
||||
RETURN
|
||||
@@ -471,7 +476,14 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor()
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() {
|
||||
LABEL (L0)
|
||||
LINENUMBER (9)
|
||||
GETSTATIC (OptionalUser$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public void serialize(kotlinx.serialization.encoding.Encoder encoder, OptionalUser value) {
|
||||
LABEL (L0)
|
||||
@@ -699,7 +711,7 @@ public final class OptionalUser : java/lang/Object {
|
||||
public final class User$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public final static User$$serializer INSTANCE
|
||||
|
||||
public final static kotlinx.serialization.descriptors.SerialDescriptor descriptor
|
||||
private final static kotlinx.serialization.internal.PluginGeneratedSerialDescriptor descriptor
|
||||
|
||||
static void <clinit>() {
|
||||
NEW (User$$serializer)
|
||||
@@ -725,8 +737,7 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
|
||||
ICONST_0
|
||||
INVOKEVIRTUAL (kotlinx/serialization/internal/PluginGeneratedSerialDescriptor, addElement, (Ljava/lang/String;Z)V)
|
||||
ALOAD (0)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
PUTSTATIC (User$$serializer, descriptor, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
PUTSTATIC (User$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
LABEL (L1)
|
||||
LINENUMBER (7)
|
||||
RETURN
|
||||
@@ -876,7 +887,14 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor()
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() {
|
||||
LABEL (L0)
|
||||
LINENUMBER (6)
|
||||
GETSTATIC (User$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public void serialize(kotlinx.serialization.encoding.Encoder encoder, User value) {
|
||||
LABEL (L0)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// CURIOUS_ABOUT serialize, deserialize, write$Self, childSerializers, <init>, <clinit>
|
||||
// CURIOUS_ABOUT serialize, deserialize, write$Self, childSerializers, <init>, <clinit>, getDescriptor
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
|
||||
+18
-3
@@ -145,7 +145,12 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
|
||||
ARETURN
|
||||
}
|
||||
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor()
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() {
|
||||
LABEL (L0)
|
||||
GETSTATIC (ListOfUsers$$serializer, $$serialDesc, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public void serialize(kotlinx.serialization.encoding.Encoder encoder, ListOfUsers value) {
|
||||
LABEL (L0)
|
||||
@@ -428,7 +433,12 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
|
||||
ARETURN
|
||||
}
|
||||
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor()
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() {
|
||||
LABEL (L0)
|
||||
GETSTATIC (OptionalUser$$serializer, $$serialDesc, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public void serialize(kotlinx.serialization.encoding.Encoder encoder, OptionalUser value) {
|
||||
LABEL (L0)
|
||||
@@ -794,7 +804,12 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
|
||||
ARETURN
|
||||
}
|
||||
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor()
|
||||
public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() {
|
||||
LABEL (L0)
|
||||
GETSTATIC (User$$serializer, $$serialDesc, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public void serialize(kotlinx.serialization.encoding.Encoder encoder, User value) {
|
||||
LABEL (L0)
|
||||
|
||||
Vendored
+2
-3
@@ -11,7 +11,7 @@ public final class DelegatedKt : java/lang/Object {
|
||||
public final class Test$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public final static Test$$serializer INSTANCE
|
||||
|
||||
public final static kotlinx.serialization.descriptors.SerialDescriptor descriptor
|
||||
private final static kotlinx.serialization.internal.PluginGeneratedSerialDescriptor descriptor
|
||||
|
||||
static void <clinit>() {
|
||||
NEW (Test$$serializer)
|
||||
@@ -27,8 +27,7 @@ public final class Test$$serializer : java/lang/Object, kotlinx/serialization/in
|
||||
CHECKCAST (kotlinx/serialization/internal/GeneratedSerializer)
|
||||
ICONST_0
|
||||
INVOKESPECIAL (kotlinx/serialization/internal/PluginGeneratedSerialDescriptor, <init>, (Ljava/lang/String;Lkotlinx/serialization/internal/GeneratedSerializer;I)V)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
PUTSTATIC (Test$$serializer, descriptor, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
PUTSTATIC (Test$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
LABEL (L1)
|
||||
LINENUMBER (13)
|
||||
RETURN
|
||||
|
||||
+4
-6
@@ -1,7 +1,7 @@
|
||||
public final class Container$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public final static Container$$serializer INSTANCE
|
||||
|
||||
public final static kotlinx.serialization.descriptors.SerialDescriptor descriptor
|
||||
private final static kotlinx.serialization.internal.PluginGeneratedSerialDescriptor descriptor
|
||||
|
||||
static void <clinit>() {
|
||||
NEW (Container$$serializer)
|
||||
@@ -23,8 +23,7 @@ public final class Container$$serializer : java/lang/Object, kotlinx/serializati
|
||||
ICONST_0
|
||||
INVOKEVIRTUAL (kotlinx/serialization/internal/PluginGeneratedSerialDescriptor, addElement, (Ljava/lang/String;Z)V)
|
||||
ALOAD (0)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
PUTSTATIC (Container$$serializer, descriptor, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
PUTSTATIC (Container$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
LABEL (L1)
|
||||
LINENUMBER (19)
|
||||
RETURN
|
||||
@@ -479,7 +478,7 @@ public final class Result$Err : Result {
|
||||
public final class Result$OK$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public final static Result$OK$$serializer INSTANCE
|
||||
|
||||
public final static kotlinx.serialization.descriptors.SerialDescriptor descriptor
|
||||
private final static kotlinx.serialization.internal.PluginGeneratedSerialDescriptor descriptor
|
||||
|
||||
static void <clinit>() {
|
||||
NEW (Result$OK$$serializer)
|
||||
@@ -501,8 +500,7 @@ public final class Result$OK$$serializer : java/lang/Object, kotlinx/serializati
|
||||
ICONST_0
|
||||
INVOKEVIRTUAL (kotlinx/serialization/internal/PluginGeneratedSerialDescriptor, addElement, (Ljava/lang/String;Z)V)
|
||||
ALOAD (0)
|
||||
CHECKCAST (kotlinx/serialization/descriptors/SerialDescriptor)
|
||||
PUTSTATIC (Result$OK$$serializer, descriptor, Lkotlinx/serialization/descriptors/SerialDescriptor;)
|
||||
PUTSTATIC (Result$OK$$serializer, descriptor, Lkotlinx/serialization/internal/PluginGeneratedSerialDescriptor;)
|
||||
RETURN
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ FILE: classWithCompanionObject.kt
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<SomeClass>|
|
||||
|
||||
public constructor(): R|SomeClass.Companion|
|
||||
private constructor(): R|SomeClass.Companion|
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ FILE: classWithCompanionObject.kt
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
public constructor(): R|SomeClass.$serializer|
|
||||
private constructor(): R|SomeClass.$serializer|
|
||||
|
||||
}
|
||||
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
FILE: classWithGenericParameters.kt
|
||||
@R|kotlinx/serialization/Serializable|() public final class GenericBox<T, V> : R|kotlin/Any| {
|
||||
public constructor<T, V>(i: R|kotlin/Int|, t: R|T|, vs: R|kotlin/collections/List<V>|): R|GenericBox<T, V>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val i: R|kotlin/Int| = R|<local>/i|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val t: R|T| = R|<local>/t|
|
||||
public get(): R|T|
|
||||
|
||||
public final val vs: R|kotlin/collections/List<V>| = R|<local>/vs|
|
||||
public get(): R|kotlin/collections/List<V>|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun <T, V> serializer(typeSerial0: R|kotlinx/serialization/KSerializer<T>|, typeSerial1: R|kotlinx/serialization/KSerializer<V>|): R|kotlinx/serialization/KSerializer<GenericBox<T, V>>|
|
||||
|
||||
private constructor(): R|GenericBox.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final class $serializer<T, V> : R|kotlinx/serialization/internal/GeneratedSerializer<GenericBox<T, V>>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|GenericBox<T, V>|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|GenericBox<T, V>|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
public final fun typeParametersSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|GenericBox.$serializer<T, V>|
|
||||
|
||||
private constructor(typeSerial0: R|kotlinx/serialization/KSerializer<T>|, typeSerial1: R|kotlinx/serialization/KSerializer<V>|): R|GenericBox.$serializer<T, V>|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final fun box(): R|kotlin/String| {
|
||||
lval box: R|GenericBox<kotlin/String, kotlin/Boolean>| = R|/GenericBox.GenericBox|<R|kotlin/String|, R|kotlin/Boolean|>(Int(42), String(foo), R|kotlin/collections/listOf|<R|kotlin/Boolean|>(vararg(Boolean(true), Boolean(false))))
|
||||
lval serial: R|kotlinx/serialization/KSerializer<GenericBox<kotlin/String, kotlin/Boolean>>| = Q|GenericBox|.R|/GenericBox.Companion.serializer|<R|kotlin/String|, R|kotlin/Boolean|>(Q|kotlin/String|.R|kotlinx/serialization/builtins/serializer|(), Q|kotlin/Boolean|.R|kotlinx/serialization/builtins/serializer|())
|
||||
lval target: R|kotlin/String| = String({"i":42,"t":"foo","vs":[true,false]})
|
||||
lval s: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|GenericBox<kotlin/String, kotlin/Boolean>|>(R|<local>/serial|, R|<local>/box|)
|
||||
when () {
|
||||
!=(R|<local>/target|, R|<local>/s|) -> {
|
||||
^box <strcat>(String(Incorrect serialization: ), R|<local>/s|)
|
||||
}
|
||||
}
|
||||
|
||||
lval decoded: R|GenericBox<kotlin/String, kotlin/Boolean>| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|GenericBox<kotlin/String, kotlin/Boolean>|>(R|<local>/serial|, R|<local>/s|)
|
||||
when () {
|
||||
!=(R|<local>/box|.R|SubstitutionOverride</GenericBox.t: R|kotlin/String|>|, R|<local>/decoded|.R|SubstitutionOverride</GenericBox.t: R|kotlin/String|>|) || !=(R|<local>/box|.R|SubstitutionOverride</GenericBox.vs: R|kotlin/collections/List<kotlin/Boolean>|>|, R|<local>/decoded|.R|SubstitutionOverride</GenericBox.vs: R|kotlin/collections/List<kotlin/Boolean>|>|) -> {
|
||||
^box String(Incorrect deserialization)
|
||||
}
|
||||
}
|
||||
|
||||
^box String(OK)
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlinx.serialization.builtins.*
|
||||
|
||||
@Serializable
|
||||
class GenericBox<T, V>(
|
||||
val i: Int,
|
||||
val t: T,
|
||||
val vs: List<V>
|
||||
)
|
||||
|
||||
fun box(): String {
|
||||
val box = GenericBox(42, "foo", listOf(true, false))
|
||||
val serial = GenericBox.serializer(String.serializer(), Boolean.serializer())
|
||||
val target = """{"i":42,"t":"foo","vs":[true,false]}"""
|
||||
val s = Json.encodeToString(serial, box)
|
||||
if (target != s) return "Incorrect serialization: $s"
|
||||
val decoded = Json.decodeFromString(serial, s)
|
||||
if (box.t != decoded.t || box.vs != decoded.vs) return "Incorrect deserialization"
|
||||
return "OK"
|
||||
}
|
||||
+2
-2
@@ -27,7 +27,7 @@ FILE: defaultProperties.kt
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<SomeClass>|
|
||||
|
||||
public constructor(): R|SomeClass.Companion|
|
||||
private constructor(): R|SomeClass.Companion|
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ FILE: defaultProperties.kt
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
public constructor(): R|SomeClass.$serializer|
|
||||
private constructor(): R|SomeClass.$serializer|
|
||||
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ FILE: multipleProperties.kt
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<SomeClass>|
|
||||
|
||||
public constructor(): R|SomeClass.Companion|
|
||||
private constructor(): R|SomeClass.Companion|
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ FILE: multipleProperties.kt
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
public constructor(): R|SomeClass.$serializer|
|
||||
private constructor(): R|SomeClass.$serializer|
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user