Parcelable: Do not check property types if the Parcelable class has a custom Parceler implementation (KT-20062)
This commit is contained in:
committed by
Yan Zhulanow
parent
89c5f78a8e
commit
033386b47d
+3
-7
@@ -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()
|
||||
}
|
||||
})
|
||||
|
||||
+6
-1
@@ -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 }
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -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
|
||||
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcelable
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT describeContents
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcelable
|
||||
|
||||
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, newArray
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcel
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT newArray
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcel
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT describeContents
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcelable
|
||||
|
||||
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel
|
||||
// WITH_RUNTIME
|
||||
|
||||
import android.util.Size
|
||||
import kotlinx.android.parcel.*
|
||||
|
||||
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
||||
// WITH_RUNTIME
|
||||
|
||||
package test
|
||||
|
||||
|
||||
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcelable
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>, describeContents
|
||||
// WITH_RUNTIME
|
||||
// LOCAL_VARIABLES_TABLE
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
|
||||
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// CURIOUS_ABOUT writeToParcel, createFromParcel
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.Parcelable
|
||||
|
||||
@@ -27,5 +27,6 @@
|
||||
<orderEntry type="module" module-name="backend" />
|
||||
<orderEntry type="module" module-name="android-extensions-runtime" />
|
||||
<orderEntry type="module" module-name="idea-gradle" />
|
||||
<orderEntry type="module" module-name="kapt3-idea" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
package test
|
||||
|
||||
import kotlinx.android.parcel.*
|
||||
import android.os.*
|
||||
|
||||
class Box(val value: String)
|
||||
|
||||
@Parcelize
|
||||
class Foo(val box: Box): Parcelable {
|
||||
companion object : Parceler<Foo> {
|
||||
override fun create(parcel: Parcel) = Foo(Box(parcel.readString()))
|
||||
|
||||
override fun Foo.write(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(box.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class Foo2(val box: <error descr="[PLUGIN_ERROR] PARCELABLE_TYPE_NOT_SUPPORTED: Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'">Box</error>): Parcelable
|
||||
+6
@@ -66,6 +66,12 @@ public class ParcelCheckerTestGenerated extends AbstractParcelCheckerTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20062.kt")
|
||||
public void testKt20062() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/kt20062.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("modality.kt")
|
||||
public void testModality() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/modality.kt");
|
||||
|
||||
Reference in New Issue
Block a user