Parcelize: Add an intrinsic to access Parcelable CREATOR fields

Fixes KT-19853.

The CREATOR field is a static field on a Parcelable class which is not
visible from Kotlin since the necessary metadata would have to be in a
Companion object which may not exist.

This commit adds a [parcelableCreator] function to kotlinx.parcelize,
which is optimized to a direct field access whenever possible.
This commit is contained in:
Steven Schäfer
2021-09-14 13:51:49 +02:00
committed by Alexander Udalov
parent 897c09bf8d
commit fc013c6b9f
76 changed files with 768 additions and 89 deletions
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase.Companion.CREATOR_NAME
interface IrParcelSerializer {
fun AndroidIrBuilder.readParcel(parcel: IrValueDeclaration): IrExpression
@@ -189,13 +188,7 @@ class IrCharSequenceParcelSerializer : IrParcelSerializer {
// Parcel serializer for Parcelables in the same module, which accesses the writeToParcel/createFromParcel methods without reflection.
class IrEfficientParcelableParcelSerializer(private val irClass: IrClass) : IrParcelSerializer {
override fun AndroidIrBuilder.readParcel(parcel: IrValueDeclaration): IrExpression {
val creator: IrExpression = irClass.fields.find { it.name == CREATOR_NAME }?.let { creatorField ->
irGetField(null, creatorField)
} ?: irCall(irClass.creatorGetter!!).apply {
dispatchReceiver = irGetObject(irClass.companionObject()!!.symbol)
}
return parcelableCreatorCreateFromParcel(creator, irGet(parcel))
return parcelableCreatorCreateFromParcel(getParcelableCreator(irClass), irGet(parcel))
}
override fun AndroidIrBuilder.writeParcel(parcel: IrValueDeclaration, flags: IrValueDeclaration, value: IrExpression): IrExpression {
@@ -59,8 +59,29 @@ class ParcelizeIrTransformer(private val context: IrPluginContext, private val a
deferredOperations.forEach { it() }
// Remap broken stubs, which psi2ir generates for the synthetic descriptors coming from the ParcelizeResolveExtension.
// Replace the `parcelableCreator` intrinsic with a direct field access.
moduleFragment.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
// Handle the `parcelableCreator` intrinsic
val callee = expression.symbol.owner
if (
callee.dispatchReceiverParameter == null
&& callee.extensionReceiverParameter == null
&& callee.valueParameters.isEmpty()
&& callee.isInline
&& callee.fqNameWhenAvailable?.asString() == "kotlinx.parcelize.ParcelableCreatorKt.parcelableCreator"
&& callee.typeParameters.singleOrNull()?.let {
it.isReified && it.superTypes.singleOrNull()?.classFqName?.asString() == "android.os.Parcelable"
} == true
) {
expression.getTypeArgument(0)?.getClass()?.let { parcelableClass ->
androidSymbols.createBuilder(expression.symbol).apply {
return getParcelableCreator(parcelableClass)
}
}
}
// Remap calls to `describeContents` and `writeToParcel`
val remappedSymbol = symbolMap[expression.symbol]
?: return super.visitCall(expression)
return IrCallImpl(
@@ -7,17 +7,23 @@ package org.jetbrains.kotlin.parcelize.ir
import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addField
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELER_FQNAME
@@ -103,6 +109,36 @@ fun IrBuilderWithScope.parcelableCreatorCreateFromParcel(creator: IrExpression,
}
}
// Construct an expression to access the parcelable creator field in the given class.
fun AndroidIrBuilder.getParcelableCreator(irClass: IrClass): IrExpression {
// For classes annotated with `Parcelize` in the same module we can
// use the creator field directly, since we add it ourselves.
irClass.fields.find { it.name == CREATOR_NAME }?.let { creatorField ->
return irGetField(null, creatorField)
}
// For parcelable classes which do not use `Parcelize`, the creator field
// will be present as a `JvmField` on the companion object.
irClass.creatorGetter?.let { getter ->
return irCall(getter).apply {
dispatchReceiver = irGetObject(irClass.companionObject()!!.symbol)
}
}
// For classes in different modules, the creator field may not exist,
// since static fields are not present in the Kotlin metadata.
// As a workaround we create a synthetic field here together with a
// field access.
val creatorType = androidSymbols.androidOsParcelableCreator.typeWith(irClass.symbol.starProjectedType)
val creatorField = irClass.factory.createField(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
IrFieldSymbolImpl(), CREATOR_NAME, creatorType, DescriptorVisibilities.PUBLIC,
isFinal = true, isExternal = false, isStatic = true,
).also { it.parent = irClass }
return irGetField(null, creatorField)
}
// Find a named function declaration which overrides the corresponding function in [Parceler].
// This is more reliable than trying to match the functions signature ourselves, since the frontend
// has already done the work.
@@ -53,8 +53,9 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<PrimitiveTypes>(parcel)
val second2 = readFromParcel<PrimitiveTypes>(parcel)
val parcelableCreator = parcelableCreator<PrimitiveTypes>()
val first2 = parcelableCreator.createFromParcel(parcel)
val second2 = parcelableCreator.createFromParcel(parcel)
assert(first == first2)
assert(second == second2)
@@ -36,9 +36,10 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<UnsignedTypes>(parcel)
val second2 = readFromParcel<UnsignedTypes>(parcel)
val third2 = readFromParcel<UnsignedTypes>(parcel)
val parcelableCreator = parcelableCreator<UnsignedTypes>()
val first2 = parcelableCreator.createFromParcel(parcel)
val second2 = parcelableCreator.createFromParcel(parcel)
val third2 = parcelableCreator.createFromParcel(parcel)
assert(first == first2)
assert(second == second2)
@@ -33,7 +33,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
}
@@ -71,7 +71,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
}
@@ -37,5 +37,5 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<ServiceContainer>(parcel)
val test2 = parcelableCreator<ServiceContainer>().createFromParcel(parcel)
}
@@ -36,7 +36,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<BoxedTypes>(parcel)
val first2 = parcelableCreator<BoxedTypes>().createFromParcel(parcel)
assert(first == first2)
}
@@ -19,7 +19,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<User>(parcel)
val test2 = parcelableCreator<User>().createFromParcel(parcel)
assert(compareBundles(test.a, test2.a))
}
@@ -19,7 +19,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test.simple.toString() == test2.simple.toString())
assert(test.spanned.toString() == test2.spanned.toString())
@@ -31,7 +31,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val creator = User::class.java.getDeclaredField("CREATOR").get(null) as Parcelable.Creator<User>
val creator = parcelableCreator<User>()
val result = parcel.createTypedArray(creator)
assert(result.size == 2)
@@ -31,7 +31,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val userParcelable2 = readFromParcel<UserParcelable>(parcel)
val userParcelable2 = parcelableCreator<UserParcelable>().createFromParcel(parcel)
assert(userParcelable.user.name == userParcelable2.user.name)
assert(userParcelable2.user.age == 0)
@@ -36,7 +36,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Ints>(parcel)
val test2 = parcelableCreator<Ints>().createFromParcel(parcel)
assert(test2.a == -test.a)
assert(test2.b == -test.b)
@@ -41,7 +41,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
println(test.toString())
println(test2.toString())
@@ -42,7 +42,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test.a == "Abc" && test.b == "Abc" && test.c == "Abc" && test.d == "Abc")
assert(test2.a == "3" && test2.b == "3" && test2.c == "Abc" && test2.d == "ABC")
@@ -43,7 +43,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
with (test) {
assert(a == "Abc" && b == "Abc" && c == listOf("A", "bc") && d == listOf("A", "bc") && e == listOf("A", "bc"))
@@ -30,7 +30,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val user2 = readFromParcel<User>(parcel)
val user2 = parcelableCreator<User>().createFromParcel(parcel)
assert(user.firstName == user2.firstName)
assert(user.secondName == user2.secondName)
@@ -27,8 +27,8 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val black2 = readFromParcel<Color>(parcel)
val obj2 = readFromParcel<Obj>(parcel)
val black2 = parcelableCreator<Color>().createFromParcel(parcel)
val obj2 = parcelableCreator<Obj>().createFromParcel(parcel)
println(black2)
println(obj2)
+1 -1
View File
@@ -22,6 +22,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test == test2)
}
@@ -21,5 +21,5 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<ExceptionContainer>(parcel)
val test2 = parcelableCreator<ExceptionContainer>().createFromParcel(parcel)
}
@@ -18,7 +18,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test.callback() == 1)
}
@@ -20,7 +20,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Section<Bundle>>(parcel)
val test2 = parcelableCreator<Section<Bundle>>().createFromParcel(parcel)
assert(test.title == test2.title)
assert(test2.faTitle.size() == 0)
@@ -22,6 +22,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val boxLoaded = readFromParcel<Box<Foo>>(parcel)
val boxLoaded = parcelableCreator<Box<Foo>>().createFromParcel(parcel)
assert(box == boxLoaded)
}
@@ -34,6 +34,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val film2 = readFromParcel<Film>(parcel)
val film2 = parcelableCreator<Film>().createFromParcel(parcel)
assert(film == film2)
}
@@ -27,7 +27,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<J>(parcel)
val test2 = parcelableCreator<J>().createFromParcel(parcel)
assert(test.j.j1 == test2.j.j1)
}
@@ -23,7 +23,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<M>(parcel)
val test2 = parcelableCreator<M>().createFromParcel(parcel)
assert(test.m.m1 == test2.m.m1)
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
@file:JvmName("TestKt")
package test
import kotlinx.parcelize.*
import android.os.Parcel
import android.os.Parcelable
@Parcelize
class A(val value: Int) : Parcelable
fun box() = parcelTest { parcel ->
parcel.writeTypedList(listOf(A(0), A(1)))
val bytes = parcel.marshall()
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val creator = parcelableCreator<A>()
val deserialized = mutableListOf<A>()
parcel.readTypedList(deserialized, creator)
assert(deserialized.size == 2)
assert(deserialized[0].value == 0)
assert(deserialized[1].value == 1)
}
@@ -34,7 +34,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
}
@@ -41,7 +41,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first.parcelableEnum == ParcelableEnum.THREE)
assert(first2.parcelableEnum == ParcelableEnum.ONE)
@@ -24,6 +24,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
readFromParcel<User>(parcel)
readFromParcel<User2>(parcel)
parcelableCreator<User>().createFromParcel(parcel)
parcelableCreator<User2>().createFromParcel(parcel)
}
@@ -30,7 +30,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val foo2 = readFromParcel<Foo>(parcel)
val foo2 = parcelableCreator<Foo>().createFromParcel(parcel)
assert(foo2.values.size() == 1)
assert(foo2.values.get(1) != null) // SparseArray.contains was only added in Android R
assert(foo2.values.get(1).size() == 1)
@@ -19,5 +19,5 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
readFromParcel<MyObject>(parcel)
parcelableCreator<MyObject>().createFromParcel(parcel)
}
@@ -21,9 +21,10 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val a2 = readFromParcel<A>(parcel)
val parcelableCreator = parcelableCreator<A>()
val a2 = parcelableCreator.createFromParcel(parcel)
assert(a2.params != null)
assert(Arrays.equals(a1.params!!, a2.params!!))
val b2 = readFromParcel<A>(parcel)
val b2 = parcelableCreator.createFromParcel(parcel)
assert(b1 == b2)
}
@@ -21,9 +21,10 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val a2 = readFromParcel<A>(parcel)
val parcelableCreator = parcelableCreator<A>()
val a2 = parcelableCreator.createFromParcel(parcel)
assert(a2.params != null)
assert(Arrays.equals(a1.params!!, a2.params!!))
val b2 = readFromParcel<A>(parcel)
val b2 = parcelableCreator.createFromParcel(parcel)
assert(b1 == b2)
}
@@ -59,6 +59,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val a2 = readFromParcel<A>(parcel)
val a2 = parcelableCreator<A>().createFromParcel(parcel)
assert(a1.pair == a2.pair)
}
@@ -45,7 +45,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
assert((first.d as LinkedList<*>).size == 1)
@@ -19,7 +19,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
}
+1 -1
View File
@@ -33,7 +33,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
@@ -37,7 +37,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
assert((first.c as HashMap<*, *>).size == 1)
@@ -19,7 +19,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
}
+1 -1
View File
@@ -35,7 +35,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val first2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(first == first2)
}
@@ -20,7 +20,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val second = readFromParcel<Data>(parcel)
val second = parcelableCreator<Data>().createFromParcel(parcel)
assert(second.data.size == 1)
assert(Arrays.equals(second.data[0], arrayOf(0, 1)))
}
@@ -20,7 +20,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val second = readFromParcel<Data>(parcel)
val second = parcelableCreator<Data>().createFromParcel(parcel)
assert(second.data.size == 1)
assert(Arrays.equals(second.data[0], arrayOf(0, 1)))
}
@@ -20,7 +20,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val second = readFromParcel<Data>(parcel)
val second = parcelableCreator<Data>().createFromParcel(parcel)
assert(second.data.size == 1)
val entry = second.data.entries.single()
assert(Arrays.equals(entry.key, arrayOf(0)))
@@ -29,6 +29,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test == test2)
}
@@ -24,7 +24,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val second = readFromParcel<Data>(parcel)
val second = parcelableCreator<Data>().createFromParcel(parcel)
assert(second.data.size() == 1)
assert(Arrays.equals(second.data.get(0), arrayOf(0, 1)))
}
@@ -27,7 +27,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val second = readFromParcel<Data>(parcel)
val second = parcelableCreator<Data>().createFromParcel(parcel)
assert(second.values.size() == 1)
val secondInnerArray = second.values.get(10)
assert(secondInnerArray.size() == 1)
@@ -20,7 +20,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val creator = User::class.java.getDeclaredField("CREATOR").get(null) as Parcelable.Creator<User>
val creator = parcelableCreator<User>()
val result = parcel.createTypedArray(creator)
assert(result.size == 2)
@@ -35,7 +35,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val creator = User::class.java.getDeclaredField("CREATOR").get(null) as Parcelable.Creator<User>
val creator = parcelableCreator<User>()
val result = parcel.createTypedArray(creator)
assert(result.size == 3)
@@ -30,8 +30,9 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val second2 = readFromParcel<Test>(parcel)
val parcelableCreator = parcelableCreator<Test>()
val first2 = parcelableCreator.createFromParcel(parcel)
val second2 = parcelableCreator.createFromParcel(parcel)
assert(first == first2)
assert(second == second2)
@@ -21,8 +21,9 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<Test>(parcel)
val second2 = readFromParcel<Test>(parcel)
val parcelableCreator = parcelableCreator<Test>()
val first2 = parcelableCreator.createFromParcel(parcel)
val second2 = parcelableCreator.createFromParcel(parcel)
assert(first == first2)
assert(second == second2)
@@ -26,6 +26,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test == test2)
}
@@ -34,6 +34,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val data2 = readFromParcel<Data>(parcel)
val data2 = parcelableCreator<Data>().createFromParcel(parcel)
assert(data2.uuid.uuid == data.uuid.uuid)
}
@@ -33,6 +33,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val data2 = readFromParcel<Data>(parcel)
val data2 = parcelableCreator<Data>().createFromParcel(parcel)
assert(data2.uuid.uuid == data.uuid.uuid)
}
@@ -25,7 +25,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<User>(parcel)
val test2 = parcelableCreator<User>().createFromParcel(parcel)
assert(compareBundles(test.a, test2.a))
}
@@ -31,8 +31,9 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val first2 = readFromParcel<PrimitiveTypes>(parcel)
val second2 = readFromParcel<PrimitiveTypes>(parcel)
val parcelableCreator = parcelableCreator<PrimitiveTypes>()
val first2 = parcelableCreator.createFromParcel(parcel)
val second2 = parcelableCreator.createFromParcel(parcel)
assert(first == first2)
assert(second == second2)
@@ -22,6 +22,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val data = readFromParcel<Data>(parcel)
val data = parcelableCreator<Data>().createFromParcel(parcel)
assert(data.value == "OK")
}
@@ -30,6 +30,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<Test>(parcel)
val test2 = parcelableCreator<Test>().createFromParcel(parcel)
assert(test == test2)
}
@@ -27,7 +27,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val second = readFromParcel<Bar>(parcel)
val second = parcelableCreator<Bar>().createFromParcel(parcel)
assert(first == second)
}
@@ -20,6 +20,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val user2 = readFromParcel<User>(parcel)
val user2 = parcelableCreator<User>().createFromParcel(parcel)
assert(user == user2)
}
@@ -20,6 +20,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val user2 = readFromParcel<User>(parcel)
val creator = User::class.java.getDeclaredField("CREATOR").get(null) as Parcelable.Creator<User>
val user2 = creator.createFromParcel(parcel)
assert(user == user2)
}
@@ -27,7 +27,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val user2 = readFromParcel<User>(parcel)
val user2 = parcelableCreator<User>().createFromParcel(parcel)
assert(compareSparseIntArrays(user.a, user2.a))
assert(compareSparseLongArrays(user.b, user2.b))
@@ -19,7 +19,7 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val test2 = readFromParcel<User>(parcel)
val test2 = parcelableCreator<User>().createFromParcel(parcel)
assert(compareSparseBooleanArrays(test.a, test2.a))
}
@@ -29,12 +29,12 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val covariant2 = readFromParcel<Covariant<String>>(parcel)
val covariant2 = parcelableCreator<Covariant<String>>().createFromParcel(parcel)
assert(covariant2.block() == "OK")
val contravariant2 = readFromParcel<Contravariant<String>>(parcel)
val contravariant2 = parcelableCreator<Contravariant<String>>().createFromParcel(parcel)
assert(contravariant2.block("OK"))
val invariant2 = readFromParcel<Invariant<String>>(parcel)
val invariant2 = parcelableCreator<Invariant<String>>().createFromParcel(parcel)
assert(invariant2.s.toString() == "OK")
}
@@ -29,9 +29,9 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val data2 = readFromParcel<Wrapper>(parcel)
val data2 = parcelableCreator<Wrapper>().createFromParcel(parcel)
assert(data2 == data)
val none2 = readFromParcel<NullableWrapper>(parcel)
val none2 = parcelableCreator<NullableWrapper>().createFromParcel(parcel)
assert(none2 == none)
}
@@ -49,6 +49,6 @@ fun box() = parcelTest { parcel ->
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val data2 = readFromParcel<Data>(parcel)
val data2 = parcelableCreator<Data>().createFromParcel(parcel)
assert(data2 == data)
}
@@ -11,8 +11,3 @@ fun parcelTest(block: (Parcel) -> Unit): String {
parcel.recycle()
}
}
inline fun <reified T> readFromParcel(parcel: Parcel): T {
val creator = T::class.java.getDeclaredField("CREATOR").get(null)
return creator::class.java.getDeclaredMethod("createFromParcel", Parcel::class.java).invoke(creator, parcel) as T
}
@@ -0,0 +1,207 @@
public final class A$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final A createFromParcel(android.os.Parcel parcel)
public java.lang.Object createFromParcel(android.os.Parcel source)
public final A[] newArray(int size)
public java.lang.Object[] newArray(int size)
}
public final class A : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
private final int value
static void <clinit>()
public void <init>(int value)
public int describeContents()
public final int getValue()
public void writeToParcel(android.os.Parcel out, int flags)
}
public final class B$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final B createFromParcel(android.os.Parcel parcel)
public java.lang.Object createFromParcel(android.os.Parcel source)
public final B[] newArray(int size)
public java.lang.Object[] newArray(int size)
}
public final class B : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
static void <clinit>()
public void <init>()
public int describeContents()
public void writeToParcel(android.os.Parcel out, int flags)
}
public final class C$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final C createFromParcel(android.os.Parcel parcel)
public java.lang.Object createFromParcel(android.os.Parcel source)
public final C[] newArray(int size)
public java.lang.Object[] newArray(int size)
}
public final class C : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
public final static C INSTANCE
static void <clinit>()
private void <init>()
public int describeContents()
public void writeToParcel(android.os.Parcel out, int flags)
}
public final class ParcelableCreatorKt : java/lang/Object {
public final static void test1() {
GETSTATIC (A, CREATOR, Landroid/os/Parcelable$Creator;)
POP
GETSTATIC (B, CREATOR, Landroid/os/Parcelable$Creator;)
POP
GETSTATIC (C, CREATOR, Landroid/os/Parcelable$Creator;)
POP
LABEL (L0)
LINENUMBER (20)
RETURN
}
public final static void test2() {
ICONST_0
ISTORE (0)
LABEL (L0)
LINENUMBER (23)
ICONST_0
ISTORE (1)
LABEL (L1)
ICONST_4
LDC (T)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, reifiedOperationMarker, (ILjava/lang/String;)V)
LDC (Landroid/os/Parcelable;)
CHECKCAST
LABEL (L2)
LINENUMBER (30)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (2)
ALOAD (2)
INSTANCEOF
IFEQ (L3)
ALOAD (2)
CHECKCAST
GOTO (L4)
LABEL (L3)
ACONST_NULL
LABEL (L4)
ASTORE (3)
ALOAD (3)
IFNONNULL (L5)
LABEL (L6)
LINENUMBER (31)
NEW
DUP
LDC (Could not access CREATOR field in class )
ICONST_4
LDC (T)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, reifiedOperationMarker, (ILjava/lang/String;)V)
LDC (Landroid/os/Parcelable;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L5)
LINENUMBER (30)
ALOAD (3)
CHECKCAST
LABEL (L7)
LINENUMBER (31)
NOP
LABEL (L8)
POP
LABEL (L9)
LINENUMBER (24)
RETURN
LABEL (L10)
}
public final static void test3() {
LABEL (L0)
LINENUMBER (27)
ICONST_0
ISTORE (0)
LABEL (L1)
LINENUMBER (32)
ICONST_0
ISTORE (1)
LABEL (L2)
LDC (LA;)
LABEL (L3)
LINENUMBER (33)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (2)
ALOAD (2)
INSTANCEOF
IFEQ (L4)
ALOAD (2)
CHECKCAST
GOTO (L5)
LABEL (L4)
ACONST_NULL
LABEL (L5)
ASTORE (3)
ALOAD (3)
IFNONNULL (L6)
LABEL (L7)
LINENUMBER (34)
NEW
DUP
LDC (Could not access CREATOR field in class )
LDC (LA;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L6)
LINENUMBER (33)
NOP
LABEL (L8)
LINENUMBER (34)
NOP
LABEL (L9)
LINENUMBER (35)
NOP
LABEL (L10)
LINENUMBER (28)
RETURN
}
}
@@ -0,0 +1,28 @@
// CURIOUS_ABOUT test1, test2, test3
// WITH_RUNTIME
import kotlinx.parcelize.*
import android.os.Parcelable
@Parcelize
class A(val value: Int) : Parcelable
@Parcelize
class B : Parcelable
@Parcelize
object C : Parcelable
fun test1() {
parcelableCreator<A>()
parcelableCreator<B>()
parcelableCreator<C>()
}
inline fun <reified T : Parcelable> test2() {
parcelableCreator<T>()
}
fun test3() {
test2<A>()
}
@@ -0,0 +1,327 @@
public final class A$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final A createFromParcel(android.os.Parcel in)
public java.lang.Object createFromParcel(android.os.Parcel p0)
public final A[] newArray(int size)
public java.lang.Object[] newArray(int p0)
}
public final class A : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
private final int value
static void <clinit>()
public void <init>(int value)
public int describeContents()
public final int getValue()
public void writeToParcel(android.os.Parcel parcel, int flags)
}
public final class B$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final B createFromParcel(android.os.Parcel in)
public java.lang.Object createFromParcel(android.os.Parcel p0)
public final B[] newArray(int size)
public java.lang.Object[] newArray(int p0)
}
public final class B : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
static void <clinit>()
public void <init>()
public int describeContents()
public void writeToParcel(android.os.Parcel parcel, int flags)
}
public final class C$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final C createFromParcel(android.os.Parcel in)
public java.lang.Object createFromParcel(android.os.Parcel p0)
public final C[] newArray(int size)
public java.lang.Object[] newArray(int p0)
}
public final class C : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
public final static C INSTANCE
static void <clinit>()
private void <init>()
public int describeContents()
public void writeToParcel(android.os.Parcel parcel, int flags)
}
public final class ParcelableCreatorKt : java/lang/Object {
public final static void test1() {
LABEL (L0)
LINENUMBER (17)
ICONST_0
ISTORE (0)
LABEL (L1)
LDC (LA;)
LABEL (L2)
LINENUMBER (30)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (1)
ALOAD (1)
INSTANCEOF
IFEQ (L3)
ALOAD (1)
CHECKCAST
GOTO (L4)
LABEL (L3)
ACONST_NULL
LABEL (L4)
ASTORE (2)
ALOAD (2)
IFNONNULL (L5)
LABEL (L6)
LINENUMBER (31)
NEW
DUP
LDC (Could not access CREATOR field in class )
LDC (LA;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L5)
LINENUMBER (30)
NOP
LABEL (L7)
LINENUMBER (31)
NOP
LABEL (L8)
LINENUMBER (18)
ICONST_0
ISTORE (0)
LABEL (L9)
LDC (LB;)
LABEL (L10)
LINENUMBER (32)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (1)
ALOAD (1)
INSTANCEOF
IFEQ (L11)
ALOAD (1)
CHECKCAST
GOTO (L12)
LABEL (L11)
ACONST_NULL
LABEL (L12)
ASTORE (2)
ALOAD (2)
IFNONNULL (L13)
LABEL (L14)
LINENUMBER (33)
NEW
DUP
LDC (Could not access CREATOR field in class )
LDC (LB;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L13)
LINENUMBER (32)
NOP
LABEL (L15)
LINENUMBER (33)
NOP
LABEL (L16)
LINENUMBER (19)
ICONST_0
ISTORE (0)
LABEL (L17)
LDC (LC;)
LABEL (L18)
LINENUMBER (34)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (1)
ALOAD (1)
INSTANCEOF
IFEQ (L19)
ALOAD (1)
CHECKCAST
GOTO (L20)
LABEL (L19)
ACONST_NULL
LABEL (L20)
ASTORE (2)
ALOAD (2)
IFNONNULL (L21)
LABEL (L22)
LINENUMBER (35)
NEW
DUP
LDC (Could not access CREATOR field in class )
LDC (LC;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L21)
LINENUMBER (34)
NOP
LABEL (L23)
LINENUMBER (35)
NOP
LABEL (L24)
LINENUMBER (20)
RETURN
}
public final static void test2() {
LDC (0)
ISTORE (0)
LABEL (L0)
LINENUMBER (23)
ICONST_0
ISTORE (1)
LABEL (L1)
ICONST_4
LDC (T)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, reifiedOperationMarker, (ILjava/lang/String;)V)
LDC (Landroid/os/Parcelable;)
CHECKCAST
LABEL (L2)
LINENUMBER (36)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (2)
ALOAD (2)
INSTANCEOF
IFEQ (L3)
ALOAD (2)
CHECKCAST
GOTO (L4)
LABEL (L3)
ACONST_NULL
LABEL (L4)
ASTORE (3)
ALOAD (3)
IFNONNULL (L5)
LABEL (L6)
LINENUMBER (37)
NEW
DUP
LDC (Could not access CREATOR field in class )
ICONST_4
LDC (T)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, reifiedOperationMarker, (ILjava/lang/String;)V)
LDC (Landroid/os/Parcelable;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L5)
LINENUMBER (36)
ALOAD (3)
CHECKCAST
LABEL (L7)
LINENUMBER (37)
NOP
LABEL (L8)
POP
LABEL (L9)
LINENUMBER (24)
RETURN
LABEL (L10)
}
public final static void test3() {
LABEL (L0)
LINENUMBER (27)
ICONST_0
ISTORE (0)
LABEL (L1)
LINENUMBER (38)
ICONST_0
ISTORE (1)
LABEL (L2)
LDC (LA;)
LABEL (L3)
LINENUMBER (39)
LDC (CREATOR)
INVOKEVIRTUAL (java/lang/Class, getDeclaredField, (Ljava/lang/String;)Ljava/lang/reflect/Field;)
ACONST_NULL
INVOKEVIRTUAL (java/lang/reflect/Field, get, (Ljava/lang/Object;)Ljava/lang/Object;)
ASTORE (2)
ALOAD (2)
INSTANCEOF
IFEQ (L4)
ALOAD (2)
CHECKCAST
GOTO (L5)
LABEL (L4)
ACONST_NULL
LABEL (L5)
ASTORE (3)
ALOAD (3)
IFNONNULL (L6)
LABEL (L7)
LINENUMBER (40)
NEW
DUP
LDC (Could not access CREATOR field in class )
LDC (LA;)
INVOKESTATIC (kotlin/jvm/internal/Reflection, getOrCreateKotlinClass, (Ljava/lang/Class;)Lkotlin/reflect/KClass;)
INVOKEINTERFACE (kotlin/reflect/KClass, getSimpleName, ()Ljava/lang/String;)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, stringPlus, (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;)
INVOKESPECIAL (java/lang/IllegalArgumentException, <init>, (Ljava/lang/String;)V)
ATHROW
LABEL (L6)
LINENUMBER (39)
NOP
LABEL (L8)
LINENUMBER (40)
NOP
LABEL (L9)
LINENUMBER (41)
NOP
LABEL (L10)
LINENUMBER (28)
RETURN
}
}
@@ -165,6 +165,11 @@ public class ParcelizeBoxTestGenerated extends AbstractParcelizeBoxTest {
runTest("plugins/parcelize/parcelize-compiler/testData/box/kt19749.kt");
}
@TestMetadata("kt19853.kt")
public void testKt19853() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/kt19853.kt");
}
@TestMetadata("kt20002.kt")
public void testKt20002() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/kt20002.kt");
@@ -105,6 +105,11 @@ public class ParcelizeBytecodeListingTestGenerated extends AbstractParcelizeByte
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/parcelable.kt");
}
@TestMetadata("parcelableCreator.kt")
public void testParcelableCreator() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/parcelableCreator.kt");
}
@TestMetadata("serializable.kt")
public void testSerializable() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/serializable.kt");
@@ -165,6 +165,11 @@ public class ParcelizeIrBoxTestGenerated extends AbstractParcelizeIrBoxTest {
runTest("plugins/parcelize/parcelize-compiler/testData/box/kt19749.kt");
}
@TestMetadata("kt19853.kt")
public void testKt19853() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/kt19853.kt");
}
@TestMetadata("kt20002.kt")
public void testKt20002() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/kt20002.kt");
@@ -105,6 +105,11 @@ public class ParcelizeIrBytecodeListingTestGenerated extends AbstractParcelizeIr
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/parcelable.kt");
}
@TestMetadata("parcelableCreator.kt")
public void testParcelableCreator() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/parcelableCreator.kt");
}
@TestMetadata("serializable.kt")
public void testSerializable() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/serializable.kt");
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("unused")
package kotlinx.parcelize
import android.os.Parcelable
/**
* Read the CREATOR field of the given [Parcelable] class. Calls to this function with
* a concrete class will be optimized to a direct field access.
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Parcelable> parcelableCreator(): Parcelable.Creator<T> =
T::class.java.getDeclaredField("CREATOR").get(null) as? Parcelable.Creator<T>
?: throw IllegalArgumentException("Could not access CREATOR field in class ${T::class.simpleName}")