Support for @EncodeDefault annotation
This commit is contained in:
+33
-9
@@ -1227,24 +1227,48 @@ interface IrBuilderExtension {
|
||||
)
|
||||
|
||||
// check for call to .shouldEncodeElementDefault
|
||||
if (!property.optional) {
|
||||
val encodeDefaults = property.getIrPropertyFrom(serializableIrClass).getEncodeDefaultAnnotationValue()
|
||||
if (!property.optional || encodeDefaults == true) {
|
||||
// emit call right away
|
||||
+elementCall
|
||||
} else {
|
||||
// emit check:
|
||||
// if (if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) {
|
||||
// output.encodeIntElement(this.descriptor, i, obj.prop)// block {obj.prop != DEFAULT_VALUE} may contain several statements
|
||||
val shouldEncodeFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.shouldEncodeDefault)
|
||||
val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
|
||||
val partB = irNotEquals(property.irGet(), initializerAdapter(property.irField.initializer!!))
|
||||
// Ir infrastructure does not have dedicated symbol for ||, so
|
||||
// `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror
|
||||
val condition = irIfThenElse(compilerContext.irBuiltIns.booleanType, partA, irTrue(), partB)
|
||||
|
||||
val condition = if (encodeDefaults == false) {
|
||||
// drop default without call to .shouldEncodeElementDefault
|
||||
partB
|
||||
} else {
|
||||
// emit check:
|
||||
// if (if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) {
|
||||
// output.encodeIntElement(this.descriptor, i, obj.prop)// block {obj.prop != DEFAULT_VALUE} may contain several statements
|
||||
val shouldEncodeFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.shouldEncodeDefault)
|
||||
val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
|
||||
// Ir infrastructure does not have dedicated symbol for ||, so
|
||||
// `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror
|
||||
irIfThenElse(compilerContext.irBuiltIns.booleanType, partA, irTrue(), partB)
|
||||
}
|
||||
+irIfThen(condition, elementCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True — ALWAYS
|
||||
* False — NEVER
|
||||
* null — not specified
|
||||
*/
|
||||
fun IrProperty.getEncodeDefaultAnnotationValue(): Boolean? {
|
||||
val call = annotations.findAnnotation(SerializationAnnotations.encodeDefaultFqName) ?: return null
|
||||
val arg = call.getValueArgument(0) ?: return true // ALWAYS by default
|
||||
val argValue = (arg as? IrGetEnumValue ?: error("Argument of enum constructor expected to implement IrGetEnumValue, got $arg")).symbol.owner.name.toString()
|
||||
return when (argValue) {
|
||||
"ALWAYS" -> true
|
||||
"NEVER" -> false
|
||||
else -> error("Unknown EncodeDefaultMode enum value: $argValue")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
||||
enclosingGenerator: AbstractSerialGenerator,
|
||||
encoder: IrExpression,
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ object SerializationAnnotations {
|
||||
internal val requiredAnnotationFqName = FqName("kotlinx.serialization.Required")
|
||||
val serialTransientFqName = FqName("kotlinx.serialization.Transient")
|
||||
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
|
||||
internal val encodeDefaultFqName = FqName("kotlinx.serialization.EncodeDefault")
|
||||
|
||||
internal val contextualFqName = FqName("kotlinx.serialization.ContextualSerialization") // this one is deprecated
|
||||
internal val contextualOnFileFqName = FqName("kotlinx.serialization.UseContextualSerialization")
|
||||
|
||||
Reference in New Issue
Block a user