Add SerializerFactory supertype for Native & JS in FIR serialization plugin.
This supertype is intended to be used with @AssociatedObject on platforms where reflection possibilities are limited.
This commit is contained in:
+25
-6
@@ -7,6 +7,8 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
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
|
||||||
@@ -16,14 +18,14 @@ 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.defaultType
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.types.starProjectedType
|
||||||
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.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.SerialEntityNames
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.needSerializerFactory
|
|
||||||
|
|
||||||
class SerializableCompanionIrGenerator(
|
class SerializableCompanionIrGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
@@ -149,14 +151,31 @@ class SerializableCompanionIrGenerator(
|
|||||||
generateSerializerFactoryIfNeeded(methodDescriptor)
|
generateSerializerFactoryIfNeeded(methodDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSerializerFactoryIfNeeded(getterDescriptor: IrSimpleFunction) {
|
private fun getOrCreateSerializerVarargFactory(): IrSimpleFunction {
|
||||||
if (!irClass.needSerializerFactory(compilerContext)) return
|
irClass.findDeclaration<IrSimpleFunction> {
|
||||||
val serialFactoryDescriptor = irClass.findDeclaration<IrSimpleFunction> {
|
|
||||||
it.valueParameters.size == 1
|
it.valueParameters.size == 1
|
||||||
&& it.valueParameters.first().isVararg
|
&& it.valueParameters.first().isVararg
|
||||||
&& it.returnType.isKSerializer()
|
&& it.returnType.isKSerializer()
|
||||||
&& it.isFromPlugin()
|
&& it.isFromPlugin()
|
||||||
} ?: return
|
}?.let { return it }
|
||||||
|
val kSerializerStarType = compilerContext.getClassFromRuntime(SerialEntityNames.KSERIALIZER_CLASS).starProjectedType
|
||||||
|
val f = irClass.addFunction(
|
||||||
|
SerialEntityNames.SERIALIZER_PROVIDER_NAME.asString(),
|
||||||
|
kSerializerStarType,
|
||||||
|
origin = SERIALIZATION_PLUGIN_ORIGIN
|
||||||
|
)
|
||||||
|
f.addValueParameter {
|
||||||
|
name = Name.identifier("typeParamsSerializers")
|
||||||
|
varargElementType = kSerializerStarType
|
||||||
|
type = compilerContext.irBuiltIns.arrayClass.typeWith(kSerializerStarType)
|
||||||
|
origin = SERIALIZATION_PLUGIN_ORIGIN
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateSerializerFactoryIfNeeded(getterDescriptor: IrSimpleFunction) {
|
||||||
|
if (!irClass.needSerializerFactory(compilerContext)) return
|
||||||
|
val serialFactoryDescriptor = getOrCreateSerializerVarargFactory()
|
||||||
addFunctionBody(serialFactoryDescriptor) { factory ->
|
addFunctionBody(serialFactoryDescriptor) { factory ->
|
||||||
val kSerializerStarType = factory.returnType
|
val kSerializerStarType = factory.returnType
|
||||||
val array = factory.valueParameters.first()
|
val array = factory.valueParameters.first()
|
||||||
|
|||||||
+2
@@ -83,6 +83,8 @@ object SerialEntityNames {
|
|||||||
val GENERATED_SERIALIZER_CLASS = Name.identifier("GeneratedSerializer")
|
val GENERATED_SERIALIZER_CLASS = Name.identifier("GeneratedSerializer")
|
||||||
val GENERATED_SERIALIZER_FQ = SerializationPackages.internalPackageFqName.child(GENERATED_SERIALIZER_CLASS)
|
val GENERATED_SERIALIZER_FQ = SerializationPackages.internalPackageFqName.child(GENERATED_SERIALIZER_CLASS)
|
||||||
|
|
||||||
|
val SERIALIZER_FACTORY_INTERFACE_NAME = Name.identifier("SerializerFactory")
|
||||||
|
|
||||||
const val ENCODER_CLASS = "Encoder"
|
const val ENCODER_CLASS = "Encoder"
|
||||||
const val STRUCTURE_ENCODER_CLASS = "CompositeEncoder"
|
const val STRUCTURE_ENCODER_CLASS = "CompositeEncoder"
|
||||||
const val DECODER_CLASS = "Decoder"
|
const val DECODER_CLASS = "Decoder"
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:fir:tree"))
|
compileOnly(project(":compiler:fir:tree"))
|
||||||
compileOnly(project(":compiler:fir:resolve"))
|
compileOnly(project(":compiler:fir:resolve"))
|
||||||
compileOnly(project(":compiler:fir:entrypoint"))
|
compileOnly(project(":compiler:fir:entrypoint"))
|
||||||
|
compileOnly(project(":js:js.config"))
|
||||||
|
compileOnly(project(":compiler:cli-common"))
|
||||||
|
|
||||||
implementation(project(":kotlinx-serialization-compiler-plugin.common"))
|
implementation(project(":kotlinx-serialization-compiler-plugin.common"))
|
||||||
|
|
||||||
|
|||||||
+17
@@ -32,7 +32,10 @@ import org.jetbrains.kotlin.name.CallableId
|
|||||||
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.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
import org.jetbrains.kotlin.platform.js.isJs
|
||||||
|
import org.jetbrains.kotlin.platform.konan.isNative
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_FACTORY_INTERFACE_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||||
|
|
||||||
val generatedSerializerClassId = ClassId(SerializationPackages.internalPackageFqName, SerialEntityNames.GENERATED_SERIALIZER_CLASS)
|
val generatedSerializerClassId = ClassId(SerializationPackages.internalPackageFqName, SerialEntityNames.GENERATED_SERIALIZER_CLASS)
|
||||||
@@ -321,6 +324,10 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
|||||||
name = SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
name = SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
||||||
symbol = FirRegularClassSymbol(classId)
|
symbol = FirRegularClassSymbol(classId)
|
||||||
superTypeRefs += session.builtinTypes.anyType
|
superTypeRefs += session.builtinTypes.anyType
|
||||||
|
if (owner.companionNeedsSerializerFactory()) {
|
||||||
|
val serializerFactoryClassId = ClassId(SerializationPackages.internalPackageFqName, SERIALIZER_FACTORY_INTERFACE_NAME)
|
||||||
|
superTypeRefs += serializerFactoryClassId.constructClassLikeType(emptyArray(), false).toFirResolvedTypeRef()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return regularClass.symbol
|
return regularClass.symbol
|
||||||
}
|
}
|
||||||
@@ -328,4 +335,14 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
|||||||
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
|
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
|
||||||
register(FirSerializationPredicates.annotatedWithSerializable)
|
register(FirSerializationPredicates.annotatedWithSerializable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirClassSymbol<*>.companionNeedsSerializerFactory(): Boolean {
|
||||||
|
if (!(moduleData.platform.isNative() || moduleData.platform.isJs())) return false
|
||||||
|
if (isSerializableObject) return true
|
||||||
|
if (isSerializableEnum) return true
|
||||||
|
if (isAbstractOrSealedSerializableClass) return true
|
||||||
|
if (isSealedSerializableInterface) return true
|
||||||
|
if (typeParameterSymbols.isEmpty()) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -157,6 +157,9 @@ internal val FirClassSymbol<*>.isInternalSerializable: Boolean
|
|||||||
return hasSerializableAnnotationWithoutArgs
|
return hasSerializableAnnotationWithoutArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val FirClassSymbol<*>.isAbstractOrSealedSerializableClass: Boolean
|
||||||
|
get() = isInternalSerializable && (rawStatus.modality == Modality.ABSTRACT || rawStatus.modality == Modality.SEALED)
|
||||||
|
|
||||||
internal val FirClassSymbol<*>.isInternallySerializableEnum: Boolean
|
internal val FirClassSymbol<*>.isInternallySerializableEnum: Boolean
|
||||||
get() = classKind.isEnumClass && hasSerializableAnnotationWithoutArgs
|
get() = classKind.isEnumClass && hasSerializableAnnotationWithoutArgs
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user