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