Repository: JetBrains/kotlin
File: plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ir/irUtils.kt (Kotlin)

Code before:
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELER_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELIZE_CLASS_FQ_NAMES
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase.Companion.CREATOR_NAME
import org.jetbrains.kotlin.types.Variance

private val IrClass.sealedSuperClass: IrClass?
    get() = superTypes.mapNotNull { superType ->
        superType.classOrNull?.owner?.takeIf { it.modality == Modality.SEALED }
    }.singleOrNull()

// true if the class should be processed by the parcelize plugin
val IrClass.isParcelize: Boolean
    get() = kind in ParcelizeExtensionBase.ALLOWED_CLASS_KINDS &&
            (hasAnyAnnotation(PARCELIZE_CLASS_FQ_NAMES) || sealedSuperClass?.hasAnyAnnotation(PARCELIZE_CLASS_FQ_NAMES) == true)

// 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?
    get() = companionObject()?.getPropertyGetter(CREATOR_NAME.asString())?.takeIf {
        it.owner.correspondingPropertySymbol?.owner?.backingField?.hasAnnotation(FqName("kotlin.jvm.JvmField")) == true
    }

// true if the class has a static CREATOR field
val IrClass.hasCreatorField: Boolean
    get() = fields.any { field -> field.name == CREATOR_NAME } || creatorGetter != null

// object P : Parceler<T> { fun T.write(parcel: Parcel, flags: Int) ...}
fun IrBuilderWithScope.parcelerWrite(
    parceler: IrClass,
    parcel: IrValueDeclaration,
    flags: IrValueDeclaration,
    value: IrExpression,
) = irCall(parceler.parcelerSymbolByName("write")!!).apply {
    dispatchReceiver = irGetObject(parceler.symbol)
    extensionReceiver = value
    putValueArgument(0, irGet(parcel))
    putValueArgument(1, irGet(flags))
}

// object P : Parceler<T> { fun create(parcel: Parcel): T }

Review comment (suggestion):
Sealed interfaces are possible since 1.5, so a class can have several sealed supertypes:
```
sealed class A
sealed interface I

class C : A(), I
```

Code after:
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELER_FQNAME
import org.jetbrains.kotlin.parcelize.PARCELIZE_CLASS_FQ_NAMES
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase.Companion.CREATOR_NAME
import org.jetbrains.kotlin.types.Variance

// true if the class should be processed by the parcelize plugin
val IrClass.isParcelize: Boolean
    get() = kind in ParcelizeExtensionBase.ALLOWED_CLASS_KINDS &&
            (hasAnyAnnotation(PARCELIZE_CLASS_FQ_NAMES) || superTypes.any { superType ->
                superType.classOrNull?.owner?.let {
                    it.modality == Modality.SEALED && it.hasAnyAnnotation(PARCELIZE_CLASS_FQ_NAMES)
                } == true
            })

// 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?
    get() = companionObject()?.getPropertyGetter(CREATOR_NAME.asString())?.takeIf {
        it.owner.correspondingPropertySymbol?.owner?.backingField?.hasAnnotation(FqName("kotlin.jvm.JvmField")) == true
    }

// true if the class has a static CREATOR field
val IrClass.hasCreatorField: Boolean
    get() = fields.any { field -> field.name == CREATOR_NAME } || creatorGetter != null

// object P : Parceler<T> { fun T.write(parcel: Parcel, flags: Int) ...}
fun IrBuilderWithScope.parcelerWrite(
    parceler: IrClass,
    parcel: IrValueDeclaration,
    flags: IrValueDeclaration,
    value: IrExpression,
) = irCall(parceler.parcelerSymbolByName("write")!!).apply {
    dispatchReceiver = irGetObject(parceler.symbol)
    extensionReceiver = value
    putValueArgument(0, irGet(parcel))
    putValueArgument(1, irGet(flags))
}

// object P : Parceler<T> { fun create(parcel: Parcel): T }
fun IrBuilderWithScope.parcelerCreate(parceler: IrClass, parcel: IrValueDeclaration): IrExpression =