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.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
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.synthetic.isVisibleOutside
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
@@ -199,10 +202,17 @@ interface ParcelSerializer {
|
|||||||
|
|
||||||
type.isParcelable() -> {
|
type.isParcelable() -> {
|
||||||
val clazz = type.constructor.declarationDescriptor as? ClassDescriptor
|
val clazz = type.constructor.declarationDescriptor as? ClassDescriptor
|
||||||
if (clazz != null && clazz.modality == Modality.FINAL) {
|
if (clazz != null && clazz.modality == Modality.FINAL && clazz.source is PsiSourceElement) {
|
||||||
val creatorVar = clazz.staticScope.getContributedVariables(
|
|
||||||
|
fun MemberScope.findCreatorField() = getContributedVariables(
|
||||||
Name.identifier("CREATOR"), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS).firstOrNull()
|
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 {
|
val creatorAsmType = when {
|
||||||
creatorVar != null -> typeMapper.mapTypeSafe(creatorVar.type)
|
creatorVar != null -> typeMapper.mapTypeSafe(creatorVar.type)
|
||||||
clazz.isParcelize -> Type.getObjectType(asmType.internalName + "\$Creator")
|
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);
|
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")
|
@TestMetadata("customSimple.kt")
|
||||||
public void testCustomSimple() throws Exception {
|
public void testCustomSimple() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/customSimple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/customSimple.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user