diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ir/ParcelableIrTransformer.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ir/ParcelableIrTransformer.kt index c2f00c89021..83b753c575c 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ir/ParcelableIrTransformer.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ir/ParcelableIrTransformer.kt @@ -283,7 +283,9 @@ class ParcelableIrTransformer(private val context: IrPluginContext, private val } } - private data class ParcelableProperty(val field: IrField, val parceler: IrParcelSerializer) + private class ParcelableProperty(val field: IrField, parcelerThunk: () -> IrParcelSerializer) { + val parceler by lazy(parcelerThunk) + } private val IrClass.classParceler: IrParcelSerializer get() = if (kind == ClassKind.CLASS) { @@ -302,8 +304,9 @@ class ParcelableIrTransformer(private val context: IrPluginContext, private val return constructor.valueParameters.map { parameter -> val property = properties.first { it.name == parameter.name } val localScope = property.getParcelerScope(toplevelScope) - val parceler = serializerFactory.get(parameter.type, parcelizeType = defaultType, strict = true, scope = localScope) - ParcelableProperty(property.backingField!!, parceler) + ParcelableProperty(property.backingField!!) { + serializerFactory.get(parameter.type, parcelizeType = defaultType, strict = true, scope = localScope) + } } } diff --git a/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelBoxTestGenerated.java b/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelBoxTestGenerated.java index 83b14c3952d..6c42ae238c6 100644 --- a/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelBoxTestGenerated.java +++ b/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelBoxTestGenerated.java @@ -64,6 +64,11 @@ public class ParcelBoxTestGenerated extends AbstractParcelBoxTest { runTest("plugins/android-extensions/android-extensions-compiler/testData/parcel/box/charSequence.kt"); } + @TestMetadata("customParcelable.kt") + public void testCustomParcelable() throws Exception { + runTest("plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelable.kt"); + } + @TestMetadata("customParcelerScoping.kt") public void testCustomParcelerScoping() throws Exception { runTest("plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelerScoping.kt"); diff --git a/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelIrBoxTestGenerated.java b/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelIrBoxTestGenerated.java index 8ef1c49aa51..ea4b741c8cb 100644 --- a/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelIrBoxTestGenerated.java +++ b/plugins/android-extensions/android-extensions-compiler/test/org/jetbrains/kotlin/android/parcel/ParcelIrBoxTestGenerated.java @@ -64,6 +64,11 @@ public class ParcelIrBoxTestGenerated extends AbstractParcelIrBoxTest { runTest("plugins/android-extensions/android-extensions-compiler/testData/parcel/box/charSequence.kt"); } + @TestMetadata("customParcelable.kt") + public void testCustomParcelable() throws Exception { + runTest("plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelable.kt"); + } + @TestMetadata("customParcelerScoping.kt") public void testCustomParcelerScoping() throws Exception { runTest("plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelerScoping.kt"); diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelable.kt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelable.kt new file mode 100644 index 00000000000..86195ce0985 --- /dev/null +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/box/customParcelable.kt @@ -0,0 +1,37 @@ +// IGNORE_BACKEND: JVM +// See KT-38105 +// Throws IllegalAccessError, since the code tries to access the private companion field directly from the generated User$Creator class. +// WITH_RUNTIME + +@file:JvmName("TestKt") +package test + +import kotlinx.android.parcel.* +import android.os.Parcel +import android.os.Parcelable + +data class User(val name: String, val age: Int) + +@Parcelize +data class UserParcelable(val user: User) : Parcelable { + private companion object : Parceler { + override fun UserParcelable.write(parcel: Parcel, flags: Int) { + parcel.writeString(user.name) + } + + override fun create(parcel: Parcel) = UserParcelable(User(parcel.readString(), 0)) + } +} + +fun box() = parcelTest { parcel -> + val userParcelable = UserParcelable(User("John", 20)) + userParcelable.writeToParcel(parcel, 0) + + val bytes = parcel.marshall() + parcel.unmarshall(bytes, 0, bytes.size) + + val userParcelable2 = readFromParcel(parcel) + + assert(userParcelable.user.name == userParcelable2.user.name) + assert(userParcelable2.user.age == 0) +}