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

org.jetbrains.kotlin.fir.deserialization.FirMemberDeserializer.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.fir.deserialization

import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyBackingField
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.sourceElement
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.transformers.setLazyPublishedVisibility
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.toEffectiveVisibility
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.getName

class FirDeserializationContext(
    val nameResolver: NameResolver,
    val typeTable: TypeTable,
    val versionRequirementTable: VersionRequirementTable,
    val moduleData: FirModuleData,
    val packageFqName: FqName,
    val relativeClassName: FqName?,
    val typeDeserializer: FirTypeDeserializer,
    val annotationDeserializer: AbstractAnnotationDeserializer,
    val constDeserializer: FirConstDeserializer,
    val containerSource: DeserializedContainerSource?,
    val outerClassSymbol: FirRegularClassSymbol?,
    val outerTypeParameters: List
) {
    val session: FirSession = moduleData.session

    val allTypeParameters: List =
        typeDeserializer.ownTypeParameters + outerTypeParameters

    fun childContext(
        typeParameterProtos: List,
        containingDeclarationSymbol: FirBasedSymbol<*>,
        nameResolver: NameResolver = this.nameResolver,
        typeTable: TypeTable = this.typeTable,
        relativeClassName: FqName? = this.relativeClassName,
        containerSource: DeserializedContainerSource? = this.containerSource,
        outerClassSymbol: FirRegularClassSymbol? = this.outerClassSymbol,
        annotationDeserializer: AbstractAnnotationDeserializer = this.annotationDeserializer,
        constDeserializer: FirConstDeserializer = this.constDeserializer,
        capturesTypeParameters: Boolean = true,
    ): FirDeserializationContext = FirDeserializationContext(
        nameResolver,
        typeTable,
        versionRequirementTable,
        moduleData,
        packageFqName,
        relativeClassName,
        typeDeserializer.forChildContext(
            typeParameterProtos, containingDeclarationSymbol, nameResolver, typeTable, annotationDeserializer
        ),
        annotationDeserializer,
        constDeserializer,
        containerSource,
        outerClassSymbol,
        if (capturesTypeParameters) allTypeParameters else emptyList()
    )

    val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this)
    val dispatchReceiver = relativeClassName?.let { ClassId(packageFqName, it, isLocal = false).defaultType(allTypeParameters) }

    companion object {
        fun createForPackage(
            fqName: FqName,
            packageProto: ProtoBuf.Package,
            nameResolver: NameResolver,
            moduleData: FirModuleData,
            annotationDeserializer: AbstractAnnotationDeserializer,
            flexibleTypeFactory: FirTypeDeserializer.FlexibleTypeFactory,
            constDeserializer: FirConstDeserializer,
            containerSource: DeserializedContainerSource?
        ): FirDeserializationContext = createRootContext(
            nameResolver,
            TypeTable(packageProto.typeTable),
            moduleData,
            VersionRequirementTable.create(packageProto.versionRequirementTable),
            annotationDeserializer,
            flexibleTypeFactory,
            constDeserializer,
            fqName,
            relativeClassName = null,
            typeParameterProtos = emptyList(),
            containerSource,
            outerClassSymbol = null,
            containingDeclarationSymbol = null
        )

        fun createForClass(
            classId: ClassId,
            classProto: ProtoBuf.Class,
            nameResolver: NameResolver,
            moduleData: FirModuleData,
            annotationDeserializer: AbstractAnnotationDeserializer,
            flexibleTypeFactory: FirTypeDeserializer.FlexibleTypeFactory,
            constDeserializer: FirConstDeserializer,
            containerSource: DeserializedContainerSource?,
            outerClassSymbol: FirRegularClassSymbol
        ): FirDeserializationContext = createRootContext(
            nameResolver,
            TypeTable(classProto.typeTable),
            moduleData,
            VersionRequirementTable.create(classProto.versionRequirementTable),
            annotationDeserializer,
            flexibleTypeFactory,
            constDeserializer,
            classId.packageFqName,
            classId.relativeClassName,
            classProto.typeParameterList,
            containerSource,
            outerClassSymbol,
            outerClassSymbol
        )

        private fun createRootContext(
            nameResolver: NameResolver,
            typeTable: TypeTable,
            moduleData: FirModuleData,
            versionRequirementTable: VersionRequirementTable,
            annotationDeserializer: AbstractAnnotationDeserializer,
            flexibleTypeFactory: FirTypeDeserializer.FlexibleTypeFactory,
            constDeserializer: FirConstDeserializer,
            packageFqName: FqName,
            relativeClassName: FqName?,
            typeParameterProtos: List,
            containerSource: DeserializedContainerSource?,
            outerClassSymbol: FirRegularClassSymbol?,
            containingDeclarationSymbol: FirBasedSymbol<*>?
        ): FirDeserializationContext {
            return FirDeserializationContext(
                nameResolver, typeTable,
                versionRequirementTable,
                moduleData,
                packageFqName,
                relativeClassName,
                FirTypeDeserializer(
                    moduleData,
                    nameResolver,
                    typeTable,
                    annotationDeserializer,
                    flexibleTypeFactory,
                    typeParameterProtos,
                    null,
                    containingDeclarationSymbol
                ),
                annotationDeserializer,
                constDeserializer,
                containerSource,
                outerClassSymbol,
                emptyList()
            )
        }
    }
}

