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
@@ -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
}
}