Fix Parcelize annotation implementing Parcelable.Creator<T>
This commit is contained in:
+35
-13
@@ -77,7 +77,7 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hasCreatorField()) {
|
if (!hasCreatorField()) {
|
||||||
writeCreatorAccessField(codegen)
|
writeCreatorAccessField(codegen, parcelableClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,10 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
val parcelClassType = ParcelableResolveExtension.resolveParcelClassType(parcelableClass.module)
|
val parcelClassType = ParcelableResolveExtension.resolveParcelClassType(parcelableClass.module)
|
||||||
?: error("Can't resolve 'android.os.Parcel' class")
|
?: error("Can't resolve 'android.os.Parcel' class")
|
||||||
|
|
||||||
writeCreatorClass(codegen, parcelableClass, parcelClassType, PARCEL_TYPE, parcelerObject, propertiesToSerialize)
|
val parcelableCreatorClassType = ParcelableResolveExtension.resolveParcelableCreatorClassType(parcelableClass.module)
|
||||||
|
?: error("Can't resolve 'android.os.Parcelable.Creator' class")
|
||||||
|
|
||||||
|
writeCreatorClass(codegen, parcelableClass, parcelClassType, parcelableCreatorClassType, PARCEL_TYPE, parcelerObject, propertiesToSerialize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +205,7 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
private fun writeCreateFromParcel(
|
private fun writeCreateFromParcel(
|
||||||
codegen: ImplementationBodyCodegen,
|
codegen: ImplementationBodyCodegen,
|
||||||
parcelableClass: ClassDescriptor,
|
parcelableClass: ClassDescriptor,
|
||||||
|
parcelableCreatorClassType: KotlinType,
|
||||||
creatorClass: ClassDescriptorImpl,
|
creatorClass: ClassDescriptorImpl,
|
||||||
parcelClassType: KotlinType,
|
parcelClassType: KotlinType,
|
||||||
parcelAsmType: Type,
|
parcelAsmType: Type,
|
||||||
@@ -211,10 +215,12 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
val containerAsmType = codegen.typeMapper.mapType(parcelableClass)
|
val containerAsmType = codegen.typeMapper.mapType(parcelableClass)
|
||||||
val creatorAsmType = codegen.typeMapper.mapType(creatorClass)
|
val creatorAsmType = codegen.typeMapper.mapType(creatorClass)
|
||||||
|
|
||||||
|
val overriddenFunction = parcelableCreatorClassType.findFunction(CREATE_FROM_PARCEL)
|
||||||
|
?: error("Can't resolve 'android.os.Parcelable.Creator.${CREATE_FROM_PARCEL.methodName}' method")
|
||||||
createMethod(
|
createMethod(
|
||||||
creatorClass, CREATE_FROM_PARCEL, Modality.FINAL,
|
creatorClass, CREATE_FROM_PARCEL, Modality.FINAL,
|
||||||
parcelableClass.builtIns.anyType, "in" to parcelClassType
|
parcelableClass.defaultType, "in" to parcelClassType
|
||||||
).write(codegen) {
|
).write(codegen, overriddenFunction) {
|
||||||
if (parcelerObject != null) {
|
if (parcelerObject != null) {
|
||||||
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
|
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
|
||||||
|
|
||||||
@@ -262,17 +268,20 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeCreatorAccessField(codegen: ImplementationBodyCodegen) {
|
private fun writeCreatorAccessField(codegen: ImplementationBodyCodegen, parcelableClass: ClassDescriptor) {
|
||||||
val creatorType = Type.getObjectType("android/os/Parcelable\$Creator")
|
val creatorType = Type.getObjectType("android/os/Parcelable\$Creator")
|
||||||
|
val parcelableType = codegen.typeMapper.mapType(parcelableClass)
|
||||||
|
val fieldSignature = "L${creatorType.internalName}<${parcelableType.descriptor}>;"
|
||||||
|
|
||||||
codegen.v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_STATIC or ACC_PUBLIC or ACC_FINAL, "CREATOR",
|
codegen.v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_STATIC or ACC_PUBLIC or ACC_FINAL, "CREATOR",
|
||||||
creatorType.descriptor, null, null)
|
creatorType.descriptor, fieldSignature, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeCreatorClass(
|
private fun writeCreatorClass(
|
||||||
codegen: ImplementationBodyCodegen,
|
codegen: ImplementationBodyCodegen,
|
||||||
parcelableClass: ClassDescriptor,
|
parcelableClass: ClassDescriptor,
|
||||||
parcelClassType: KotlinType,
|
parcelClassType: KotlinType,
|
||||||
|
parcelableCreatorClassType: KotlinType,
|
||||||
parcelAsmType: Type,
|
parcelAsmType: Type,
|
||||||
parcelerObject: ClassDescriptor?,
|
parcelerObject: ClassDescriptor?,
|
||||||
properties: List<PropertyToSerialize>
|
properties: List<PropertyToSerialize>
|
||||||
@@ -281,7 +290,7 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
val creatorAsmType = Type.getObjectType(containerAsmType.internalName + "\$Creator")
|
val creatorAsmType = Type.getObjectType(containerAsmType.internalName + "\$Creator")
|
||||||
|
|
||||||
val creatorClass = ClassDescriptorImpl(
|
val creatorClass = ClassDescriptorImpl(
|
||||||
parcelableClass, Name.identifier("Creator"), Modality.FINAL, ClassKind.CLASS, emptyList(),
|
parcelableClass, Name.identifier("Creator"), Modality.FINAL, ClassKind.CLASS, listOf(parcelableCreatorClassType),
|
||||||
parcelableClass.source, false, LockBasedStorageManager.NO_LOCKS)
|
parcelableClass.source, false, LockBasedStorageManager.NO_LOCKS)
|
||||||
|
|
||||||
creatorClass.initialize(
|
creatorClass.initialize(
|
||||||
@@ -298,8 +307,9 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
val codegenForCreator = ImplementationBodyCodegen(
|
val codegenForCreator = ImplementationBodyCodegen(
|
||||||
codegen.myClass, classContextForCreator, classBuilderForCreator, codegen.state, codegen.parentCodegen, false)
|
codegen.myClass, classContextForCreator, classBuilderForCreator, codegen.state, codegen.parentCodegen, false)
|
||||||
|
|
||||||
|
val classSignature = "Ljava/lang/Object;Landroid/os/Parcelable\$Creator<${containerAsmType.descriptor}>;"
|
||||||
classBuilderForCreator.defineClass(null, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
|
classBuilderForCreator.defineClass(null, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
|
||||||
creatorAsmType.internalName, null, "java/lang/Object",
|
creatorAsmType.internalName, classSignature, "java/lang/Object",
|
||||||
arrayOf("android/os/Parcelable\$Creator"))
|
arrayOf("android/os/Parcelable\$Creator"))
|
||||||
|
|
||||||
codegen.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC)
|
codegen.v.visitInnerClass(creatorAsmType.internalName, containerAsmType.internalName, "Creator", ACC_PUBLIC or ACC_STATIC)
|
||||||
@@ -308,8 +318,8 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
writeSyntheticClassMetadata(classBuilderForCreator, codegen.state)
|
writeSyntheticClassMetadata(classBuilderForCreator, codegen.state)
|
||||||
|
|
||||||
writeCreatorConstructor(codegenForCreator, creatorClass, creatorAsmType)
|
writeCreatorConstructor(codegenForCreator, creatorClass, creatorAsmType)
|
||||||
writeNewArrayMethod(codegenForCreator, parcelableClass, creatorClass, parcelerObject)
|
writeNewArrayMethod(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelerObject)
|
||||||
writeCreateFromParcel(codegenForCreator, parcelableClass, creatorClass, parcelClassType, parcelAsmType, parcelerObject, properties)
|
writeCreateFromParcel(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelClassType, parcelAsmType, parcelerObject, properties)
|
||||||
|
|
||||||
classBuilderForCreator.done()
|
classBuilderForCreator.done()
|
||||||
}
|
}
|
||||||
@@ -328,16 +338,19 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
private fun writeNewArrayMethod(
|
private fun writeNewArrayMethod(
|
||||||
codegen: ImplementationBodyCodegen,
|
codegen: ImplementationBodyCodegen,
|
||||||
parcelableClass: ClassDescriptor,
|
parcelableClass: ClassDescriptor,
|
||||||
|
parcelableCreatorClassType: KotlinType,
|
||||||
creatorClass: ClassDescriptorImpl,
|
creatorClass: ClassDescriptorImpl,
|
||||||
parcelerObject: ClassDescriptor?
|
parcelerObject: ClassDescriptor?
|
||||||
) {
|
) {
|
||||||
val builtIns = parcelableClass.builtIns
|
val builtIns = parcelableClass.builtIns
|
||||||
val parcelableAsmType = codegen.typeMapper.mapType(parcelableClass)
|
val parcelableAsmType = codegen.typeMapper.mapType(parcelableClass)
|
||||||
|
|
||||||
|
val overriddenFunction = parcelableCreatorClassType.findFunction(NEW_ARRAY)
|
||||||
|
?: error("Can't resolve 'android.os.Parcelable.Creator.${NEW_ARRAY.methodName}' method")
|
||||||
createMethod(creatorClass, NEW_ARRAY, Modality.FINAL,
|
createMethod(creatorClass, NEW_ARRAY, Modality.FINAL,
|
||||||
builtIns.getArrayType(Variance.INVARIANT, builtIns.anyType),
|
builtIns.getArrayType(Variance.INVARIANT, parcelableClass.defaultType),
|
||||||
"size" to builtIns.intType
|
"size" to builtIns.intType
|
||||||
).write(codegen) {
|
).write(codegen, overriddenFunction) {
|
||||||
if (parcelerObject != null) {
|
if (parcelerObject != null) {
|
||||||
val newArrayMethod = parcelerObject.unsubstitutedMemberScope
|
val newArrayMethod = parcelerObject.unsubstitutedMemberScope
|
||||||
.getContributedFunctions(Name.identifier("newArray"), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
.getContributedFunctions(Name.identifier("newArray"), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
||||||
@@ -367,14 +380,23 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionDescriptor.write(codegen: ImplementationBodyCodegen, code: ExpressionCodegen.() -> Unit) {
|
private fun FunctionDescriptor.write(codegen: ImplementationBodyCodegen, overriddenDescriptor: FunctionDescriptor? = null, code: ExpressionCodegen.() -> Unit) {
|
||||||
val declarationOrigin = JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, null, this)
|
val declarationOrigin = JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, null, this)
|
||||||
|
if (overriddenDescriptor != null) {
|
||||||
|
this.overriddenDescriptors = listOf(overriddenDescriptor)
|
||||||
|
}
|
||||||
codegen.functionCodegen.generateMethod(declarationOrigin, this, object : CodegenBased(codegen.state) {
|
codegen.functionCodegen.generateMethod(declarationOrigin, this, object : CodegenBased(codegen.state) {
|
||||||
override fun doGenerateBody(e: ExpressionCodegen, signature: JvmMethodSignature) = with(e) {
|
override fun doGenerateBody(e: ExpressionCodegen, signature: JvmMethodSignature) = with(e) {
|
||||||
e.code()
|
e.code()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KotlinType.findFunction(componentKind: ParcelableSyntheticComponent.ComponentKind): SimpleFunctionDescriptor? {
|
||||||
|
return memberScope
|
||||||
|
.getContributedFunctions(Name.identifier(componentKind.methodName), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getTypeParcelers(annotations: Annotations): List<TypeParcelerMapping> {
|
internal fun getTypeParcelers(annotations: Annotations): List<TypeParcelerMapping> {
|
||||||
|
|||||||
+5
@@ -44,6 +44,11 @@ open class ParcelableResolveExtension : SyntheticResolveExtension {
|
|||||||
return module.findClassAcrossModuleDependencies(ClassId.topLevel(FqName("android.os.Parcel")))?.defaultType
|
return module.findClassAcrossModuleDependencies(ClassId.topLevel(FqName("android.os.Parcel")))?.defaultType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resolveParcelableCreatorClassType(module: ModuleDescriptor): SimpleType? {
|
||||||
|
val creatorClassId = ClassId(FqName("android.os"), FqName("Parcelable.Creator"), false)
|
||||||
|
return module.findClassAcrossModuleDependencies(creatorClassId)?.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
fun createMethod(
|
fun createMethod(
|
||||||
classDescriptor: ClassDescriptor,
|
classDescriptor: ClassDescriptor,
|
||||||
componentKind: ParcelableSyntheticComponent.ComponentKind,
|
componentKind: ParcelableSyntheticComponent.ComponentKind,
|
||||||
|
|||||||
Reference in New Issue
Block a user