Support full pipeline for basic kotlinx.serialization case:
FIR frontend and IR backend plugins. Note: IR plugin is now broken for old FE, fixed in subsequent commits
This commit is contained in:
@@ -148,6 +148,7 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
|
||||
error(ERROR_MESSAGE)
|
||||
}
|
||||
|
||||
@Deprecated("Use classId overload instead")
|
||||
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
|
||||
error(ERROR_MESSAGE)
|
||||
}
|
||||
|
||||
+1
@@ -54,6 +54,7 @@ interface IrPluginContext : IrGeneratorContext {
|
||||
@Deprecated("Use classId overload instead")
|
||||
fun referenceClass(fqName: FqName): IrClassSymbol?
|
||||
fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol?
|
||||
@Deprecated("Use classId overload instead")
|
||||
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol>
|
||||
@Deprecated("Use callableId overload instead")
|
||||
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol>
|
||||
|
||||
+2
@@ -121,6 +121,7 @@ open class IrPluginContextImpl constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use classId overload instead")
|
||||
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
|
||||
@Suppress("DEPRECATION")
|
||||
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
|
||||
@@ -157,6 +158,7 @@ open class IrPluginContextImpl constructor(
|
||||
}
|
||||
|
||||
override fun referenceConstructors(classId: ClassId): Collection<IrConstructorSymbol> {
|
||||
@Suppress("DEPRECATION")
|
||||
return referenceConstructors(classId.asSingleFqName())
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -294,6 +294,7 @@ internal fun IrPluginContext.getArrayConstructorSymbol(
|
||||
): IrConstructorSymbol {
|
||||
val jsArrayName = irType.getArrayClassFqName()
|
||||
return try {
|
||||
@Suppress("DEPRECATION") // caution: referenceConstructors(fqName) doesn't work with FIR
|
||||
referenceConstructors(jsArrayName).single(predicate)
|
||||
} catch (e: RuntimeException) {
|
||||
error("Array constructor $jsArrayName matching the predicate was not found in the context")
|
||||
|
||||
+6
-1
@@ -10,6 +10,9 @@ import org.jetbrains.kotlin.codegen.CompilationException
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -323,4 +326,6 @@ internal fun IrConstructor.isSerializationCtor(): Boolean {
|
||||
SerialEntityNames.SERIAL_CTOR_MARKER_NAME
|
||||
)
|
||||
} == true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrExpression.isInitializePropertyFromParameter(): Boolean = this is IrGetValueImpl && this.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
+7
-7
@@ -742,12 +742,12 @@ interface IrBuilderExtension {
|
||||
fun IrBuilderWithScope.classReference(classSymbol: IrType): IrClassReference =
|
||||
createClassReference(classSymbol, startOffset, endOffset)
|
||||
|
||||
private fun extractDefaultValuesFromConstructor(irClass: IrClass?): Map<ParameterDescriptor, IrExpression?> {
|
||||
private fun extractDefaultValuesFromConstructor(irClass: IrClass?): Map<IrValueSymbol, IrExpression?> {
|
||||
if (irClass == null) return emptyMap()
|
||||
val original = irClass.constructors.singleOrNull { it.isPrimary }
|
||||
// default arguments of original constructor
|
||||
val defaultsMap: Map<ParameterDescriptor, IrExpression?> =
|
||||
original?.valueParameters?.associate { it.descriptor to it.defaultValue?.expression } ?: emptyMap()
|
||||
val defaultsMap: Map<IrValueSymbol, IrExpression?> =
|
||||
original?.valueParameters?.associate { it.symbol to it.defaultValue?.expression } ?: emptyMap()
|
||||
return defaultsMap + extractDefaultValuesFromConstructor(irClass.getSuperClassNotAny())
|
||||
}
|
||||
|
||||
@@ -783,9 +783,9 @@ interface IrBuilderExtension {
|
||||
return fun(initializer: IrExpressionBody): IrExpression {
|
||||
val rawExpression = initializer.expression
|
||||
val expression =
|
||||
if (rawExpression is IrGetValueImpl && rawExpression.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) {
|
||||
if (rawExpression.isInitializePropertyFromParameter()) {
|
||||
// this is a primary constructor property, use corresponding default of value parameter
|
||||
defaultsMap.getValue(rawExpression.symbol.descriptor as ParameterDescriptor)!!
|
||||
defaultsMap.getValue((rawExpression as IrGetValue).symbol)!!
|
||||
} else {
|
||||
rawExpression
|
||||
}
|
||||
@@ -1252,8 +1252,8 @@ interface IrBuilderExtension {
|
||||
} == true
|
||||
}
|
||||
|
||||
fun serializableSyntheticConstructor(forClass: IrClass): IrConstructorSymbol {
|
||||
return forClass.declarations.filterIsInstance<IrConstructor>().single { it.isSerializationCtor() }.symbol
|
||||
fun serializableSyntheticConstructor(forClass: IrClass): IrConstructorSymbol? { // todo: remove this W/A when FIR plugin will add proper ctor
|
||||
return forClass.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.isSerializationCtor() }?.symbol
|
||||
}
|
||||
|
||||
fun IrClass.getSuperClassOrAny(): IrClass = getSuperClassNotAny() ?: compilerContext.irBuiltIns.anyClass.owner
|
||||
|
||||
+4
-5
@@ -105,8 +105,7 @@ class SerializableIrGenerator(
|
||||
}
|
||||
|
||||
// Missing field exception parts
|
||||
val exceptionFqn = getSerializationPackageFqn(MISSING_FIELD_EXC)
|
||||
val exceptionCtorRef = compilerContext.referenceConstructors(exceptionFqn)
|
||||
val exceptionCtorRef = compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(MISSING_FIELD_EXC)))
|
||||
.single { it.owner.valueParameters.singleOrNull()?.type?.isString() == true }
|
||||
val exceptionType = exceptionCtorRef.owner.returnType
|
||||
|
||||
@@ -230,8 +229,8 @@ class SerializableIrGenerator(
|
||||
}
|
||||
|
||||
private fun IrBlockBodyBuilder.getInstantiateDescriptorExpr(): IrExpression {
|
||||
val classConstructors = compilerContext.referenceConstructors(serialDescriptorImplClass.kotlinFqName) //todo: remove reference
|
||||
val serialClassDescImplCtor = classConstructors.single { it.owner.isPrimary }
|
||||
val classConstructors = serialDescriptorImplClass.constructors //todo: remove reference
|
||||
val serialClassDescImplCtor = classConstructors.single { it.isPrimary }.symbol
|
||||
return irInvoke(
|
||||
null, serialClassDescImplCtor,
|
||||
irString(irClass.serialName()), irNull(), irInt(properties.serializableProperties.size)
|
||||
@@ -282,7 +281,7 @@ class SerializableIrGenerator(
|
||||
propertiesStart: Int
|
||||
): Int {
|
||||
check(superClass.isInternalSerializable)
|
||||
val superCtorRef = serializableSyntheticConstructor(superClass)
|
||||
val superCtorRef = serializableSyntheticConstructor(superClass)!!
|
||||
val superProperties = bindingContext.serializablePropertiesFor(superClass.descriptor).serializableProperties
|
||||
val superSlots = superProperties.bitMaskSlotCount()
|
||||
val arguments = allValueParameters.subList(0, superSlots) +
|
||||
|
||||
+8
-6
@@ -23,6 +23,8 @@ 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.util.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
@@ -34,6 +36,7 @@ import org.jetbrains.kotlinx.serialization.compiler.fir.SerializationPluginKey
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.LOAD
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SAVE
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_DECODER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_ENCODER_CLASS
|
||||
@@ -458,8 +461,7 @@ open class SerializerIrGenerator(
|
||||
|
||||
// throw exception on unknown field
|
||||
|
||||
val exceptionFqn = getSerializationPackageFqn(UNKNOWN_FIELD_EXC)
|
||||
val excClassRef = compilerContext.referenceConstructors(exceptionFqn)
|
||||
val excClassRef = compilerContext.referenceConstructors(ClassId(SerializationPackages.packageFqName, Name.identifier(UNKNOWN_FIELD_EXC)))
|
||||
.single { it.owner.valueParameters.singleOrNull()?.type?.isInt() == true }
|
||||
+elseBranch(
|
||||
irThrow(
|
||||
@@ -485,11 +487,11 @@ open class SerializerIrGenerator(
|
||||
)
|
||||
|
||||
val typeArgs = (loadFunc.returnType as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
|
||||
if (serializableIrClass.isInternalSerializable) {
|
||||
val deserCtor: IrConstructorSymbol? = serializableSyntheticConstructor(serializableIrClass)
|
||||
if (serializableIrClass.isInternalSerializable && deserCtor != null) {
|
||||
var args: List<IrExpression> = serializableProperties.map { serialPropertiesMap.getValue(it.descriptor).get() }
|
||||
args = bitMasks.map { irGet(it) } + args + irNull()
|
||||
val ctor: IrConstructorSymbol = serializableSyntheticConstructor(serializableIrClass)
|
||||
+irReturn(irInvoke(null, ctor, typeArgs, args))
|
||||
+irReturn(irInvoke(null, deserCtor, typeArgs, args))
|
||||
} else {
|
||||
if (irClass.isLocal) {
|
||||
// if the serializer is local, then the serializable class too, since they must be in the same scope
|
||||
@@ -592,7 +594,7 @@ open class SerializerIrGenerator(
|
||||
if (prop)
|
||||
generateSerialDesc()
|
||||
val save = irClass.findPluginGeneratedMethod(SAVE)?.let { generateSave(it); true } ?: false
|
||||
val load = irClass.findPluginGeneratedMethod(SAVE)?.let { generateSave(it); true } ?: false
|
||||
val load = irClass.findPluginGeneratedMethod(LOAD)?.let { generateLoad(it); true } ?: false
|
||||
irClass.findPluginGeneratedMethod(SerialEntityNames.CHILD_SERIALIZERS_GETTER.identifier)?.let { generateChildSerializersGetter(it) }
|
||||
irClass.findPluginGeneratedMethod(SerialEntityNames.TYPE_PARAMS_SERIALIZERS_GETTER.identifier)?.let { generateTypeParamsSerializersGetter(it) }
|
||||
if (!prop && (save || load))
|
||||
|
||||
+3
-1
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.isInterface
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isInitializePropertyFromParameter
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isInternalSerializable
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isInternallySerializableEnum
|
||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SERIALIZABLE_PROPERTIES
|
||||
@@ -227,9 +228,10 @@ internal fun BindingContext?.serializablePropertiesForIrBackend(
|
||||
it,
|
||||
isConstructorParameterWithDefault,
|
||||
it.backingField != null,
|
||||
it.backingField?.initializer != null || isConstructorParameterWithDefault
|
||||
it.backingField?.initializer.let { init -> init != null && !init.expression.isInitializePropertyFromParameter() } || isConstructorParameterWithDefault
|
||||
)
|
||||
}
|
||||
.filterNot { it.transient }
|
||||
.partition { primaryParamsAsProps.contains(it.descriptor) }
|
||||
|
||||
val serializableProps = run {
|
||||
|
||||
+8
-3
@@ -26,6 +26,8 @@ import org.jetbrains.kotlinx.serialization.compiler.fir.FirSerializationExtensio
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractSerializationFirMembersTest: AbstractKotlinCompilerTest() {
|
||||
private val librariesList = listOf(getSerializationCoreLibraryJar()!!, getSerializationLibraryJar("kotlinx.serialization.json.Json")!!)
|
||||
|
||||
override fun TestConfigurationBuilder.configuration() {
|
||||
baseFirDiagnosticTestConfiguration()
|
||||
|
||||
@@ -34,22 +36,25 @@ abstract class AbstractSerializationFirMembersTest: AbstractKotlinCompilerTest()
|
||||
+FirDiagnosticsDirectives.FIR_DUMP
|
||||
}
|
||||
|
||||
configureForKotlinxSerialization(listOf(getSerializationCoreLibraryJar()!!)) {
|
||||
configureForKotlinxSerialization(librariesList) {
|
||||
FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class AbstractSerializationFirBlackBoxTest : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) {
|
||||
|
||||
private val librariesList = listOf(getSerializationCoreLibraryJar()!!, getSerializationLibraryJar("kotlinx.serialization.json.Json")!!)
|
||||
|
||||
override fun TestConfigurationBuilder.configuration() {
|
||||
baseFirDiagnosticTestConfiguration()
|
||||
configureForKotlinxSerialization(listOf(getSerializationCoreLibraryJar()!!)) {
|
||||
configureForKotlinxSerialization(librariesList) {
|
||||
FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())
|
||||
}
|
||||
useCustomRuntimeClasspathProviders({ ts ->
|
||||
object : RuntimeClasspathProvider(ts) {
|
||||
override fun runtimeClassPaths(module: TestModule): List<File> {
|
||||
return listOf(getSerializationCoreLibraryJar()!!)
|
||||
return librariesList
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
+12
@@ -30,4 +30,16 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
|
||||
public void testClassWithCompanionObject() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/classWithCompanionObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultProperties.kt")
|
||||
public void testDefaultProperties() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/defaultProperties.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProperties.kt")
|
||||
public void testMultipleProperties() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/multipleProperties.kt");
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -29,4 +29,16 @@ public class SerializationFirMembersTestGenerated extends AbstractSerializationF
|
||||
public void testClassWithCompanionObject() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/classWithCompanionObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultProperties.kt")
|
||||
public void testDefaultProperties() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/defaultProperties.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProperties.kt")
|
||||
public void testMultipleProperties() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/multipleProperties.kt");
|
||||
}
|
||||
}
|
||||
|
||||
+28
-1
@@ -1,9 +1,12 @@
|
||||
FILE: classWithCompanionObject.kt
|
||||
@R|kotlinx/serialization/Serializable|() public final class SomeClass : R|kotlin/Any| {
|
||||
public constructor(): R|SomeClass| {
|
||||
public constructor(i: R|kotlin/Int|): R|SomeClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val i: R|kotlin/Int| = R|<local>/i|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<SomeClass>|
|
||||
|
||||
@@ -27,5 +30,29 @@ FILE: classWithCompanionObject.kt
|
||||
|
||||
}
|
||||
public final fun box(): R|kotlin/String| {
|
||||
lval targetString: R|kotlin/String| = String({"i":42})
|
||||
lval serializer: R|kotlinx/serialization/KSerializer<SomeClass>| = Q|SomeClass.Companion|.R|/SomeClass.Companion.serializer|()
|
||||
lval descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor| = R|<local>/serializer|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|
|
||||
when () {
|
||||
!=(R|<local>/descriptor|.R|kotlin/Any.toString|(), String(SomeClass(i: kotlin.Int))) -> {
|
||||
^box <strcat>(String(Incorrect SerialDescriptor.toString(): ), R|<local>/descriptor|)
|
||||
}
|
||||
}
|
||||
|
||||
lval instance: R|SomeClass| = R|/SomeClass.SomeClass|(Int(42))
|
||||
lval string: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|SomeClass|>(R|<local>/serializer|, R|<local>/instance|)
|
||||
when () {
|
||||
!=(R|<local>/string|, R|<local>/targetString|) -> {
|
||||
^box <strcat>(String(Incorrect serialization result: expected ), R|<local>/targetString|, String(, got ), R|<local>/string|)
|
||||
}
|
||||
}
|
||||
|
||||
lval instance2: R|SomeClass| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|SomeClass|>(R|<local>/serializer|, R|<local>/string|)
|
||||
when () {
|
||||
!=(R|<local>/instance2|.R|/SomeClass.i|, R|<local>/instance|.R|/SomeClass.i|) -> {
|
||||
^box <strcat>(String(Incorrect deserialization result: expected ), R|<local>/instance|.R|/SomeClass.i|, String(, got ), R|<local>/instance2|.R|/SomeClass.i|)
|
||||
}
|
||||
}
|
||||
|
||||
^box String(OK)
|
||||
}
|
||||
|
||||
+13
-3
@@ -1,11 +1,21 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
|
||||
@Serializable
|
||||
class SomeClass
|
||||
class SomeClass(val i: Int)
|
||||
|
||||
fun box(): String {
|
||||
// SomeClass.serializer()
|
||||
// SomeClass.Companion.serializer()
|
||||
val targetString = """{"i":42}"""
|
||||
val serializer = SomeClass.Companion.serializer()
|
||||
val descriptor = serializer.descriptor
|
||||
if (descriptor.toString() != "SomeClass(i: kotlin.Int)") return "Incorrect SerialDescriptor.toString(): $descriptor"
|
||||
val instance = SomeClass(42)
|
||||
val string = Json.encodeToString(serializer, instance)
|
||||
if (string != targetString) return "Incorrect serialization result: expected $targetString, got $string"
|
||||
val instance2 = Json.decodeFromString(serializer, string)
|
||||
if (instance2.i != instance.i) return "Incorrect deserialization result: expected ${instance.i}, got ${instance2.i}"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
FILE: defaultProperties.kt
|
||||
@R|kotlinx/serialization/Serializable|() public final data class SomeClass : R|kotlin/Any| {
|
||||
public constructor(ctor: R|kotlin/Int| = Int(42), ctorDependent: R|kotlin/Int| = R|<local>/ctor|.R|kotlin/Int.plus|(Int(1))): R|SomeClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val ctor: R|kotlin/Int| = R|<local>/ctor|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val ctorDependent: R|kotlin/Int| = R|<local>/ctorDependent|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final var body: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
public final var bodyDependent: R|kotlin/Int| = this@R|/SomeClass|.R|/SomeClass.ctor|.R|kotlin/Int.plus|(Int(2))
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final operator fun component1(): R|kotlin/Int|
|
||||
|
||||
public final operator fun component2(): R|kotlin/Int|
|
||||
|
||||
public final fun copy(ctor: R|kotlin/Int| = this@R|/SomeClass|.R|/SomeClass.ctor|, ctorDependent: R|kotlin/Int| = this@R|/SomeClass|.R|/SomeClass.ctorDependent|): R|SomeClass|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<SomeClass>|
|
||||
|
||||
public constructor(): R|SomeClass.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<SomeClass>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|SomeClass|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|SomeClass|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
public constructor(): R|SomeClass.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test(targetString: R|kotlin/String|): R|kotlin/String| {
|
||||
lval json: R|kotlinx/serialization/json/Json| = R|kotlinx/serialization/json/Json|(<L> = Json@fun R|kotlinx/serialization/json/JsonBuilder|.<anonymous>(): R|kotlin/Unit| <inline=NoInline> {
|
||||
this@R|special/anonymous|.R|kotlinx/serialization/json/JsonBuilder.encodeDefaults| = Boolean(true)
|
||||
}
|
||||
)
|
||||
lval c: R|SomeClass| = R|/SomeClass.SomeClass|(Int(1)).R|kotlin/apply|<R|SomeClass|>(<L> = apply@fun R|SomeClass|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|/SomeClass.body| = String(x)
|
||||
}
|
||||
)
|
||||
lval s: R|kotlin/String| = R|<local>/json|.R|kotlinx/serialization/json/Json.encodeToString|<R|SomeClass|>(Q|SomeClass|.R|/SomeClass.Companion.serializer|(), R|<local>/c|)
|
||||
when () {
|
||||
!=(R|<local>/s|, R|<local>/targetString|) -> {
|
||||
^test R|<local>/s|
|
||||
}
|
||||
}
|
||||
|
||||
lval i2: R|SomeClass| = R|<local>/json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|SomeClass|>(Q|SomeClass|.R|/SomeClass.Companion.serializer|(), String({}))
|
||||
when () {
|
||||
!=(R|<local>/i2|.R|/SomeClass.ctor|, Int(42)) -> {
|
||||
^test String(Incorrect default ctor)
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
!=(R|<local>/i2|.R|/SomeClass.ctorDependent|, Int(43)) -> {
|
||||
^test String(Incorrect default ctorDependent)
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
!=(R|<local>/i2|.R|/SomeClass.body|, String()) -> {
|
||||
^test String(Incorrect default body)
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
!=(R|<local>/i2|.R|/SomeClass.bodyDependent|, Int(44)) -> {
|
||||
^test String(Incorrect default bodyDependent)
|
||||
}
|
||||
}
|
||||
|
||||
^test String(OK)
|
||||
}
|
||||
public final fun box(): R|kotlin/String| {
|
||||
^box R|/test|(String({"ctor":1,"ctorDependent":2,"body":"x","bodyDependent":3}))
|
||||
}
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
|
||||
@Serializable
|
||||
data class SomeClass(val ctor: Int = 42, val ctorDependent: Int = ctor + 1) {
|
||||
var body: String = ""
|
||||
|
||||
var bodyDependent = ctor + 2
|
||||
}
|
||||
|
||||
fun test(targetString: String): String {
|
||||
val json = Json { encodeDefaults = true }
|
||||
val c = SomeClass(1).apply { body = "x" }
|
||||
val s = json.encodeToString(SomeClass.serializer(), c)
|
||||
if (s != targetString) return s
|
||||
val i2 = json.decodeFromString(SomeClass.serializer(), "{}")
|
||||
if (i2.ctor != 42) return "Incorrect default ctor"
|
||||
if (i2.ctorDependent != 43) return "Incorrect default ctorDependent"
|
||||
if (i2.body != "") return "Incorrect default body"
|
||||
if (i2.bodyDependent != 44) return "Incorrect default bodyDependent"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return test("""{"ctor":1,"ctorDependent":2,"body":"x","bodyDependent":3}""")
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
FILE: multipleProperties.kt
|
||||
@R|kotlinx/serialization/Serializable|() public final class SomeClass : R|kotlin/Any| {
|
||||
public constructor(ctor: R|kotlin/Int|): R|SomeClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val ctor: R|kotlin/Int| = R|<local>/ctor|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final var body: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
public final val getter: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int| {
|
||||
^ Int(42)
|
||||
}
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<SomeClass>|
|
||||
|
||||
public constructor(): R|SomeClass.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<SomeClass>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|SomeClass|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|SomeClass|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
public constructor(): R|SomeClass.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test(targetString: R|kotlin/String|): R|kotlin/String| {
|
||||
lval c: R|SomeClass| = R|/SomeClass.SomeClass|(Int(1)).R|kotlin/apply|<R|SomeClass|>(<L> = apply@fun R|SomeClass|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|/SomeClass.body| = String(x)
|
||||
}
|
||||
)
|
||||
lval s: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|SomeClass|>(Q|SomeClass|.R|/SomeClass.Companion.serializer|(), R|<local>/c|)
|
||||
when () {
|
||||
!=(R|<local>/s|, R|<local>/targetString|) -> {
|
||||
^test R|<local>/s|
|
||||
}
|
||||
}
|
||||
|
||||
lval i: R|SomeClass| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|SomeClass|>(Q|SomeClass|.R|/SomeClass.Companion.serializer|(), R|<local>/s|)
|
||||
when () {
|
||||
!=(R|<local>/i|.R|/SomeClass.ctor|, R|<local>/c|.R|/SomeClass.ctor|) -> {
|
||||
^test String(Incorrect ctor)
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
!=(R|<local>/i|.R|/SomeClass.body|, R|<local>/c|.R|/SomeClass.body|) -> {
|
||||
^test String(Incorrect body)
|
||||
}
|
||||
}
|
||||
|
||||
^test String(OK)
|
||||
}
|
||||
public final fun box(): R|kotlin/String| {
|
||||
^box R|/test|(String({"ctor":1,"body":"x"}))
|
||||
}
|
||||
plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/multipleProperties.kt
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
|
||||
@Serializable
|
||||
class SomeClass(val ctor: Int) {
|
||||
var body: String = ""
|
||||
|
||||
// Not serializable: no backing field
|
||||
val getter: Int get() = 42
|
||||
}
|
||||
|
||||
fun test(targetString: String): String {
|
||||
val c = SomeClass(1).apply { body = "x" }
|
||||
val s = Json.encodeToString(SomeClass.serializer(), c)
|
||||
if (s != targetString) return s
|
||||
val i = Json.decodeFromString(SomeClass.serializer(), s)
|
||||
if (i.ctor != c.ctor) return "Incorrect ctor"
|
||||
if (i.body != c.body) return "Incorrect body"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return test("""{"ctor":1,"body":"x"}""")
|
||||
}
|
||||
Reference in New Issue
Block a user