class FirMemberDeserializer(private val c: FirDeserializationContext) {
    private val contractDeserializer = FirContractDeserializer(c)

    private fun loadOldFlags(oldFlags: Int): Int {
        val lowSixBits = oldFlags and 0x3f
        val rest = (oldFlags shr 8) shl 6
        return lowSixBits + rest
    }

    /**
     * If loading happens in post-compute, then symbol for type alias is already computed and should be provided in [preComputedSymbol]
     * @See AbstractFirDeserializedSymbolProvider.findAndDeserializeTypeAlias
     */
    fun loadTypeAlias(proto: ProtoBuf.TypeAlias, preComputedSymbol: FirTypeAliasSymbol? = null): FirTypeAlias {
        val flags = proto.flags
        val name = c.nameResolver.getName(proto.name)
        val classId = ClassId(c.packageFqName, name)
        val symbol = preComputedSymbol ?: FirTypeAliasSymbol(classId)
        val local = c.childContext(proto.typeParameterList, containingDeclarationSymbol = symbol)
        val versionRequirements = VersionRequirement.create(proto, c)
        return buildTypeAlias {
            moduleData = c.moduleData
            origin = FirDeclarationOrigin.Library
            this.name = name
            val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags))
            status = FirResolvedDeclarationStatusImpl(
                visibility,
                Modality.FINAL,
                visibility.toEffectiveVisibility(owner = null)
            ).apply {
                isExpect = Flags.IS_EXPECT_CLASS.get(flags)
                isActual = false
            }

