fun loadProperty()

in compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt [358:566]


    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 = FirRegularPropertySymbol(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, 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)

        // classSymbol?.classKind?.isAnnotationClass throws 'Fir is not initialized for FirRegularClassSymbol kotlin/String'
        val isFromAnnotation = classProto != null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.ANNOTATION_CLASS
        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
                    this.symbol = FirReceiverParameterSymbol()
                    this.moduleData = c.moduleData
                    this.origin = FirDeclarationOrigin.Library
                    containingDeclarationSymbol = symbol
                }
            }

            name = callableName
            this.isVar = isVar
            this.symbol = symbol
            dispatchReceiverType = c.dispatchReceiver
            val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags))
            status = FirResolvedDeclarationStatusWithLazyEffectiveVisibility(
                visibility,
                propertyModality,
                visibility.toLazyEffectiveVisibility(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)
                returnValueStatus = ProtoEnumFlags.returnValueStatus(Flags.RETURN_VALUE_STATUS_PROPERTY.get(flags))
            }
            isLocal = false

            resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
            typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
            if (!isFromAnnotation || c.session.deserializationExtension?.isLoadingOfAnnotationsOnAnnotationPropertiesEnabled != false) {
                annotations += c.annotationDeserializer.loadPropertyAnnotations(
                    c.containerSource, proto, classProto, local.nameResolver, local.typeTable
                )
            }
            val backingFieldAnnotations = mutableListOf<FirAnnotation>()
            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.coneType.isUnsignedTypeOrNullableUnsignedType
                    )
                }

                isFromAnnotation -> {
                    c.annotationDeserializer.loadAnnotationPropertyDefaultValue(
                        c.containerSource,
                        proto,
                        returnTypeRef,
                        local.nameResolver,
                        local.typeTable
                    )
                }
                else -> null
            }

            local.memberDeserializer.loadContextParametersTo(
                proto.contextParameterList,
                proto.contextReceiverTypes(c.typeTable),
                symbol,
                proto,
                callableKind = CallableKind.PROPERTY_GETTER,
                classProto,
                deserializationOrigin = FirDeclarationOrigin.Library,
                destination = contextParameters,
            )
        }.apply {
            when (val initializer = initializer) {
                /**
                 * Deserialized annotation values don't have any information about type arguments for annotation expression, so
                 *   they should be updated from the expected type
                 *
                 * ```
                 * annotation class One<T>(val s: String)
                 *
                 * annotation class Two(
                 *     val one: One<Int> = One("hello") // <--------
                 * )
                 * ```
                 *
                 * Annotation value for `One("hello")` contains only annotation type (`One`) and argument values (`"hello"`)
                 */
                is FirAnnotation -> initializer.replaceAnnotationTypeRef(initializer.annotationTypeRef.withReplacedReturnType(returnTypeRef.coneType))
                else -> initializer?.replaceConeTypeOrNull(returnTypeRef.coneType)
            }
            this.versionRequirements = versionRequirements
            c.session.deserializationExtension?.loadHasBackingFieldFlag(proto)?.let { hasBackingField ->
                @OptIn(FirImplementationDetail::class)
                hasBackingFieldAttr = hasBackingField
            }

            if (Flags.IS_DELEGATED[proto.flags]) {
                @OptIn(FirImplementationDetail::class)
                isDelegatedPropertyAttr = true
            }

            if (isFromAnnotation) {
                isDeserializedPropertyFromAnnotation = true
            }

            replaceDeprecationsProvider(getDeprecationsProvider(c.session))
            deserializeCompilerPluginMetadata(c, proto, ProtoBuf.Property::getCompilerPluginDataList)
            setLazyPublishedVisibility(c.session)
            getter?.setLazyPublishedVisibility(annotations, this, c.session)
            setter?.setLazyPublishedVisibility(annotations, this, c.session)
            // Contract deserialization needs access to the property FIR, therefore these contracts deserialized after building the property
            getter?.let {
                if (proto.hasGetterContract()) {
                    contractDeserializer.loadContract(proto.getterContract, it)?.let { contract ->
                        it.replaceContractDescription(contract)
                    }
                }
            }
            setter?.let {
                if (proto.hasSetterContract()) {
                    contractDeserializer.loadContract(proto.setterContract, it)?.let { contract ->
                        it.replaceContractDescription(contract)
                    }
                }
            }
        }
    }