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)
}
}
}
}
}