FIR deserializer: build property accessors if non-default ones exist
This commit is contained in:
committed by
Mikhail Glukhikh
parent
369c08214b
commit
2d55b8db07
+20
@@ -56,6 +56,26 @@ abstract class AbstractAnnotationDeserializer(
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
fun loadPropertyGetterAnnotations(
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
getterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(getterFlags)) return emptyList()
|
||||
val annotations = propertyProto.getExtension(protocol.propertyGetterAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
fun loadPropertySetterAnnotations(
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
setterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(setterFlags)) return emptyList()
|
||||
val annotations = propertyProto.getExtension(protocol.propertySetterAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
fun loadConstructorAnnotations(constructorProto: ProtoBuf.Constructor, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(constructorProto.flags)) return emptyList()
|
||||
val annotations = constructorProto.getExtension(protocol.constructorAnnotation).orEmpty()
|
||||
|
||||
+71
-8
@@ -20,15 +20,16 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
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.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
|
||||
class FirDeserializationContext(
|
||||
val nameResolver: NameResolver,
|
||||
@@ -172,13 +173,77 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
val symbol = FirPropertySymbol(CallableId(c.packageFqName, c.relativeClassName, callableName))
|
||||
val local = c.childContext(proto.typeParameterList)
|
||||
|
||||
val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else flags
|
||||
val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else flags
|
||||
// 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 getter = if (Flags.HAS_GETTER.get(flags)) {
|
||||
val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags
|
||||
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(getterFlags))
|
||||
if (Flags.IS_NOT_DEFAULT.get(getterFlags)) {
|
||||
buildPropertyAccessor {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.returnTypeRef = returnTypeRef
|
||||
isGetter = true
|
||||
status = FirDeclarationStatusImpl(visibility, modality)
|
||||
annotations += c.annotationDeserializer.loadPropertyGetterAnnotations(proto, local.nameResolver, getterFlags)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
}
|
||||
} else {
|
||||
FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val setter = if (Flags.HAS_SETTER.get(flags)) {
|
||||
val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags
|
||||
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(setterFlags))
|
||||
if (Flags.IS_NOT_DEFAULT.get(setterFlags)) {
|
||||
buildPropertyAccessor {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.returnTypeRef = FirImplicitUnitTypeRef(source)
|
||||
isGetter = false
|
||||
status = FirDeclarationStatusImpl(visibility, modality)
|
||||
annotations += c.annotationDeserializer.loadPropertySetterAnnotations(proto, local.nameResolver, setterFlags)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
valueParameters += proto.setterValueParameter.let {
|
||||
val parameterFlags = if (it.hasFlags()) it.flags else 0
|
||||
buildValueParameter {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.returnTypeRef = returnTypeRef
|
||||
name = if (it.hasName()) c.nameResolver.getName(it.name) else Name.special("<default-setter-parameter>")
|
||||
this.symbol = FirVariableSymbol(CallableId(FqName.ROOT, name))
|
||||
isCrossinline = Flags.IS_CROSSINLINE.get(parameterFlags)
|
||||
isNoinline = Flags.IS_NOINLINE.get(parameterFlags)
|
||||
isVararg = it.hasVarargElementType()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val isVar = Flags.IS_VAR.get(flags)
|
||||
return buildProperty {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local)
|
||||
this.returnTypeRef = returnTypeRef
|
||||
receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local)
|
||||
name = callableName
|
||||
this.isVar = isVar
|
||||
@@ -198,10 +263,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
annotations += c.annotationDeserializer.loadPropertyAnnotations(proto, local.nameResolver)
|
||||
getter = FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags)))
|
||||
setter = if (isVar) {
|
||||
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags)))
|
||||
} else null
|
||||
this.getter = getter
|
||||
this.setter = setter
|
||||
this.containerSource = c.containerSource
|
||||
this.initializer = if (Flags.HAS_CONSTANT.get(flags)) {
|
||||
proto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue)?.let {
|
||||
|
||||
Reference in New Issue
Block a user