[KTX.SERIALIZATION] Refactor plugin once again
This commit is contained in:
+133
-146
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
+6
-12
@@ -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(
|
||||
|
||||
+38
-29
@@ -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) +
|
||||
|
||||
+12
-8
@@ -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),
|
||||
|
||||
+38
-34
@@ -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))
|
||||
|
||||
+6
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user