FIR deserializer: signature-aware annotation loading for functions

This commit is contained in:
Jinseong Jeon
2020-06-11 12:56:49 -07:00
committed by Denis Zharkov
parent 11a680d7d8
commit b076bec07f
32 changed files with 68 additions and 42 deletions
@@ -17,8 +17,10 @@ import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
import org.jetbrains.kotlin.load.kotlin.MemberSignature
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.protobuf.MessageLite
@@ -33,6 +35,7 @@ class JvmBinaryAnnotationDeserializer(
private data class MemberAnnotations(val memberAnnotations: Map<MemberSignature, MutableList<FirAnnotationCall>>)
private enum class CallableKind {
FUNCTION,
PROPERTY_GETTER,
PROPERTY_SETTER
}
@@ -42,36 +45,55 @@ class JvmBinaryAnnotationDeserializer(
return annotations.map { deserializeAnnotation(it, nameResolver) }
}
override fun loadFunctionAnnotations(
containerSource: DeserializedContainerSource?,
functionProto: ProtoBuf.Function,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
val signature = getCallableSignature(functionProto, nameResolver, typeTable, CallableKind.FUNCTION) ?: return emptyList()
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
}
override fun loadPropertyGetterAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable,
getterFlags: Int
): List<FirAnnotationCall> {
val signature = getCallableSignature(propertyProto, nameResolver, CallableKind.PROPERTY_GETTER) ?: return emptyList()
val kotlinClass = containerSource?.toKotlinJvmBinaryClass() ?: return emptyList()
return loadMemberAnnotations(kotlinClass).memberAnnotations[signature] ?: emptyList()
val signature = getCallableSignature(propertyProto, nameResolver, typeTable, CallableKind.PROPERTY_GETTER) ?: return emptyList()
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
}
override fun loadPropertySetterAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable,
setterFlags: Int
): List<FirAnnotationCall> {
val signature = getCallableSignature(propertyProto, nameResolver, CallableKind.PROPERTY_SETTER) ?: return emptyList()
val kotlinClass = containerSource?.toKotlinJvmBinaryClass() ?: return emptyList()
return loadMemberAnnotations(kotlinClass).memberAnnotations[signature] ?: emptyList()
val signature = getCallableSignature(propertyProto, nameResolver, typeTable, CallableKind.PROPERTY_SETTER) ?: return emptyList()
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
}
private fun getCallableSignature(
proto: MessageLite,
nameResolver: NameResolver,
typeTable: TypeTable,
kind: CallableKind
): MemberSignature? {
return when (proto) {
// TODO: ProtoBuf.Constructor
// TODO: ProtoBuf.Function
is ProtoBuf.Function -> {
val signature = JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable) ?: return null
// TODO: Investigate why annotations for accessors affect resolution, resulting in dangling type parameter.
// regressions: Fir2IrTextTest.Declarations.test*LevelProperties
if (signature.name.startsWith("get") || signature.name.startsWith("set")) {
return null
}
MemberSignature.fromJvmMemberSignature(signature)
}
is ProtoBuf.Property -> {
val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature) ?: return null
when (kind) {
@@ -80,12 +102,22 @@ class JvmBinaryAnnotationDeserializer(
CallableKind.PROPERTY_SETTER ->
if (signature.hasSetter()) MemberSignature.fromMethod(nameResolver, signature.setter) else null
// TODO: PROPERTY
else ->
null
}
}
else -> null
}
}
private fun findJvmBinaryClassAndLoadMemberAnnotations(
containerSource: DeserializedContainerSource?,
memberSignature: MemberSignature
): List<FirAnnotationCall> {
val kotlinClass = containerSource?.toKotlinJvmBinaryClass() ?: return emptyList()
return loadMemberAnnotations(kotlinClass).memberAnnotations[memberSignature] ?: emptyList()
}
private fun DeserializedContainerSource.toKotlinJvmBinaryClass(): KotlinJvmBinaryClass? =
when (this) {
is JvmPackagePartSource -> this.knownJvmBinaryClass