            annotations += c.annotationDeserializer.loadTypeAliasAnnotations(proto, local.nameResolver)
            this.symbol = symbol
            expandedTypeRef = proto.underlyingType(c.typeTable).toTypeRef(local)
            resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
            typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
            deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(c.session, fromJava = false, versionRequirements)
        }.apply {
            this.versionRequirements = versionRequirements
            sourceElement = c.containerSource
        }
    }

    private fun loadPropertyGetter(
        proto: ProtoBuf.Property,
        classSymbol: FirClassSymbol<*>?,
        defaultAccessorFlags: Int,
        returnTypeRef: FirTypeRef,
        propertySymbol: FirPropertySymbol,
        local: FirDeserializationContext,
        propertyModality: Modality,
    ): FirPropertyAccessor {
        val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags
        val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))
        val accessorModality = ProtoEnumFlags.modality(Flags.MODALITY.get(getterFlags))
        val effectiveVisibility = visibility.toEffectiveVisibility(classSymbol)
        return if (Flags.IS_NOT_DEFAULT.get(getterFlags)) {
            buildPropertyAccessor {
                moduleData = c.moduleData
                origin = FirDeclarationOrigin.Library
                this.returnTypeRef = returnTypeRef
                resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
                isGetter = true
                status = FirResolvedDeclarationStatusImpl(visibility, accessorModality, effectiveVisibility).apply {
                    isInline = Flags.IS_INLINE_ACCESSOR.get(getterFlags)
                    isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(getterFlags)
                }
                this.symbol = FirPropertyAccessorSymbol()
                dispatchReceiverType = c.dispatchReceiver
                this.propertySymbol = propertySymbol
            }.apply {
                this.versionRequirements = VersionRequirement.create(proto, c)
            }
        } else {
            FirDefaultPropertyGetter(
                null,
                c.moduleData,
                FirDeclarationOrigin.Library,
                returnTypeRef,
                visibility,
                propertySymbol,
                propertyModality,
                effectiveVisibility,
                resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES,
            )
        }.apply {
            replaceAnnotations(
                c.annotationDeserializer.loadPropertyGetterAnnotations(
                    c.containerSource, proto, local.nameResolver, local.typeTable, getterFlags
                )
            )
            containingClassForStaticMemberAttr = c.dispatchReceiver?.lookupTag
        }
    }

    private fun loadPropertySetter(
        proto: ProtoBuf.Property,
        classProto: ProtoBuf.Class? = null,
        classSymbol: FirClassSymbol<*>?,
        defaultAccessorFlags: Int,
        returnTypeRef: FirTypeRef,
        propertySymbol: FirPropertySymbol,
        local: FirDeserializationContext,
        propertyModality: Modality,
    ): FirPropertyAccessor {
        val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags
        val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))
        val accessorModality = ProtoEnumFlags.modality(Flags.MODALITY.get(setterFlags))
        val effectiveVisibility = visibility.toEffectiveVisibility(classSymbol)
        return if (Flags.IS_NOT_DEFAULT.get(setterFlags)) {
            buildPropertyAccessor {
                moduleData = c.moduleData
                origin = FirDeclarationOrigin.Library
                this.returnTypeRef = FirImplicitUnitTypeRef(source)
                resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
                isGetter = false
                status = FirResolvedDeclarationStatusImpl(visibility, accessorModality, effectiveVisibility).apply {
                    isInline = Flags.IS_INLINE_ACCESSOR.get(setterFlags)
                    isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(setterFlags)
                }
                this.symbol = FirPropertyAccessorSymbol()
                dispatchReceiverType = c.dispatchReceiver
                valueParameters += local.memberDeserializer.valueParameters(
                    listOf(proto.setterValueParameter),
                    symbol,
                    proto,
                    AbstractAnnotationDeserializer.CallableKind.PROPERTY_SETTER,
                    classProto
                )
                this.propertySymbol = propertySymbol
            }.apply {
                this.versionRequirements = VersionRequirement.create(proto, c)
            }
        } else {
            FirDefaultPropertySetter(
                null,
                c.moduleData,
                FirDeclarationOrigin.Library,
                returnTypeRef,
                visibility,
                propertySymbol,
                propertyModality,
                effectiveVisibility,
                resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES,
            )
        }.apply {
            replaceAnnotations(
                c.annotationDeserializer.loadPropertySetterAnnotations(
                    c.containerSource, proto, local.nameResolver, local.typeTable, setterFlags
                )
            )
            containingClassForStaticMemberAttr = c.dispatchReceiver?.lookupTag
        }
    }

    fun loadProperty(
        proto: ProtoBuf.Property,
        classProto: ProtoBuf.Class? = null,
        classSymbol: FirClassSymbol<*>? = null
    ): FirProperty {
        val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
        val callableName = c.nameResolver.getName(proto.name)
        val callableId = CallableId(c.packageFqName, c.relativeClassName, callableName)
        val symbol = FirPropertySymbol(callableId)
        val local = c.childContext(proto.typeParameterList, containingDeclarationSymbol = symbol)

        // Per documentation on Property.getter_flags in metadata.proto, if an accessor flags field is absent, its value should be computed
        // by taking hasAnnotations/visibility/modality from property flags, and using false for the rest
        val defaultAccessorFlags = Flags.getAccessorFlags(
            Flags.HAS_ANNOTATIONS.get(flags),
            Flags.VISIBILITY.get(flags),
            Flags.MODALITY.get(flags),
            false, false, false
        )

        val returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local)

        val hasGetter = Flags.HAS_GETTER.get(flags)
        val receiverAnnotations = if (hasGetter && proto.hasReceiver()) {
            c.annotationDeserializer.loadExtensionReceiverParameterAnnotations(
                c.containerSource, proto, local.nameResolver, local.typeTable, AbstractAnnotationDeserializer.CallableKind.PROPERTY_GETTER
            )
        } else {
            emptyList()
        }

        val propertyModality = ProtoEnumFlags.modality(Flags.MODALITY.get(flags))

        val isVar = Flags.IS_VAR.get(flags)
        val versionRequirements = VersionRequirement.create(proto, c)
        return buildProperty {
            moduleData = c.moduleData
            origin = FirDeclarationOrigin.Library
            this.returnTypeRef = returnTypeRef
            receiverParameter = proto.receiverType(c.typeTable)?.toTypeRef(local)?.let { receiverType ->
                buildReceiverParameter {
                    typeRef = receiverType
                    annotations += receiverAnnotations
                }
            }

            name = callableName
            this.isVar = isVar
            this.symbol = symbol
            dispatchReceiverType = c.dispatchReceiver
            isLocal = false
            val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags))
            status = FirResolvedDeclarationStatusImpl(visibility, propertyModality, visibility.toEffectiveVisibility(classSymbol)).apply {
                isExpect = Flags.IS_EXPECT_PROPERTY.get(flags)
                isActual = false
                isOverride = false
                isConst = Flags.IS_CONST.get(flags)
                isLateInit = Flags.IS_LATEINIT.get(flags)
                isExternal = Flags.IS_EXTERNAL_PROPERTY.get(flags)
            }

            resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
            typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
            annotations +=
                c.annotationDeserializer.loadPropertyAnnotations(c.containerSource, proto, classProto, local.nameResolver, local.typeTable)
            val backingFieldAnnotations = mutableListOf()
            backingFieldAnnotations +=
                c.annotationDeserializer.loadPropertyBackingFieldAnnotations(
                    c.containerSource, proto, local.nameResolver, local.typeTable
                )
            backingFieldAnnotations +=
                c.annotationDeserializer.loadPropertyDelegatedFieldAnnotations(
                    c.containerSource, proto, local.nameResolver, local.typeTable
                )
            backingField = FirDefaultPropertyBackingField(
                c.moduleData,
                FirDeclarationOrigin.Library,
                source = null,
                backingFieldAnnotations,
                returnTypeRef,
                isVar,
                symbol,
                status,
            )

            if (hasGetter) {
                this.getter = loadPropertyGetter(
                    proto,
                    classSymbol,
                    defaultAccessorFlags,
                    returnTypeRef,
                    symbol,
                    local,
                    propertyModality
                )
            }
            if (Flags.HAS_SETTER.get(flags)) {
                this.setter = loadPropertySetter(
                    proto,
                    classProto,
                    classSymbol,
                    defaultAccessorFlags,
                    returnTypeRef,
                    symbol,
                    local,
                    propertyModality
                )
            }
            this.containerSource = c.containerSource
            this.initializer = when {
                Flags.HAS_CONSTANT.get(proto.flags) -> {
                    c.constDeserializer.loadConstant(
                        proto, symbol.callableId, c.nameResolver, returnTypeRef.type.isUnsignedTypeOrNullableUnsignedType
                    )
                }
                // classSymbol?.classKind?.isAnnotationClass throws 'Fir is not initialized for FirRegularClassSymbol kotlin/String'
                classProto != null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.ANNOTATION_CLASS -> {
                    c.annotationDeserializer.loadAnnotationPropertyDefaultValue(
                        c.containerSource,
                        proto,
                        returnTypeRef,
                        local.nameResolver,
                        local.typeTable
                    )
                }
                else -> null
            }

            proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers) { loadContextReceiver(it, local) }
        }.apply {
            initializer?.replaceConeTypeOrNull(returnTypeRef.type)
            this.versionRequirements = versionRequirements
            replaceDeprecationsProvider(getDeprecationsProvider(c.session))
            setLazyPublishedVisibility(c.session)
            getter?.setLazyPublishedVisibility(annotations, this, c.session)
            setter?.setLazyPublishedVisibility(annotations, this, c.session)
        }
    }

    private fun loadContextReceiver(proto: ProtoBuf.Type, context: FirDeserializationContext): FirContextReceiver {
        val typeRef = proto.toTypeRef(context)
        return buildContextReceiver {
            val type = typeRef.coneType
            this.labelNameFromTypeRef = (type as? ConeLookupTagBasedType)?.lookupTag?.name
            this.typeRef = typeRef
        }
    }

    internal fun createContextReceiversForClass(classProto: ProtoBuf.Class): List =
        classProto.contextReceiverTypes(c.typeTable).map { loadContextReceiver(it, c) }

    fun loadFunction(
        proto: ProtoBuf.Function,
        classProto: ProtoBuf.Class? = null,
        classSymbol: FirClassSymbol<*>? = null,
        // TODO: introduce the similar changes for the other deserialized entities
        deserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
    ): FirSimpleFunction {
        val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)

        val receiverAnnotations = if (proto.hasReceiver()) {
            c.annotationDeserializer.loadExtensionReceiverParameterAnnotations(
                c.containerSource, proto, c.nameResolver, c.typeTable, AbstractAnnotationDeserializer.CallableKind.OTHERS
            )
        } else {
            emptyList()
        }

        val callableName = c.nameResolver.getName(proto.name)
        val callableId = CallableId(c.packageFqName, c.relativeClassName, callableName)
        val symbol = FirNamedFunctionSymbol(callableId)
        val local = c.childContext(proto.typeParameterList, containingDeclarationSymbol = symbol)

        val versionRequirements = VersionRequirement.create(proto, c)
        val simpleFunction = buildSimpleFunction {
            moduleData = c.moduleData
            origin = deserializationOrigin
            returnTypeRef = proto.returnType(local.typeTable).toTypeRef(local)
            receiverParameter = proto.receiverType(local.typeTable)?.toTypeRef(local)?.let { receiverType ->
                buildReceiverParameter {
                    typeRef = receiverType
                    annotations += receiverAnnotations
                }
            }

            name = callableName
            val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags))
            status = FirResolvedDeclarationStatusImpl(
                visibility,
                ProtoEnumFlags.modality(Flags.MODALITY.get(flags)),
                visibility.toEffectiveVisibility(classSymbol)
            ).apply {
                isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
                isActual = false
                isOverride = false
                isOperator = Flags.IS_OPERATOR.get(flags)
                isInfix = Flags.IS_INFIX.get(flags)
                isInline = Flags.IS_INLINE.get(flags)
                isTailRec = Flags.IS_TAILREC.get(flags)
                isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags)
                isSuspend = Flags.IS_SUSPEND.get(flags)
                hasStableParameterNames = !Flags.IS_FUNCTION_WITH_NON_STABLE_PARAMETER_NAMES.get(flags)
            }
            this.symbol = symbol
            dispatchReceiverType = c.dispatchReceiver
            resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
            typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
            valueParameters += local.memberDeserializer.valueParameters(
                proto.valueParameterList,
                symbol,
                proto,
                AbstractAnnotationDeserializer.CallableKind.OTHERS,
                classProto
            )
            annotations +=
                c.annotationDeserializer.loadFunctionAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
            deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(c.session, fromJava = false, versionRequirements)
            this.containerSource = c.containerSource

            proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers) { loadContextReceiver(it, local) }
        }.apply {
            this.versionRequirements = versionRequirements
            setLazyPublishedVisibility(c.session)
        }
        if (proto.hasContract()) {
            val contractDeserializer = if (proto.typeParameterList.isEmpty()) this.contractDeserializer else FirContractDeserializer(local)
            val contractDescription = contractDeserializer.loadContract(proto.contract, simpleFunction)
            if (contractDescription != null) {
                simpleFunction.replaceContractDescription(contractDescription)
            }
        }
        return simpleFunction
    }

    fun loadConstructor(
        proto: ProtoBuf.Constructor,
        classProto: ProtoBuf.Class,
        classBuilder: FirRegularClassBuilder
    ): FirConstructor {
        val flags = proto.flags
        val relativeClassName = c.relativeClassName!!
        val callableId = CallableId(c.packageFqName, relativeClassName, relativeClassName.shortName())
        val symbol = FirConstructorSymbol(callableId)
        val local = c.childContext(emptyList(), containingDeclarationSymbol = symbol)
        val isPrimary = !Flags.IS_SECONDARY.get(flags)

        val typeParameters = classBuilder.typeParameters

        val delegatedSelfType = buildResolvedTypeRef {
            type = ConeClassLikeTypeImpl(
                classBuilder.symbol.toLookupTag(),
                typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
                false
            )
        }

        return if (isPrimary) {
            FirPrimaryConstructorBuilder()
        } else {
            FirConstructorBuilder()
        }.apply {
            moduleData = c.moduleData
            origin = FirDeclarationOrigin.Library
            returnTypeRef = delegatedSelfType
            val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags))
            val isInner = classBuilder.status.isInner
            status = FirResolvedDeclarationStatusImpl(
                visibility,
                Modality.FINAL,
                visibility.toEffectiveVisibility(classBuilder.symbol)
            ).apply {
                // We don't store information about expect modifier on constructors
                // It is inherited from containing class
                isExpect = Flags.IS_EXPECT_CLASS.get(classProto.flags)
                hasStableParameterNames = !Flags.IS_CONSTRUCTOR_WITH_NON_STABLE_PARAMETER_NAMES.get(flags)
                isActual = false
                isOverride = false
                this.isInner = isInner
            }
            this.symbol = symbol
            dispatchReceiverType =
                if (!isInner) null
                else with(c) {
                    ClassId(packageFqName, relativeClassName.parent(), isLocal = false).defaultType(outerTypeParameters)
                }
            resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
            this.typeParameters +=
                typeParameters.filterIsInstance()
                    .map { buildConstructedClassTypeParameterRef { this.symbol = it.symbol } }
            valueParameters += local.memberDeserializer.valueParameters(
                proto.valueParameterList,
                symbol,
                proto,
                AbstractAnnotationDeserializer.CallableKind.OTHERS,
                classProto,
                addDefaultValue = classBuilder.symbol.classId == StandardClassIds.Enum
            )
            annotations +=
                c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
            containerSource = c.containerSource
            deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(c.session, fromJava = false)

            contextReceivers.addAll(createContextReceiversForClass(classProto))
        }.build().apply {
            containingClassForStaticMemberAttr = c.dispatchReceiver!!.lookupTag
            this.versionRequirements = VersionRequirement.create(proto, c)
            setLazyPublishedVisibility(c.session)
        }
    }

    private fun defaultValue(flags: Int): FirExpression? {
        if (Flags.DECLARES_DEFAULT_VALUE.get(flags)) {
            return buildExpressionStub()
        }
        return null
    }

    private fun valueParameters(
        valueParameters: List,
        functionSymbol: FirFunctionSymbol<*>,
        callableProto: MessageLite,
        callableKind: AbstractAnnotationDeserializer.CallableKind,
        classProto: ProtoBuf.Class?,
        addDefaultValue: Boolean = false
    ): List {
        return valueParameters.mapIndexed { index, proto ->
            val flags = if (proto.hasFlags()) proto.flags else 0
            val name = c.nameResolver.getName(proto.name)
            buildValueParameter {
                moduleData = c.moduleData
                this.containingFunctionSymbol = functionSymbol
                origin = FirDeclarationOrigin.Library
                returnTypeRef = proto.type(c.typeTable).toTypeRef(c)
                this.name = name
                symbol = FirValueParameterSymbol(name)
                resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
                defaultValue = defaultValue(flags)
                if (addDefaultValue) {
                    defaultValue = buildExpressionStub()
                }
                isCrossinline = Flags.IS_CROSSINLINE.get(flags)
                isNoinline = Flags.IS_NOINLINE.get(flags)
                isVararg = proto.varargElementType(c.typeTable) != null
                annotations += c.annotationDeserializer.loadValueParameterAnnotations(
                    c.containerSource,
                    callableProto,
                    proto,
                    classProto,
                    c.nameResolver,
                    c.typeTable,
                    callableKind,
                    index,
                )
            }
        }.toList()
    }

    private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirResolvedTypeRef =
        context.typeDeserializer.typeRef(this)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy