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()) {
|
||||
writeCreatorAccessField(codegen)
|
||||
writeCreatorAccessField(codegen, parcelableClass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,10 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
||||
val parcelClassType = ParcelableResolveExtension.resolveParcelClassType(parcelableClass.module)
|
||||
?: 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(
|
||||
codegen: ImplementationBodyCodegen,
|
||||
parcelableClass: ClassDescriptor,
|
||||
parcelableCreatorClassType: KotlinType,
|
||||
creatorClass: ClassDescriptorImpl,
|
||||
parcelClassType: KotlinType,
|
||||
parcelAsmType: Type,
|
||||
@@ -211,10 +215,12 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
||||
val containerAsmType = codegen.typeMapper.mapType(parcelableClass)
|
||||
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(
|
||||
creatorClass, CREATE_FROM_PARCEL, Modality.FINAL,
|
||||
parcelableClass.builtIns.anyType, "in" to parcelClassType
|
||||
).write(codegen) {
|
||||
parcelableClass.defaultType, "in" to parcelClassType
|
||||
).write(codegen, overriddenFunction) {
|
||||
if (parcelerObject != null) {
|
||||
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 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",
|
||||
creatorType.descriptor, null, null)
|
||||
creatorType.descriptor, fieldSignature, null)
|
||||
}
|
||||
|
||||
private fun writeCreatorClass(
|
||||
codegen: ImplementationBodyCodegen,
|
||||
parcelableClass: ClassDescriptor,
|
||||
parcelClassType: KotlinType,
|
||||
parcelableCreatorClassType: KotlinType,
|
||||
parcelAsmType: Type,
|
||||
parcelerObject: ClassDescriptor?,
|
||||
properties: List<PropertyToSerialize>
|
||||
@@ -281,7 +290,7 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
||||
val creatorAsmType = Type.getObjectType(containerAsmType.internalName + "\$Creator")
|
||||
|
||||
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)
|
||||
|
||||
creatorClass.initialize(
|
||||
@@ -298,8 +307,9 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
||||
val codegenForCreator = ImplementationBodyCodegen(
|
||||
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,
|
||||
creatorAsmType.internalName, null, "java/lang/Object",
|
||||
creatorAsmType.internalName, classSignature, "java/lang/Object",
|
||||
arrayOf("android/os/Parcelable\$Creator"))
|
||||
|
||||
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)
|
||||
|
||||
writeCreatorConstructor(codegenForCreator, creatorClass, creatorAsmType)
|
||||
writeNewArrayMethod(codegenForCreator, parcelableClass, creatorClass, parcelerObject)
|
||||
writeCreateFromParcel(codegenForCreator, parcelableClass, creatorClass, parcelClassType, parcelAsmType, parcelerObject, properties)
|
||||
writeNewArrayMethod(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelerObject)
|
||||
writeCreateFromParcel(codegenForCreator, parcelableClass, parcelableCreatorClassType, creatorClass, parcelClassType, parcelAsmType, parcelerObject, properties)
|
||||
|
||||
classBuilderForCreator.done()
|
||||
}
|
||||
@@ -328,16 +338,19 @@ open class ParcelableCodegenExtension : ParcelableExtensionBase, ExpressionCodeg
|
||||
private fun writeNewArrayMethod(
|
||||
codegen: ImplementationBodyCodegen,
|
||||
parcelableClass: ClassDescriptor,
|
||||
parcelableCreatorClassType: KotlinType,
|
||||
creatorClass: ClassDescriptorImpl,
|
||||
parcelerObject: ClassDescriptor?
|
||||
) {
|
||||
val builtIns = parcelableClass.builtIns
|
||||
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,
|
||||
builtIns.getArrayType(Variance.INVARIANT, builtIns.anyType),
|
||||
builtIns.getArrayType(Variance.INVARIANT, parcelableClass.defaultType),
|
||||
"size" to builtIns.intType
|
||||
).write(codegen) {
|
||||
).write(codegen, overriddenFunction) {
|
||||
if (parcelerObject != null) {
|
||||
val newArrayMethod = parcelerObject.unsubstitutedMemberScope
|
||||
.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)
|
||||
if (overriddenDescriptor != null) {
|
||||
this.overriddenDescriptors = listOf(overriddenDescriptor)
|
||||
}
|
||||
codegen.functionCodegen.generateMethod(declarationOrigin, this, object : CodegenBased(codegen.state) {
|
||||
override fun doGenerateBody(e: ExpressionCodegen, signature: JvmMethodSignature) = with(e) {
|
||||
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> {
|
||||
|
||||
+5
@@ -44,6 +44,11 @@ open class ParcelableResolveExtension : SyntheticResolveExtension {
|
||||
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(
|
||||
classDescriptor: ClassDescriptor,
|
||||
componentKind: ParcelableSyntheticComponent.ComponentKind,
|
||||
|
||||
Reference in New Issue
Block a user