Patch serializable class with addtional annotation
(which contains actual serializer) to make use of it with @AssociatedObjectKey
This commit is contained in:
+21
-6
@@ -12,23 +12,36 @@ 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.*
|
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.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.*
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
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.*
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
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.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
|
||||||
val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable
|
val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable
|
||||||
@@ -386,7 +399,7 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.classReference(classType: KotlinType): IrClassReference {
|
fun createClassReference(classType: KotlinType, startOffset: Int, endOffset: Int): IrClassReference {
|
||||||
val clazz = classType.toClassDescriptor!!
|
val clazz = classType.toClassDescriptor!!
|
||||||
val kClass = clazz.module.findClassAcrossModuleDependencies(ClassId(FqName("kotlin.reflect"), Name.identifier("KClass")))!!
|
val kClass = clazz.module.findClassAcrossModuleDependencies(ClassId(FqName("kotlin.reflect"), Name.identifier("KClass")))!!
|
||||||
val returnType =
|
val returnType =
|
||||||
@@ -400,6 +413,8 @@ interface IrBuilderExtension {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.classReference(classType: KotlinType): IrClassReference = createClassReference(classType, startOffset, endOffset)
|
||||||
|
|
||||||
fun buildInitializersRemapping(irClass: IrClass): (IrField) -> IrExpression? {
|
fun buildInitializersRemapping(irClass: IrClass): (IrField) -> IrExpression? {
|
||||||
val original = irClass.constructors.singleOrNull { it.isPrimary }
|
val original = irClass.constructors.singleOrNull { it.isPrimary }
|
||||||
?: throw IllegalStateException("Serializable class must have single primary constructor")
|
?: throw IllegalStateException("Serializable class must have single primary constructor")
|
||||||
|
|||||||
+40
-3
@@ -1,20 +1,24 @@
|
|||||||
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.BackendContext
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
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.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeArgument
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.types.defaultType
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
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.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
|
||||||
@@ -41,6 +45,38 @@ class SerializableCompanionIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.patchSerializableClassWithMarkerAnnotation(serializer: ClassDescriptor) {
|
||||||
|
if (serializer.kind != ClassKind.OBJECT) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val annotationMarkerClass = serializer.module.findClassAcrossModuleDependencies(
|
||||||
|
ClassId(
|
||||||
|
SerializationPackages.packageFqName,
|
||||||
|
Name.identifier(SerialEntityNames.ANNOTATION_MARKER_CLASS)
|
||||||
|
)
|
||||||
|
) ?: return
|
||||||
|
val annotationCtor = requireNotNull(annotationMarkerClass.unsubstitutedPrimaryConstructor?.let {
|
||||||
|
compilerContext.externalSymbols.referenceConstructor(it)
|
||||||
|
})
|
||||||
|
|
||||||
|
val annotationType = compilerContext.externalSymbols.referenceClass(annotationMarkerClass).owner.defaultType
|
||||||
|
val irSerializableClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor).owner
|
||||||
|
val annotationCtorCall = IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, annotationType, annotationCtor).apply {
|
||||||
|
val serializerType = serializer.toSimpleType(false)
|
||||||
|
putValueArgument(
|
||||||
|
0,
|
||||||
|
createClassReference(
|
||||||
|
serializerType,
|
||||||
|
startOffset,
|
||||||
|
endOffset
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
irSerializableClass.annotations.add(annotationCtorCall)
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) =
|
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) =
|
||||||
irClass.contributeFunction(methodDescriptor, fromStubs = true) { getter ->
|
irClass.contributeFunction(methodDescriptor, fromStubs = true) { getter ->
|
||||||
val serializer = serializableDescriptor.classSerializer!!
|
val serializer = serializableDescriptor.classSerializer!!
|
||||||
@@ -66,6 +102,7 @@ class SerializableCompanionIrGenerator(
|
|||||||
irInvoke(null, ctor, typeArgs, args, returnTypeHint = getter.returnType)
|
irInvoke(null, ctor, typeArgs, args, returnTypeHint = getter.returnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
patchSerializableClassWithMarkerAnnotation(serializer)
|
||||||
+irReturn(expr)
|
+irReturn(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
@@ -48,6 +48,8 @@ object SerialEntityNames {
|
|||||||
const val DECODER_CLASS = "Decoder"
|
const val DECODER_CLASS = "Decoder"
|
||||||
const val STRUCTURE_DECODER_CLASS = "CompositeDecoder"
|
const val STRUCTURE_DECODER_CLASS = "CompositeDecoder"
|
||||||
|
|
||||||
|
const val ANNOTATION_MARKER_CLASS = "SerializableWith"
|
||||||
|
|
||||||
const val SERIAL_SAVER_CLASS = "SerializationStrategy"
|
const val SERIAL_SAVER_CLASS = "SerializationStrategy"
|
||||||
const val SERIAL_LOADER_CLASS = "DeserializationStrategy"
|
const val SERIAL_LOADER_CLASS = "DeserializationStrategy"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user