Parcelize: Support old (kotlinx.android.parcel) annotations in Parcelize plugin

This commit is contained in:
Yan Zhulanow
2020-09-18 01:52:14 +09:00
parent f0b93bf352
commit 1d5ab192f5
8 changed files with 108 additions and 41 deletions
@@ -18,9 +18,6 @@ package org.jetbrains.kotlin.parcelize
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.TypeParceler
import kotlinx.parcelize.WriteWith
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
@@ -40,10 +37,22 @@ import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.types.typeUtil.supertypes
class ParcelizeAnnotationChecker : CallChecker { class ParcelizeAnnotationChecker : CallChecker {
@Suppress("DEPRECATION")
companion object { companion object {
val TYPE_PARCELER_FQNAME = FqName(TypeParceler::class.java.name) val TYPE_PARCELER_FQ_NAMES = listOf(
val WRITE_WITH_FQNAME = FqName(WriteWith::class.java.name) FqName(kotlinx.parcelize.TypeParceler::class.java.name),
val IGNORED_ON_PARCEL_FQNAME = FqName(IgnoredOnParcel::class.java.name) FqName(kotlinx.android.parcel.TypeParceler::class.java.name)
)
val WRITE_WITH_FQ_NAMES = listOf(
FqName(kotlinx.parcelize.WriteWith::class.java.name),
FqName(kotlinx.android.parcel.WriteWith::class.java.name)
)
val IGNORED_ON_PARCEL_FQ_NAMES = listOf(
FqName(kotlinx.parcelize.IgnoredOnParcel::class.java.name),
FqName(kotlinx.android.parcel.IgnoredOnParcel::class.java.name)
)
} }
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
@@ -53,15 +62,15 @@ class ParcelizeAnnotationChecker : CallChecker {
val annotationEntry = resolvedCall.call.callElement.getNonStrictParentOfType<KtAnnotationEntry>() ?: return val annotationEntry = resolvedCall.call.callElement.getNonStrictParentOfType<KtAnnotationEntry>() ?: return
val annotationOwner = annotationEntry.getStrictParentOfType<KtModifierListOwner>() ?: return val annotationOwner = annotationEntry.getStrictParentOfType<KtModifierListOwner>() ?: return
if (annotationClass.fqNameSafe == TYPE_PARCELER_FQNAME) { if (annotationClass.fqNameSafe in TYPE_PARCELER_FQ_NAMES) {
checkTypeParcelerUsage(resolvedCall, annotationEntry, context, annotationOwner) checkTypeParcelerUsage(resolvedCall, annotationEntry, context, annotationOwner)
} }
if (annotationClass.fqNameSafe == WRITE_WITH_FQNAME) { if (annotationClass.fqNameSafe in WRITE_WITH_FQ_NAMES) {
checkWriteWithUsage(resolvedCall, annotationEntry, context, annotationOwner) checkWriteWithUsage(resolvedCall, annotationEntry, context, annotationOwner)
} }
if (annotationClass.fqNameSafe == IGNORED_ON_PARCEL_FQNAME) { if (annotationClass.fqNameSafe in IGNORED_ON_PARCEL_FQ_NAMES) {
checkIgnoredOnParcelUsage(annotationEntry, context, annotationOwner) checkIgnoredOnParcelUsage(annotationEntry, context, annotationOwner)
} }
} }
@@ -84,7 +93,7 @@ class ParcelizeAnnotationChecker : CallChecker {
val thisMappedType = resolvedCall.typeArguments.values.takeIf { it.size == 2 }?.first() ?: return val thisMappedType = resolvedCall.typeArguments.values.takeIf { it.size == 2 }?.first() ?: return
val duplicatingAnnotationCount = descriptor.annotations val duplicatingAnnotationCount = descriptor.annotations
.filter { it.fqName == TYPE_PARCELER_FQNAME } .filter { it.fqName in TYPE_PARCELER_FQ_NAMES }
.mapNotNull { it.type.arguments.takeIf { args -> args.size == 2 }?.first()?.type } .mapNotNull { it.type.arguments.takeIf { args -> args.size == 2 }?.first()?.type }
.count { it == thisMappedType } .count { it == thisMappedType }
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.parcelize package org.jetbrains.kotlin.parcelize
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import kotlinx.parcelize.TypeParceler
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy.CodegenBased import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy.CodegenBased
@@ -17,8 +16,8 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.ParcelizeAnnotationChecker.Companion.TYPE_PARCELER_FQ_NAMES
import org.jetbrains.kotlin.parcelize.ParcelizeResolveExtension.Companion.createMethod import org.jetbrains.kotlin.parcelize.ParcelizeResolveExtension.Companion.createMethod
import org.jetbrains.kotlin.parcelize.ParcelizeSyntheticComponent.ComponentKind.* import org.jetbrains.kotlin.parcelize.ParcelizeSyntheticComponent.ComponentKind.*
import org.jetbrains.kotlin.parcelize.serializers.* import org.jetbrains.kotlin.parcelize.serializers.*
@@ -427,10 +426,9 @@ open class ParcelizeCodegenExtension : ParcelizeExtensionBase, ExpressionCodegen
} }
internal fun getTypeParcelers(annotations: Annotations): List<TypeParcelerMapping> { internal fun getTypeParcelers(annotations: Annotations): List<TypeParcelerMapping> {
val typeParcelerFqName = FqName(TypeParceler::class.java.name)
val serializers = mutableListOf<TypeParcelerMapping>() val serializers = mutableListOf<TypeParcelerMapping>()
for (annotation in annotations.filter { it.fqName == typeParcelerFqName }) { for (annotation in annotations.filter { it.fqName in TYPE_PARCELER_FQ_NAMES }) {
val (mappedType, parcelerType) = annotation.type.arguments.takeIf { it.size == 2 } ?: continue val (mappedType, parcelerType) = annotation.type.arguments.takeIf { it.size == 2 } ?: continue
serializers += TypeParcelerMapping(mappedType.type, parcelerType.type) serializers += TypeParcelerMapping(mappedType.type, parcelerType.type)
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.parcelize package org.jetbrains.kotlin.parcelize
import kotlinx.parcelize.IgnoredOnParcel
import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.FrameMap import org.jetbrains.kotlin.codegen.FrameMap
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -37,7 +36,10 @@ val ANDROID_PARCEL_CLASS_FQNAME = FqName("android.os.Parcel")
class ParcelizeDeclarationChecker : DeclarationChecker { class ParcelizeDeclarationChecker : DeclarationChecker {
private companion object { private companion object {
private val IGNORED_ON_PARCEL_FQNAME = FqName(IgnoredOnParcel::class.java.canonicalName) private val IGNORED_ON_PARCEL_FQ_NAMES = listOf(
FqName(kotlinx.parcelize.IgnoredOnParcel::class.java.canonicalName),
FqName(kotlinx.android.parcel.IgnoredOnParcel::class.java.canonicalName)
)
} }
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
@@ -91,7 +93,7 @@ class ParcelizeDeclarationChecker : DeclarationChecker {
bindingContext: BindingContext bindingContext: BindingContext
) { ) {
fun hasIgnoredOnParcel(): Boolean { fun hasIgnoredOnParcel(): Boolean {
fun Annotations.hasIgnoredOnParcel() = any { it.fqName == IGNORED_ON_PARCEL_FQNAME } fun Annotations.hasIgnoredOnParcel() = any { it.fqName in IGNORED_ON_PARCEL_FQ_NAMES }
return property.annotations.hasIgnoredOnParcel() || (property.getter?.annotations?.hasIgnoredOnParcel() ?: false) return property.annotations.hasIgnoredOnParcel() || (property.getter?.annotations?.hasIgnoredOnParcel() ?: false)
} }
@@ -17,10 +17,10 @@
package org.jetbrains.kotlin.parcelize package org.jetbrains.kotlin.parcelize
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
@@ -169,11 +169,44 @@ interface ParcelizeSyntheticComponent {
} }
} }
val PARCELIZE_CLASS_FQNAME: FqName = FqName(Parcelize::class.java.canonicalName) val PARCELIZE_CLASS_FQ_NAMES: List<FqName> = listOf(
internal val PARCELER_FQNAME: FqName = FqName(Parceler::class.java.canonicalName) FqName(kotlinx.parcelize.Parcelize::class.java.canonicalName),
FqName(kotlinx.android.parcel.Parcelize::class.java.canonicalName)
)
internal val PARCELER_FQNAME = FqName(kotlinx.parcelize.Parceler::class.java.canonicalName)
val ClassDescriptor.isParcelize: Boolean val ClassDescriptor.isParcelize: Boolean
get() = this.annotations.hasAnnotation(PARCELIZE_CLASS_FQNAME) get() {
for (fqName in PARCELIZE_CLASS_FQ_NAMES) {
if (this.annotations.hasAnnotation(fqName)) {
return true
}
}
val KotlinType.isParceler return false
}
val KotlinType.isParceler: Boolean
get() = constructor.declarationDescriptor?.fqNameSafe == PARCELER_FQNAME get() = constructor.declarationDescriptor?.fqNameSafe == PARCELER_FQNAME
fun Annotated.findAnyAnnotation(fqNames: List<FqName>): AnnotationDescriptor? {
for (fqName in fqNames) {
val annotation = annotations.findAnnotation(fqName)
if (annotation != null) {
return annotation
}
}
return null
}
fun Annotated.hasAnyAnnotation(fqNames: List<FqName>): Boolean {
for (fqName in fqNames) {
if (annotations.hasAnnotation(fqName)) {
return true
}
}
return false
}
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.parcelize.serializers.RAW_VALUE_ANNOTATION_FQNAME import org.jetbrains.kotlin.parcelize.serializers.RAW_VALUE_ANNOTATION_FQ_NAMES
class IrParcelSerializerFactory(symbols: AndroidSymbols) { class IrParcelSerializerFactory(symbols: AndroidSymbols) {
/** /**
@@ -28,7 +28,7 @@ class IrParcelSerializerFactory(symbols: AndroidSymbols) {
strict: Boolean = false, strict: Boolean = false,
toplevel: Boolean = false toplevel: Boolean = false
): IrParcelSerializer { ): IrParcelSerializer {
fun strict() = strict && !irType.hasAnnotation(RAW_VALUE_ANNOTATION_FQNAME) fun strict() = strict && !irType.hasAnyAnnotation(RAW_VALUE_ANNOTATION_FQ_NAMES)
scope.getCustomSerializer(irType)?.let { parceler -> scope.getCustomSerializer(irType)?.let { parceler ->
return IrCustomParcelSerializer(parceler) return IrCustomParcelSerializer(parceler)
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.typeOrNull import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.util.constructedClass import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.parcelize.ParcelizeAnnotationChecker import org.jetbrains.kotlin.parcelize.ParcelizeAnnotationChecker
// Keep track of all custom parcelers which are currently in scope. // Keep track of all custom parcelers which are currently in scope.
@@ -30,7 +29,7 @@ class IrParcelerScope(private val parent: IrParcelerScope? = null) {
} }
fun IrParcelerScope?.getCustomSerializer(irType: IrType): IrClass? { fun IrParcelerScope?.getCustomSerializer(irType: IrType): IrClass? {
return irType.getAnnotation(ParcelizeAnnotationChecker.WRITE_WITH_FQNAME)?.let { writeWith -> return irType.getAnyAnnotation(ParcelizeAnnotationChecker.WRITE_WITH_FQ_NAMES)?.let { writeWith ->
(writeWith.type as IrSimpleType).arguments.single().typeOrNull!!.getClass()!! (writeWith.type as IrSimpleType).arguments.single().typeOrNull!!.getClass()!!
} ?: this?.get(irType) } ?: this?.get(irType)
} }
@@ -41,7 +40,7 @@ fun IrParcelerScope?.hasCustomSerializer(irType: IrType): Boolean {
fun IrAnnotationContainer.getParcelerScope(parent: IrParcelerScope? = null): IrParcelerScope? { fun IrAnnotationContainer.getParcelerScope(parent: IrParcelerScope? = null): IrParcelerScope? {
val typeParcelerAnnotations = annotations.filterTo(mutableListOf()) { val typeParcelerAnnotations = annotations.filterTo(mutableListOf()) {
it.symbol.owner.constructedClass.fqNameWhenAvailable == ParcelizeAnnotationChecker.TYPE_PARCELER_FQNAME it.symbol.owner.constructedClass.fqNameWhenAvailable in ParcelizeAnnotationChecker.TYPE_PARCELER_FQ_NAMES
} }
if (typeParcelerAnnotations.isEmpty()) if (typeParcelerAnnotations.isEmpty())
@@ -8,12 +8,10 @@ package org.jetbrains.kotlin.parcelize.ir
import org.jetbrains.kotlin.backend.common.ir.allOverridden import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
@@ -23,14 +21,14 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CLASS_FQNAME import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELER_FQNAME import org.jetbrains.kotlin.parcelize.PARCELER_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELIZE_CLASS_FQNAME import org.jetbrains.kotlin.parcelize.PARCELIZE_CLASS_FQ_NAMES
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase.Companion.CREATOR_NAME import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase.Companion.CREATOR_NAME
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
// true if the class should be processed by the parcelize plugin // true if the class should be processed by the parcelize plugin
val IrClass.isParcelize: Boolean val IrClass.isParcelize: Boolean
get() = kind in ParcelizeExtensionBase.ALLOWED_CLASS_KINDS && hasAnnotation(PARCELIZE_CLASS_FQNAME) get() = kind in ParcelizeExtensionBase.ALLOWED_CLASS_KINDS && hasAnyAnnotation(PARCELIZE_CLASS_FQ_NAMES)
// Finds the getter for a pre-existing CREATOR field on the class companion, which is used for manual Parcelable implementations in Kotlin. // Finds the getter for a pre-existing CREATOR field on the class companion, which is used for manual Parcelable implementations in Kotlin.
val IrClass.creatorGetter: IrSimpleFunctionSymbol? val IrClass.creatorGetter: IrSimpleFunctionSymbol?
@@ -175,3 +173,24 @@ fun IrClass.getMethodWithoutArguments(name: String): IrSimpleFunction =
function.name.asString() == name && function.dispatchReceiverParameter != null function.name.asString() == name && function.dispatchReceiverParameter != null
&& function.extensionReceiverParameter == null && function.valueParameters.isEmpty() && function.extensionReceiverParameter == null && function.valueParameters.isEmpty()
} }
internal fun IrAnnotationContainer.hasAnyAnnotation(fqNames: List<FqName>): Boolean {
for (fqName in fqNames) {
if (hasAnnotation(fqName)) {
return true
}
}
return false
}
internal fun IrAnnotationContainer.getAnyAnnotation(fqNames: List<FqName>): IrConstructorCall? {
for (fqName in fqNames) {
val annotation = getAnnotation(fqName)
if (annotation != null) {
return annotation
}
}
return null
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.parcelize.serializers package org.jetbrains.kotlin.parcelize.serializers
import kotlinx.parcelize.WriteWith
import org.jetbrains.kotlin.codegen.FrameMap import org.jetbrains.kotlin.codegen.FrameMap
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -27,6 +26,8 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.findAnyAnnotation
import org.jetbrains.kotlin.parcelize.hasAnyAnnotation
import org.jetbrains.kotlin.parcelize.isParcelize import org.jetbrains.kotlin.parcelize.isParcelize
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -42,7 +43,10 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
val RAW_VALUE_ANNOTATION_FQNAME = FqName("kotlinx.parcelize.RawValue") val RAW_VALUE_ANNOTATION_FQ_NAMES = listOf(
FqName(kotlinx.parcelize.RawValue::class.java.name),
FqName(kotlinx.android.parcel.RawValue::class.java.name)
)
internal typealias TypeParcelerMapping = Pair<KotlinType, KotlinType> internal typealias TypeParcelerMapping = Pair<KotlinType, KotlinType>
@@ -64,7 +68,10 @@ interface ParcelSerializer {
} }
companion object { companion object {
private val WRITE_WITH_FQNAME = FqName(WriteWith::class.java.name) private val WRITE_WITH_FQ_NAMES = listOf(
FqName(kotlinx.parcelize.WriteWith::class.java.name),
FqName(kotlinx.android.parcel.WriteWith::class.java.name),
)
private fun KotlinTypeMapper.mapTypeSafe(type: KotlinType, forceBoxed: Boolean) = when { private fun KotlinTypeMapper.mapTypeSafe(type: KotlinType, forceBoxed: Boolean) = when {
type.isError -> Type.getObjectType("java/lang/Object") type.isError -> Type.getObjectType("java/lang/Object")
@@ -81,10 +88,10 @@ interface ParcelSerializer {
val typeMapper = context.typeMapper val typeMapper = context.typeMapper
val className = asmType.className val className = asmType.className
fun strict() = strict && !type.annotations.hasAnnotation(RAW_VALUE_ANNOTATION_FQNAME) fun strict() = strict && !type.hasAnyAnnotation(RAW_VALUE_ANNOTATION_FQ_NAMES)
fun findCustomParcelerType(type: KotlinType): KotlinType? { fun findCustomParcelerType(type: KotlinType): KotlinType? {
type.annotations.findAnnotation(WRITE_WITH_FQNAME)?.let { writeWith -> type.findAnyAnnotation(WRITE_WITH_FQ_NAMES)?.let { writeWith ->
val parceler = writeWith.type.arguments.singleOrNull()?.type val parceler = writeWith.type.arguments.singleOrNull()?.type
if (parceler != null && !parceler.isError) { if (parceler != null && !parceler.isError) {
return parceler return parceler
@@ -371,7 +378,7 @@ interface ParcelSerializer {
} }
else -> { else -> {
if (strict && !type.annotations.hasAnnotation(RAW_VALUE_ANNOTATION_FQNAME)) if (strict && !type.hasAnyAnnotation(RAW_VALUE_ANNOTATION_FQ_NAMES))
throw IllegalArgumentException("Illegal type") throw IllegalArgumentException("Illegal type")
else else
GenericParcelSerializer(asmType) GenericParcelSerializer(asmType)