Parcelable: Use efficient serialize strategy for Java/Kotlin Parcelables only from the current source roots (KT-20029)
This commit is contained in:
committed by
Yan Zhulanow
parent
1b688182cd
commit
eefb490a8a
+12
-2
@@ -22,10 +22,13 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.synthetic.isVisibleOutside
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -199,10 +202,17 @@ interface ParcelSerializer {
|
||||
|
||||
type.isParcelable() -> {
|
||||
val clazz = type.constructor.declarationDescriptor as? ClassDescriptor
|
||||
if (clazz != null && clazz.modality == Modality.FINAL) {
|
||||
val creatorVar = clazz.staticScope.getContributedVariables(
|
||||
if (clazz != null && clazz.modality == Modality.FINAL && clazz.source is PsiSourceElement) {
|
||||
|
||||
fun MemberScope.findCreatorField() = getContributedVariables(
|
||||
Name.identifier("CREATOR"), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS).firstOrNull()
|
||||
|
||||
val creatorVar = when (clazz) {
|
||||
is JavaClassDescriptor -> clazz.staticScope.findCreatorField()
|
||||
else -> clazz.companionObjectDescriptor?.unsubstitutedMemberScope?.findCreatorField()
|
||||
?.takeIf { it.annotations.hasAnnotation(FqName(JvmField::class.java.name)) }
|
||||
}
|
||||
|
||||
val creatorAsmType = when {
|
||||
creatorVar != null -> typeMapper.mapTypeSafe(creatorVar.type)
|
||||
clazz.isParcelize -> Type.getObjectType(asmType.internalName + "\$Creator")
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
||||
// WITH_RUNTIME
|
||||
|
||||
package test
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.*
|
||||
import android.accounts.Account
|
||||
|
||||
@Parcelize
|
||||
class Foo(val kp: Account): Parcelable
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
public final class test/Foo$Creator : java/lang/Object, android/os/Parcelable$Creator {
|
||||
public void <init>()
|
||||
|
||||
public final java.lang.Object createFromParcel(android.os.Parcel p0) {
|
||||
LABEL (L0)
|
||||
ALOAD (1)
|
||||
LDC (in)
|
||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V)
|
||||
NEW
|
||||
DUP
|
||||
ALOAD (1)
|
||||
LDC (Ltest/Foo;)
|
||||
INVOKEVIRTUAL (java/lang/Class, getClassLoader, ()Ljava/lang/ClassLoader;)
|
||||
INVOKEVIRTUAL (android/os/Parcel, readParcelable, (Ljava/lang/ClassLoader;)Landroid/os/Parcelable;)
|
||||
CHECKCAST
|
||||
INVOKESPECIAL (test/Foo, <init>, (Landroid/accounts/Account;)V)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public final test.Foo[] newArray(int p0)
|
||||
}
|
||||
|
||||
public final class test/Foo : java/lang/Object, android/os/Parcelable {
|
||||
public final static test.Foo$Creator CREATOR
|
||||
|
||||
private final android.accounts.Account kp
|
||||
|
||||
static void <clinit>() {
|
||||
NEW
|
||||
DUP
|
||||
INVOKESPECIAL (test/Foo$Creator, <init>, ()V)
|
||||
PUTSTATIC (CREATOR, Ltest/Foo$Creator;)
|
||||
RETURN
|
||||
}
|
||||
|
||||
public void <init>(android.accounts.Account p0)
|
||||
|
||||
public final int describeContents()
|
||||
|
||||
public final android.accounts.Account getKp()
|
||||
|
||||
public final void writeToParcel(android.os.Parcel p0, int p1) {
|
||||
LABEL (L0)
|
||||
ALOAD (1)
|
||||
LDC (parcel)
|
||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V)
|
||||
ALOAD (1)
|
||||
ALOAD (0)
|
||||
GETFIELD (kp, Landroid/accounts/Account;)
|
||||
ILOAD (2)
|
||||
INVOKEVIRTUAL (android/os/Parcel, writeParcelable, (Landroid/os/Parcelable;I)V)
|
||||
RETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
||||
// WITH_RUNTIME
|
||||
|
||||
// FILE: KotlinParcelable.kt
|
||||
package k
|
||||
import android.os.*
|
||||
|
||||
data class KotlinParcelable(var data: Int): Parcelable {
|
||||
|
||||
override fun describeContents() = 1
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
dest.writeInt(data)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CREATOR = Creator()
|
||||
}
|
||||
|
||||
class Creator : Parcelable.Creator<KotlinParcelable> {
|
||||
override fun createFromParcel(source: Parcel): KotlinParcelable {
|
||||
val data = source.readInt()
|
||||
return KotlinParcelable(data)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int) = arrayOfNulls<KotlinParcelable>(size)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: test.kt
|
||||
package test
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.*
|
||||
import k.*
|
||||
|
||||
@Parcelize
|
||||
class Foo(val kp: KotlinParcelable): Parcelable
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
public final class k/KotlinParcelable$Companion : java/lang/Object {
|
||||
private void <init>()
|
||||
|
||||
public void <init>(kotlin.jvm.internal.DefaultConstructorMarker p0)
|
||||
}
|
||||
|
||||
public final class k/KotlinParcelable$Creator : java/lang/Object, android/os/Parcelable$Creator {
|
||||
public void <init>()
|
||||
|
||||
public k.KotlinParcelable createFromParcel(android.os.Parcel p0) {
|
||||
LABEL (L0)
|
||||
ALOAD (1)
|
||||
LDC (source)
|
||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V)
|
||||
LABEL (L1)
|
||||
LINENUMBER (23)
|
||||
ALOAD (1)
|
||||
INVOKEVIRTUAL (android/os/Parcel, readInt, ()I)
|
||||
ISTORE (2)
|
||||
LABEL (L2)
|
||||
LINENUMBER (24)
|
||||
NEW
|
||||
DUP
|
||||
ILOAD (2)
|
||||
INVOKESPECIAL (k/KotlinParcelable, <init>, (I)V)
|
||||
ARETURN
|
||||
LABEL (L3)
|
||||
}
|
||||
|
||||
public java.lang.Object createFromParcel(android.os.Parcel p0) {
|
||||
LABEL (L0)
|
||||
LINENUMBER (21)
|
||||
ALOAD (0)
|
||||
ALOAD (1)
|
||||
INVOKEVIRTUAL (k/KotlinParcelable$Creator, createFromParcel, (Landroid/os/Parcel;)Lk/KotlinParcelable;)
|
||||
ARETURN
|
||||
}
|
||||
|
||||
public k.KotlinParcelable[] newArray(int p0)
|
||||
|
||||
public java.lang.Object[] newArray(int p0)
|
||||
}
|
||||
|
||||
public final class k/KotlinParcelable : java/lang/Object, android/os/Parcelable {
|
||||
public final static k.KotlinParcelable$Creator CREATOR
|
||||
|
||||
public final static k.KotlinParcelable$Companion Companion
|
||||
|
||||
private int data
|
||||
|
||||
static void <clinit>() {
|
||||
NEW
|
||||
DUP
|
||||
ACONST_NULL
|
||||
INVOKESPECIAL (k/KotlinParcelable$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
|
||||
PUTSTATIC (Companion, Lk/KotlinParcelable$Companion;)
|
||||
LABEL (L0)
|
||||
LINENUMBER (18)
|
||||
NEW
|
||||
DUP
|
||||
INVOKESPECIAL (k/KotlinParcelable$Creator, <init>, ()V)
|
||||
PUTSTATIC (CREATOR, Lk/KotlinParcelable$Creator;)
|
||||
RETURN
|
||||
}
|
||||
|
||||
public void <init>(int p0)
|
||||
|
||||
public final int component1()
|
||||
|
||||
public final k.KotlinParcelable copy(int p0)
|
||||
|
||||
public static k.KotlinParcelable copy$default(k.KotlinParcelable p0, int p1, int p2, java.lang.Object p3)
|
||||
|
||||
public int describeContents()
|
||||
|
||||
public boolean equals(java.lang.Object p0)
|
||||
|
||||
public final int getData()
|
||||
|
||||
public int hashCode()
|
||||
|
||||
public final void setData(int p0)
|
||||
|
||||
public java.lang.String toString()
|
||||
|
||||
public void writeToParcel(android.os.Parcel p0, int p1) {
|
||||
LABEL (L0)
|
||||
ALOAD (1)
|
||||
LDC (dest)
|
||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V)
|
||||
LABEL (L1)
|
||||
LINENUMBER (13)
|
||||
ALOAD (1)
|
||||
ALOAD (0)
|
||||
GETFIELD (data, I)
|
||||
INVOKEVIRTUAL (android/os/Parcel, writeInt, (I)V)
|
||||
LABEL (L2)
|
||||
LINENUMBER (14)
|
||||
RETURN
|
||||
LABEL (L3)
|
||||
}
|
||||
}
|
||||
|
||||
public final class test/Foo$Creator : java/lang/Object, android/os/Parcelable$Creator {
|
||||
public void <init>()
|
||||
|
||||
public final java.lang.Object createFromParcel(android.os.Parcel p0) {
|
||||
LABEL (L0)
|
||||
ALOAD (1)
|
||||
LDC (in)
|
||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V)
|
||||
NEW
|
||||
DUP
|
||||
ALOAD (1)
|
||||
GETSTATIC (CREATOR, Lk/KotlinParcelable$Creator;)
|
||||
SWAP
|
||||
INVOKEINTERFACE (android/os/Parcelable$Creator, createFromParcel, (Landroid/os/Parcel;)Ljava/lang/Object;)
|
||||
CHECKCAST
|
||||
INVOKESPECIAL (test/Foo, <init>, (Lk/KotlinParcelable;)V)
|
||||
ARETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
|
||||
public final test.Foo[] newArray(int p0)
|
||||
}
|
||||
|
||||
public final class test/Foo : java/lang/Object, android/os/Parcelable {
|
||||
public final static test.Foo$Creator CREATOR
|
||||
|
||||
private final k.KotlinParcelable kp
|
||||
|
||||
static void <clinit>() {
|
||||
NEW
|
||||
DUP
|
||||
INVOKESPECIAL (test/Foo$Creator, <init>, ()V)
|
||||
PUTSTATIC (CREATOR, Ltest/Foo$Creator;)
|
||||
RETURN
|
||||
}
|
||||
|
||||
public void <init>(k.KotlinParcelable p0)
|
||||
|
||||
public final int describeContents()
|
||||
|
||||
public final k.KotlinParcelable getKp()
|
||||
|
||||
public final void writeToParcel(android.os.Parcel p0, int p1) {
|
||||
LABEL (L0)
|
||||
ALOAD (1)
|
||||
LDC (parcel)
|
||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkParameterIsNotNull, (Ljava/lang/Object;Ljava/lang/String;)V)
|
||||
ALOAD (1)
|
||||
ALOAD (0)
|
||||
GETFIELD (kp, Lk/KotlinParcelable;)
|
||||
SWAP
|
||||
LDC (0)
|
||||
INVOKEINTERFACE (android/os/Parcelable, writeToParcel, (Landroid/os/Parcel;I)V)
|
||||
RETURN
|
||||
LABEL (L1)
|
||||
}
|
||||
}
|
||||
+12
@@ -42,6 +42,18 @@ public class ParcelBytecodeListingTestGenerated extends AbstractParcelBytecodeLi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("customParcelablesDifferentModule.kt")
|
||||
public void testCustomParcelablesDifferentModule() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/customParcelablesDifferentModule.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("customParcelablesSameModule.kt")
|
||||
public void testCustomParcelablesSameModule() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/customParcelablesSameModule.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("customSimple.kt")
|
||||
public void testCustomSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/customSimple.kt");
|
||||
|
||||
Reference in New Issue
Block a user