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
|
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.ParcelableSyntheticComponent.ComponentKind.*
|
||||||
import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod
|
import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod
|
||||||
import org.jetbrains.kotlin.android.parcel.serializers.PARCEL_TYPE
|
import org.jetbrains.kotlin.android.parcel.serializers.PARCEL_TYPE
|
||||||
@@ -55,9 +54,6 @@ import java.io.FileDescriptor
|
|||||||
open class ParcelableCodegenExtension : ExpressionCodegenExtension {
|
open class ParcelableCodegenExtension : ExpressionCodegenExtension {
|
||||||
private companion object {
|
private companion object {
|
||||||
private val FILE_DESCRIPTOR_FQNAME = FqName(FileDescriptor::class.java.canonicalName)
|
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
|
protected open fun isExperimental(element: KtElement) = true
|
||||||
@@ -77,7 +73,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
|
|||||||
val parcelAsmType = codegen.typeMapper.mapType(parcelClassType)
|
val parcelAsmType = codegen.typeMapper.mapType(parcelClassType)
|
||||||
|
|
||||||
val parcelerObject = parcelableClass.companionObjectDescriptor?.takeIf {
|
val parcelerObject = parcelableClass.companionObjectDescriptor?.takeIf {
|
||||||
TypeUtils.getAllSupertypes(it.defaultType).any { it.isParceler() }
|
TypeUtils.getAllSupertypes(it.defaultType).any { it.isParceler }
|
||||||
}
|
}
|
||||||
|
|
||||||
with (parcelableClass) {
|
with (parcelableClass) {
|
||||||
@@ -297,7 +293,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
|
|||||||
it.typeParameters.isEmpty()
|
it.typeParameters.isEmpty()
|
||||||
&& it.kind == CallableMemberDescriptor.Kind.DECLARATION
|
&& it.kind == CallableMemberDescriptor.Kind.DECLARATION
|
||||||
&& (it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type))
|
&& (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) {
|
if (newArrayMethod != null) {
|
||||||
@@ -321,7 +317,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
|
|||||||
|
|
||||||
private fun FunctionDescriptor.write(codegen: ImplementationBodyCodegen, code: ExpressionCodegen.() -> Unit) {
|
private fun FunctionDescriptor.write(codegen: ImplementationBodyCodegen, code: ExpressionCodegen.() -> Unit) {
|
||||||
codegen.functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, this, object : CodegenBased(codegen.state) {
|
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()
|
e.code()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+6
-1
@@ -202,7 +202,7 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker {
|
|||||||
val descriptor = typeMapper.bindingContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter] ?: return
|
val descriptor = typeMapper.bindingContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter] ?: return
|
||||||
val type = descriptor.type
|
val type = descriptor.type
|
||||||
|
|
||||||
if (!type.isError) {
|
if (!type.isError && !containerClass.hasCustomParceler()) {
|
||||||
val asmType = typeMapper.mapType(type)
|
val asmType = typeMapper.mapType(type)
|
||||||
|
|
||||||
try {
|
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
|
package org.jetbrains.kotlin.android.parcel
|
||||||
|
|
||||||
|
import kotlinx.android.parcel.Parceler
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.*
|
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
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
|
val ClassDescriptor.isParcelize: Boolean
|
||||||
get() = this.annotations.hasAnnotation(PARCELIZE_CLASS_FQNAME)
|
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
|
// CURIOUS_ABOUT writeToParcel, createFromParcel
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT describeContents
|
// CURIOUS_ABOUT describeContents
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
|||||||
Vendored
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, newArray
|
// CURIOUS_ABOUT writeToParcel, createFromParcel, newArray
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT newArray
|
// CURIOUS_ABOUT newArray
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT describeContents
|
// CURIOUS_ABOUT describeContents
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
|||||||
Vendored
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel
|
// CURIOUS_ABOUT writeToParcel
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
|
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel
|
// CURIOUS_ABOUT writeToParcel
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
|
|||||||
Vendored
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>, describeContents
|
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>, describeContents
|
||||||
|
// WITH_RUNTIME
|
||||||
// LOCAL_VARIABLES_TABLE
|
// LOCAL_VARIABLES_TABLE
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
|
|||||||
Vendored
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel
|
// CURIOUS_ABOUT writeToParcel
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
|
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel, createFromParcel
|
// CURIOUS_ABOUT writeToParcel, createFromParcel
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
|||||||
@@ -27,5 +27,6 @@
|
|||||||
<orderEntry type="module" module-name="backend" />
|
<orderEntry type="module" module-name="backend" />
|
||||||
<orderEntry type="module" module-name="android-extensions-runtime" />
|
<orderEntry type="module" module-name="android-extensions-runtime" />
|
||||||
<orderEntry type="module" module-name="idea-gradle" />
|
<orderEntry type="module" module-name="idea-gradle" />
|
||||||
|
<orderEntry type="module" module-name="kapt3-idea" scope="TEST" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</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);
|
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")
|
@TestMetadata("modality.kt")
|
||||||
public void testModality() throws Exception {
|
public void testModality() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/modality.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/modality.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user