Support for @EncodeDefault annotation
This commit is contained in:
+33
-9
@@ -1227,24 +1227,48 @@ interface IrBuilderExtension {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// check for call to .shouldEncodeElementDefault
|
// check for call to .shouldEncodeElementDefault
|
||||||
if (!property.optional) {
|
val encodeDefaults = property.getIrPropertyFrom(serializableIrClass).getEncodeDefaultAnnotationValue()
|
||||||
|
if (!property.optional || encodeDefaults == true) {
|
||||||
// emit call right away
|
// emit call right away
|
||||||
+elementCall
|
+elementCall
|
||||||
} else {
|
} 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!!))
|
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 = if (encodeDefaults == false) {
|
||||||
val condition = irIfThenElse(compilerContext.irBuiltIns.booleanType, partA, irTrue(), partB)
|
// 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)
|
+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(
|
fun IrBlockBodyBuilder.formEncodeDecodePropertyCall(
|
||||||
enclosingGenerator: AbstractSerialGenerator,
|
enclosingGenerator: AbstractSerialGenerator,
|
||||||
encoder: IrExpression,
|
encoder: IrExpression,
|
||||||
|
|||||||
+1
@@ -29,6 +29,7 @@ object SerializationAnnotations {
|
|||||||
internal val requiredAnnotationFqName = FqName("kotlinx.serialization.Required")
|
internal val requiredAnnotationFqName = FqName("kotlinx.serialization.Required")
|
||||||
val serialTransientFqName = FqName("kotlinx.serialization.Transient")
|
val serialTransientFqName = FqName("kotlinx.serialization.Transient")
|
||||||
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
|
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 contextualFqName = FqName("kotlinx.serialization.ContextualSerialization") // this one is deprecated
|
||||||
internal val contextualOnFileFqName = FqName("kotlinx.serialization.UseContextualSerialization")
|
internal val contextualOnFileFqName = FqName("kotlinx.serialization.UseContextualSerialization")
|
||||||
|
|||||||
Reference in New Issue
Block a user