From 1b688182cd8a7b695a27b2a68518d09ce51bcb5c Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Wed, 6 Sep 2017 23:57:45 +0300 Subject: [PATCH] Parcelable: Use specialized write/create methods where available (KT-20057) --- .../parcel/serializers/ParcelSerializer.kt | 22 +++++- .../parcel/codegen/IBinderIInterface.kt | 8 +- .../parcel/codegen/IBinderIInterface.txt | 78 ++++++++++++++++++- .../testData/parcel/codegen/listInsideList.kt | 2 +- .../testData/parcel/codegen/simpleList.txt | 20 +---- 5 files changed, 104 insertions(+), 26 deletions(-) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt index c0263917ac0..d3f6c135452 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt @@ -72,6 +72,12 @@ interface ParcelSerializer { || asmType.descriptor == "[F" || asmType.descriptor == "[L" -> PrimitiveArrayParcelSerializer(asmType) + asmType.descriptor == "[Landroid/os/IBinder;" -> NullCompliantObjectParcelSerializer(asmType, + Method("writeBinderArray"), Method("createBinderArray")) + + asmType.descriptor == "[Ljava/lang/String;" -> NullCompliantObjectParcelSerializer(asmType, + Method("writeStringArray"), Method("createStringArray")) + asmType.sort == Type.ARRAY -> { val elementType = type.builtIns.getArrayElementType(type) val elementSerializer = get(elementType, typeMapper.mapTypeSafe(elementType), context, strict = strict()) @@ -101,8 +107,20 @@ interface ParcelSerializer { || className == TreeSet::class.java.canonicalName -> { val elementType = type.arguments.single().type - val elementSerializer = get( - elementType, typeMapper.mapTypeSafe(elementType), context, forceBoxed = true, strict = strict()) + val elementAsmType = typeMapper.mapTypeSafe(elementType) + + if (className == List::class.java.canonicalName) { + // Don't care if the element type is nullable cause both writeStrongBinder() and writeString() support null values + if (elementAsmType.descriptor == "Landroid/os/IBinder;") { + return NullCompliantObjectParcelSerializer(asmType, + Method("writeBinderList"), Method("createBinderArrayList", "()Ljava/util/ArrayList;")) + } else if (elementAsmType.descriptor == "Ljava/lang/String;") { + return NullCompliantObjectParcelSerializer(asmType, + Method("writeStringList"), Method("createStringArrayList", "()Ljava/util/ArrayList;")) + } + } + + val elementSerializer = get(elementType, elementAsmType, context, forceBoxed = true, strict = strict()) wrapToNullAwareIfNeeded(type, ListSetParcelSerializer(asmType, elementSerializer)) } diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.kt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.kt index 632bfd84dc2..119fdea6bc9 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.kt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.kt @@ -7,4 +7,10 @@ import android.os.IBinder import android.os.IInterface @Parcelize -class User(val binder: IBinder, val intf: IInterface?) : Parcelable \ No newline at end of file +class User( + val binder: IBinder, + val binderArray: Array, + val binderList: List, + val binderArrayList: ArrayList, // should be serialized using our strategy, not using Parcel.writeBinderList() + val intf: IInterface? +) : Parcelable \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt index 1d79236066c..22a2be9f6bb 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt @@ -6,15 +6,45 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato ALOAD (1) LDC (in) INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L1) NEW DUP ALOAD (1) INVOKEVIRTUAL (android/os/Parcel, readStrongBinder, ()Landroid/os/IBinder;) ALOAD (1) + INVOKEVIRTUAL (android/os/Parcel, createBinderArray, ()[Landroid/os/IBinder;) + ALOAD (1) + INVOKEVIRTUAL (android/os/Parcel, createBinderArrayList, ()Ljava/util/ArrayList;) + CHECKCAST + ALOAD (1) + INVOKEVIRTUAL (android/os/Parcel, readInt, ()I) + DUP + NEW + DUP_X1 + SWAP + INVOKESPECIAL (java/util/ArrayList, , (I)V) + LABEL (L2) + SWAP + DUP_X1 + IFEQ (L3) + DUP + ALOAD (1) + INVOKEVIRTUAL (android/os/Parcel, readStrongBinder, ()Landroid/os/IBinder;) + INVOKEVIRTUAL (java/util/ArrayList, add, (Ljava/lang/Object;)Z) + POP + SWAP + LDC (-1) + IADD + SWAP + GOTO (L2) + LABEL (L3) + SWAP + POP + ALOAD (1) INVOKEVIRTUAL (android/os/Parcel, readStrongInterface, ()Landroid/os/IInterface;) - INVOKESPECIAL (User, , (Landroid/os/IBinder;Landroid/os/IInterface;)V) + INVOKESPECIAL (User, , (Landroid/os/IBinder;[Landroid/os/IBinder;Ljava/util/List;Ljava/util/ArrayList;Landroid/os/IInterface;)V) ARETURN - LABEL (L1) + LABEL (L4) } public final User[] newArray(int p0) @@ -25,16 +55,28 @@ public final class User : java/lang/Object, android/os/Parcelable { private final android.os.IBinder binder + private final android.os.IBinder[] binderArray + + private final java.util.ArrayList binderArrayList + + private final java.util.List binderList + private final android.os.IInterface intf static void () - public void (android.os.IBinder p0, android.os.IInterface p1) + public void (android.os.IBinder p0, android.os.IBinder[] p1, java.util.List p2, java.util.ArrayList p3, android.os.IInterface p4) public final int describeContents() public final android.os.IBinder getBinder() + public final android.os.IBinder[] getBinderArray() + + public final java.util.ArrayList getBinderArrayList() + + public final java.util.List getBinderList() + public final android.os.IInterface getIntf() public final void writeToParcel(android.os.Parcel p0, int p1) { @@ -48,9 +90,37 @@ public final class User : java/lang/Object, android/os/Parcelable { INVOKEVIRTUAL (android/os/Parcel, writeStrongBinder, (Landroid/os/IBinder;)V) ALOAD (1) ALOAD (0) + GETFIELD (binderArray, [Landroid/os/IBinder;) + INVOKEVIRTUAL (android/os/Parcel, writeBinderArray, ([Landroid/os/IBinder;)V) + ALOAD (1) + ALOAD (0) + GETFIELD (binderList, Ljava/util/List;) + INVOKEVIRTUAL (android/os/Parcel, writeBinderList, (Ljava/util/List;)V) + ALOAD (1) + ALOAD (0) + GETFIELD (binderArrayList, Ljava/util/ArrayList;) + DUP_X1 + INVOKEINTERFACE (java/util/Collection, size, ()I) + INVOKEVIRTUAL (android/os/Parcel, writeInt, (I)V) + INVOKEINTERFACE (java/util/Collection, iterator, ()Ljava/util/Iterator;) + LABEL (L1) + DUP + INVOKEINTERFACE (java/util/Iterator, hasNext, ()Z) + IFEQ (L2) + DUP + ALOAD (1) + SWAP + INVOKEINTERFACE (java/util/Iterator, next, ()Ljava/lang/Object;) + CHECKCAST + INVOKEVIRTUAL (android/os/Parcel, writeStrongBinder, (Landroid/os/IBinder;)V) + GOTO (L1) + LABEL (L2) + POP + ALOAD (1) + ALOAD (0) GETFIELD (intf, Landroid/os/IInterface;) INVOKEVIRTUAL (android/os/Parcel, writeStrongInterface, (Landroid/os/IInterface;)V) RETURN - LABEL (L1) + LABEL (L3) } } diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/listInsideList.kt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/listInsideList.kt index 22a7384faae..810a885debe 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/listInsideList.kt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/listInsideList.kt @@ -4,4 +4,4 @@ import kotlinx.android.parcel.* @Parcelize -class Test(val names: List>>) \ No newline at end of file +class Test(val names: List>>) \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simpleList.txt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simpleList.txt index f3a8bd5384f..80998b127dc 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simpleList.txt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simpleList.txt @@ -27,24 +27,8 @@ public final class Test : java/lang/Object { ALOAD (1) ALOAD (0) GETFIELD (names, Ljava/util/List;) - DUP_X1 - INVOKEINTERFACE (java/util/Collection, size, ()I) - INVOKEVIRTUAL (android/os/Parcel, writeInt, (I)V) - INVOKEINTERFACE (java/util/Collection, iterator, ()Ljava/util/Iterator;) - LABEL (L1) - DUP - INVOKEINTERFACE (java/util/Iterator, hasNext, ()Z) - IFEQ (L2) - DUP - ALOAD (1) - SWAP - INVOKEINTERFACE (java/util/Iterator, next, ()Ljava/lang/Object;) - CHECKCAST - INVOKEVIRTUAL (android/os/Parcel, writeString, (Ljava/lang/String;)V) - GOTO (L1) - LABEL (L2) - POP + INVOKEVIRTUAL (android/os/Parcel, writeStringList, (Ljava/util/List;)V) RETURN - LABEL (L3) + LABEL (L1) } }