All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.co.touchlab.skie.kir.builtin.DescriptorBasedKirBuiltins.kt Maven / Gradle / Ivy

The newest version!
@file:Suppress("invisible_reference", "invisible_member")

package co.touchlab.skie.kir.builtin

import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider
import co.touchlab.skie.kir.descriptor.DescriptorKirProvider
import co.touchlab.skie.kir.descriptor.ExtraDescriptorBuiltins
import co.touchlab.skie.kir.element.KirClass
import co.touchlab.skie.kir.element.KirModule
import co.touchlab.skie.kir.element.KirTypeParameter
import co.touchlab.skie.kir.element.toTypeParameterUsage
import co.touchlab.skie.kir.type.DeclaredKirType
import co.touchlab.skie.oir.element.OirTypeParameter
import co.touchlab.skie.phases.kir.CreateExposedKirTypesPhase
import org.jetbrains.kotlin.backend.konan.objcexport.NSNumberKind
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe

@Suppress("FunctionName")
class DescriptorBasedKirBuiltins(
    override val stdlibModule: KirModule,
    kotlinBuiltIns: KotlinBuiltIns,
    extraDescriptorBuiltins: ExtraDescriptorBuiltins,
    private val namer: ObjCExportNamer,
    private val descriptorConfigurationProvider: DescriptorConfigurationProvider,
    private val descriptorKirProvider: DescriptorKirProvider,
) : KirBuiltins {
    // TODO Not all Builtin methods are supported yet (supported are only those converted from Kotlin equivalents in Any)

    private val mutableBuiltinClasses = mutableSetOf()

    override val builtinClasses: Set by ::mutableBuiltinClasses

    override val NSObject: KirClass = Class(extraDescriptorBuiltins.NSObject)

    override val NSCopying: KirClass = Class(extraDescriptorBuiltins.NSCopying)

    override val NSError: KirClass = Class(extraDescriptorBuiltins.NSError) {
        superTypes.add(NSObject.defaultType)
    }

    override val NSString: KirClass = Class(extraDescriptorBuiltins.NSString) {
        superTypes.add(NSObject.defaultType)
    }

    override val NSArray: KirClass = Class(extraDescriptorBuiltins.NSArray) {
        KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        superTypes.add(NSObject.defaultType)
    }

    override val NSMutableArray: KirClass = Class(extraDescriptorBuiltins.NSMutableArray) {
        val typeParameter = KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val typeArgument = typeParameter.toTypeParameterUsage()

        superTypes.add(
            NSArray.toType(typeArgument),
        )
    }

    override val NSSet: KirClass = Class(extraDescriptorBuiltins.NSSet) {
        KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        superTypes.add(NSObject.defaultType)
    }

    override val NSMutableSet: KirClass = Class(extraDescriptorBuiltins.NSMutableSet) {
        val typeParameter = KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val typeArgument = typeParameter.toTypeParameterUsage()

        superTypes.add(
            NSSet.toType(typeArgument),
        )
    }

    override val NSDictionary: KirClass = Class(extraDescriptorBuiltins.NSDictionary) {
        KirTypeParameter(
            name = "KeyType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        superTypes.add(NSObject.defaultType)
    }

    override val NSMutableDictionary: KirClass = Class(extraDescriptorBuiltins.NSMutableDictionary) {
        val keyTypeParameter = KirTypeParameter(
            name = "KeyType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val valueTypeParameter = KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val keyTypeArgument = keyTypeParameter.toTypeParameterUsage()
        val valueTypeArgument = valueTypeParameter.toTypeParameterUsage()

        superTypes.add(
            NSDictionary.toType(keyTypeArgument, valueTypeArgument),
        )
    }

    override val NSNumber: KirClass = Class(extraDescriptorBuiltins.NSNumber) {
        // Technically should be NSValue instead but for our purposes it's not needed because we use the class only as a supertype
        superTypes.add(NSObject.defaultType)
    }

    override val Base: KirClass = Class(
        name = namer.kotlinAnyName,
        classDescriptor = kotlinBuiltIns.any,
        superTypes = listOf(
            NSObject.defaultType,
            NSCopying.defaultType,
        ),
    )

    override val MutableSet: KirClass = Class(
        name = namer.mutableSetName,
        classDescriptor = kotlinBuiltIns.mutableSet,
    ) {
        val typeParameter = KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val typeArgument = typeParameter.toTypeParameterUsage()

        superTypes.add(
            NSMutableSet.toType(typeArgument),
        )
    }

    override val MutableMap: KirClass = Class(
        name = namer.mutableMapName,
        classDescriptor = kotlinBuiltIns.mutableMap,
    ) {
        val keyTypeParameter = KirTypeParameter(
            name = "KeyType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val valueTypeParameter = KirTypeParameter(
            name = "ObjectType",
            parent = this,
            variance = OirTypeParameter.Variance.Covariant,
        )

        val keyTypeArgument = keyTypeParameter.toTypeParameterUsage()
        val valueTypeArgument = valueTypeParameter.toTypeParameterUsage()

        superTypes.add(
            NSMutableDictionary.toType(keyTypeArgument, valueTypeArgument),
        )
    }

    override val Number: KirClass = Class(
        name = namer.kotlinNumberName,
        classDescriptor = kotlinBuiltIns.number,
        superTypes = listOf(
            NSNumber.defaultType,
        ),
    )

    val nsNumberDeclarations: Map =
        NSNumberKind.values().mapNotNull { it.mappedKotlinClassId }
            .associateWith { classId ->
                Class(
                    name = namer.numberBoxName(classId),
                    classDescriptor = kotlinBuiltIns.getBuiltInClassByFqName(FqName(classId.asFqNameString())),
                    superTypes = listOf(Number.defaultType),
                )
            }

    override val nsNumberDeclarationsByFqName: Map =
        nsNumberDeclarations.mapKeys { it.key.asFqNameString() }

    private fun Class(
        name: ObjCExportNamer.ClassOrProtocolName,
        classDescriptor: ClassDescriptor,
        superTypes: List = emptyList(),
        apply: KirClass.() -> Unit = {},
    ): KirClass = KirClass(
        kotlinFqName = classDescriptor.fqNameSafe.asString(),
        objCName = name.objCName,
        swiftName = name.swiftName,
        parent = stdlibModule,
        kind = KirClass.Kind.Class,
        origin = KirClass.Origin.Kotlin,
        superTypes = superTypes,
        isSealed = false,
        hasUnexposedSealedSubclasses = false,
        nestingLevel = CreateExposedKirTypesPhase.getNestingLevel(classDescriptor),
        configuration = descriptorConfigurationProvider.getConfiguration(classDescriptor),
    ).apply {
        descriptorKirProvider.registerClass(this, classDescriptor)

        mutableBuiltinClasses.add(this)

        apply()
    }

    fun Class(descriptor: ClassDescriptor, apply: KirClass.() -> Unit = {}): KirClass =
        descriptorKirProvider.getExternalBuiltinClass(descriptor).apply {
            mutableBuiltinClasses.add(this)

            apply()
        }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy