fun convertClass()

in compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt [472:707]


    fun convertClass(classNode: LighterASTNode): FirRegularClass {
        var modifiers: ModifierList? = null
        var classKind: ClassKind = ClassKind.CLASS
        var identifier: String? = null
        val firTypeParameters = mutableListOf<FirTypeParameter>()
        var primaryConstructor: LighterASTNode? = null
        val typeConstraints = mutableListOf<TypeConstraint>()
        var classBody: LighterASTNode? = null
        var superTypeList: LighterASTNode? = null
        var typeParameterList: LighterASTNode? = null
        classNode.forEachChildren {
            when (it.tokenType) {
                MODIFIER_LIST -> modifiers = convertModifierList(it, isInClass = true)
                IDENTIFIER -> identifier = it.asText
            }
        }

        val calculatedModifiers = modifiers ?: ModifierList()
        val className = identifier.nameAsSafeName(if (calculatedModifiers.isCompanion()) "Companion" else "")
        val isLocalWithinParent = classNode.getParent()?.elementType != CLASS_BODY && isClassLocal(classNode) { getParent() }
        val classIsExpect = calculatedModifiers.hasExpect() || context.containerIsExpect

        return withChildClassName(className, isExpect = classIsExpect, isLocalWithinParent) {
            val classSymbol = FirRegularClassSymbol(context.currentClassId)
            withContainerSymbol(classSymbol) {
                classNode.forEachChildren {
                    when (it.tokenType) {
                        CLASS_KEYWORD -> classKind = ClassKind.CLASS
                        INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE
                        OBJECT_KEYWORD -> classKind = ClassKind.OBJECT
                        TYPE_PARAMETER_LIST -> typeParameterList = it
                        PRIMARY_CONSTRUCTOR -> primaryConstructor = it
                        SUPER_TYPE_LIST -> superTypeList = it
                        TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
                        CLASS_BODY -> classBody = it
                    }
                }

                if (classKind == ClassKind.CLASS) {
                    classKind = when {
                        calculatedModifiers.isEnum() -> ClassKind.ENUM_CLASS
                        calculatedModifiers.isAnnotation() -> ClassKind.ANNOTATION_CLASS
                        else -> classKind
                    }
                }

                val isLocal = context.inLocalContext
                val status = FirDeclarationStatusImpl(
                    if (isLocal) Visibilities.Local else calculatedModifiers.getVisibility(publicByDefault = true),
                    calculatedModifiers.getModality(isClassOrObject = true)
                ).apply {
                    isExpect = classIsExpect
                    isActual = calculatedModifiers.hasActual()
                    isInner = calculatedModifiers.isInner()
                    isCompanion = calculatedModifiers.isCompanion() && classKind == ClassKind.OBJECT
                    isData = calculatedModifiers.isDataClass()
                    isInline = calculatedModifiers.isInlineClass()
                    isValue = calculatedModifiers.isValueClass()
                    isFun = calculatedModifiers.isFunctionalInterface()
                    isExternal = calculatedModifiers.hasExternal()
                }


                typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) }

                withCapturedTypeParameters(
                    status = status.isInner || isLocal,
                    declarationSource = classNode.toFirSourceElement(),
                    currentFirTypeParameters = firTypeParameters,
                ) {
                    var delegatedFieldsMap: Map<Int, FirFieldSymbol>? = null
                    buildRegularClass {
                        source = classNode.toFirSourceElement()
                        moduleData = baseModuleData
                        origin = FirDeclarationOrigin.Source
                        name = className
                        this.status = status
                        this.classKind = classKind
                        scopeProvider = baseScopeProvider
                        symbol = classSymbol
                        modifiers?.convertAnnotationsTo(annotations)
                        typeParameters += firTypeParameters

                        context.appendOuterTypeParameters(ignoreLastLevel = true, typeParameters)

                        val selfType = classNode.toDelegatedSelfType(this)
                        registerSelfType(selfType)

                        val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it) }
                        var delegatedSuperTypeRef: FirTypeRef? = delegationSpecifiers?.superTypeCalls?.lastOrNull()?.delegatedSuperTypeRef
                        val delegatedConstructorSource: KtLightSourceElement? = delegationSpecifiers?.superTypeCalls?.lastOrNull()?.source

                        val superTypeRefs = mutableListOf<FirTypeRef>()

                        delegationSpecifiers?.let { superTypeRefs += it.superTypesRef }

                        when {
                            calculatedModifiers.isEnum() && (classKind == ClassKind.ENUM_CLASS) && delegatedConstructorSource == null -> {
                                delegatedSuperTypeRef = buildResolvedTypeRef {
                                    coneType = ConeClassLikeTypeImpl(
                                        implicitEnumType.coneType.lookupTag,
                                        arrayOf(selfType.coneType),
                                        isMarkedNullable = false
                                    )
                                    source = classNode.toFirSourceElement(KtFakeSourceElementKind.EnumSuperTypeRef)
                                }
                                superTypeRefs += delegatedSuperTypeRef
                            }
                            calculatedModifiers.isAnnotation() && (classKind == ClassKind.ANNOTATION_CLASS) -> {
                                superTypeRefs += implicitAnnotationType
                                delegatedSuperTypeRef = implicitAnyType
                            }
                        }

                        val classIsKotlinAny = symbol.classId == StandardClassIds.Any

                        if (superTypeRefs.isEmpty() && !classIsKotlinAny) {
                            val classIsKotlinNothing = symbol.classId == StandardClassIds.Nothing
                            // kotlin.Nothing doesn't have `Any` supertype, but does have delegating constructor call to Any
                            if (!classIsKotlinNothing) {
                                superTypeRefs += implicitAnyType
                            }
                            delegatedSuperTypeRef = implicitAnyType
                        }

                        this.superTypeRefs += superTypeRefs

                        val secondaryConstructors = classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR)
                        val classWrapper = ClassWrapper(
                            calculatedModifiers, classKind, this, hasSecondaryConstructor = secondaryConstructors.isNotEmpty(),
                            hasDefaultConstructor = if (primaryConstructor != null) !primaryConstructor.hasValueParameters()
                            else secondaryConstructors.isEmpty() || secondaryConstructors.any { !it.hasValueParameters() },
                            delegatedSelfTypeRef = selfType,
                            delegatedSuperTypeRef = delegatedSuperTypeRef ?: FirImplicitTypeRefImplWithoutSource,
                            delegatedSuperCalls = delegationSpecifiers?.superTypeCalls ?: emptyList()
                        )
                        //parse primary constructor
                        val primaryConstructorWrapper = convertPrimaryConstructor(
                            primaryConstructor,
                            selfType.source,
                            classWrapper,
                            delegatedConstructorSource,
                            containingClassIsExpectClass = status.isExpect,
                            isImplicitlyActual = isImplicitlyActual(status, classKind),
                            isKotlinAny = classIsKotlinAny,
                        )
                        val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
                        firPrimaryConstructor?.let { declarations += it }
                        delegationSpecifiers?.delegateFieldsMap?.values?.mapTo(declarations) { it.fir }
                        delegatedFieldsMap = delegationSpecifiers?.delegateFieldsMap?.takeIf { it.isNotEmpty() }

                        val properties = mutableListOf<FirProperty>()
                        if (primaryConstructor != null && firPrimaryConstructor != null) {
                            //parse properties
                            properties += primaryConstructorWrapper.valueParameters
                                .filter { it.hasValOrVar() }
                                .map {
                                    it.toFirPropertyFromPrimaryConstructor(
                                        baseModuleData,
                                        callableIdForName(it.firValueParameter.name),
                                        classIsExpect,
                                        currentDispatchReceiverType(),
                                        context
                                    )
                                }
                            addDeclarations(properties)
                        }

                        //parse declarations
                        classBody?.let {
                            addDeclarations(convertClassBody(it, classWrapper))
                        }

                        //parse data class
                        if (calculatedModifiers.isDataClass() && firPrimaryConstructor != null) {
                            val zippedParameters = properties.map { it.source!!.lighterASTNode to it }
                            DataClassMembersGenerator(
                                primaryConstructor ?: classNode,
                                this,
                                firPrimaryConstructor,
                                zippedParameters,
                                context.packageFqName,
                                context.className,
                                addValueParameterAnnotations = { valueParam ->
                                    withContainerSymbol(symbol) {
                                        valueParam.forEachChildren { node ->
                                            if (node.tokenType == MODIFIER_LIST) {
                                                buildList {
                                                    convertAnnotationsOnlyTo(node, this)
                                                }.filterTo(annotations) {
                                                    it.useSiteTarget.appliesToPrimaryConstructorParameter()
                                                }
                                            }
                                        }
                                    }
                                },
                            ).generate()
                        }

                        if (calculatedModifiers.isEnum()) {
                            generateValuesFunction(
                                baseModuleData,
                                context.packageFqName,
                                context.className,
                                classIsExpect
                            )
                            generateValueOfFunction(
                                baseModuleData,
                                context.packageFqName,
                                context.className,
                                classIsExpect
                            )
                            generateEntriesGetter(
                                baseModuleData,
                                context.packageFqName,
                                context.className,
                                classIsExpect
                            )
                        }
                        initCompanionObjectSymbolAttr()

                        contextParameters.addContextParameters(modifiers?.contextLists, classSymbol)
                    }.also {
                        it.delegateFieldsMap = delegatedFieldsMap
                    }
                }.also {
                    fillDanglingConstraintsTo(firTypeParameters, typeConstraints, it)
                }
            }
        }.also {
            if (classNode.getParent()?.elementType == KtStubElementTypes.CLASS_BODY) {
                it.initContainingClassForLocalAttr()
            }
            it.initContainingScriptOrReplAttr()
        }
    }