Parcelize: Support old (kotlinx.android.parcel) annotations in Parcelize plugin
This commit is contained in:
+19
-10
@@ -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 }
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -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
-3
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-6
@@ -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
|
||||||
|
}
|
||||||
+2
-2
@@ -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)
|
||||||
|
|||||||
+2
-3
@@ -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())
|
||||||
|
|||||||
+25
-6
@@ -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
|
||||||
|
}
|
||||||
+13
-6
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user