Parcelable: Do not check property types if the Parcelable class has a custom Parceler implementation (KT-20062)

This commit is contained in:
Yan Zhulanow
2017-09-02 00:51:03 +03:00
committed by Yan Zhulanow
parent 89c5f78a8e
commit 033386b47d
18 changed files with 56 additions and 11 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.android.parcel
import kotlinx.android.parcel.Parceler
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.*
import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod
import org.jetbrains.kotlin.android.parcel.serializers.PARCEL_TYPE
@@ -55,9 +54,6 @@ import java.io.FileDescriptor
open class ParcelableCodegenExtension : ExpressionCodegenExtension {
private companion object {
private val FILE_DESCRIPTOR_FQNAME = FqName(FileDescriptor::class.java.canonicalName)
private val PARCELER_FQNAME = FqName(Parceler::class.java.canonicalName)
fun KotlinType.isParceler() = constructor.declarationDescriptor?.fqNameSafe == PARCELER_FQNAME
}
protected open fun isExperimental(element: KtElement) = true
@@ -77,7 +73,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
val parcelAsmType = codegen.typeMapper.mapType(parcelClassType)
val parcelerObject = parcelableClass.companionObjectDescriptor?.takeIf {
TypeUtils.getAllSupertypes(it.defaultType).any { it.isParceler() }
TypeUtils.getAllSupertypes(it.defaultType).any { it.isParceler }
}
with (parcelableClass) {
@@ -297,7 +293,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
it.typeParameters.isEmpty()
&& it.kind == CallableMemberDescriptor.Kind.DECLARATION
&& (it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type))
&& !((it.containingDeclaration as? ClassDescriptor)?.defaultType?.isParceler() ?: true)
&& !((it.containingDeclaration as? ClassDescriptor)?.defaultType?.isParceler ?: true)
}
if (newArrayMethod != null) {
@@ -321,7 +317,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
private fun FunctionDescriptor.write(codegen: ImplementationBodyCodegen, code: ExpressionCodegen.() -> Unit) {
codegen.functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, this, object : CodegenBased(codegen.state) {
override fun doGenerateBody(e: ExpressionCodegen, signature: JvmMethodSignature) {
override fun doGenerateBody(e: ExpressionCodegen, signature: JvmMethodSignature) = with(e) {
e.code()
}
})
@@ -202,7 +202,7 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker {
val descriptor = typeMapper.bindingContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter] ?: return
val type = descriptor.type
if (!type.isError) {
if (!type.isError && !containerClass.hasCustomParceler()) {
val asmType = typeMapper.mapType(type)
try {
@@ -216,4 +216,9 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker {
}
}
}
private fun ClassDescriptor.hasCustomParceler(): Boolean {
val companionObjectSuperTypes = companionObjectDescriptor?.let { TypeUtils.getAllSupertypes(it.defaultType) } ?: return false
return companionObjectSuperTypes.any { it.isParceler }
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.android.parcel
import kotlinx.android.parcel.Parceler
import kotlinx.android.parcel.Parcelize
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -136,7 +137,11 @@ interface ParcelableSyntheticComponent {
}
}
private val PARCELIZE_CLASS_FQNAME = FqName(Parcelize::class.java.canonicalName)
val PARCELIZE_CLASS_FQNAME: FqName = FqName(Parcelize::class.java.canonicalName)
internal val PARCELER_FQNAME: FqName = FqName(Parceler::class.java.canonicalName)
internal val ClassDescriptor.isParcelize: Boolean
get() = this.annotations.hasAnnotation(PARCELIZE_CLASS_FQNAME)
val ClassDescriptor.isParcelize: Boolean
get() = this.annotations.hasAnnotation(PARCELIZE_CLASS_FQNAME)
val KotlinType.isParceler
get() = constructor.declarationDescriptor?.fqNameSafe == PARCELER_FQNAME