FIR deserializer: load annotations for property and fields, along with use-site targets

This commit is contained in:
Jinseong Jeon
2020-06-19 01:18:04 -07:00
committed by Denis Zharkov
parent 3580c7c28c
commit 34174d6e7d
16 changed files with 163 additions and 39 deletions
+16 -16
View File
@@ -208,10 +208,10 @@ public final class Byte : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Byte>|, R
public final const val MIN_VALUE: R|kotlin/Byte| = Byte(-128)
public get(): R|kotlin/Byte|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(8)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(8)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(1)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Byte.Companion|
@@ -279,7 +279,7 @@ public final class Char : R|kotlin/Comparable<kotlin/Char>|, R|java/io/Serializa
public final const val MAX_SURROGATE: R|kotlin/Char| = Char(57343)
public get(): R|kotlin/Char|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val MAX_VALUE: R|kotlin/Char| = Char(65535)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val MAX_VALUE: R|kotlin/Char| = Char(65535)
public get(): R|kotlin/Char|
public final const val MIN_HIGH_SURROGATE: R|kotlin/Char| = Char(55296)
@@ -291,13 +291,13 @@ public final class Char : R|kotlin/Comparable<kotlin/Char>|, R|java/io/Serializa
public final const val MIN_SURROGATE: R|kotlin/Char| = Char(55296)
public get(): R|kotlin/Char|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val MIN_VALUE: R|kotlin/Char| = Char(0)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val MIN_VALUE: R|kotlin/Char| = Char(0)
public get(): R|kotlin/Char|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(16)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(16)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(2)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(2)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Char.Companion|
@@ -499,10 +499,10 @@ public final class Double : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Double>
public final const val POSITIVE_INFINITY: R|kotlin/Double| = Double(Infinity)
public get(): R|kotlin/Double|
@R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BITS: R|kotlin/Int| = Int(64)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BITS: R|kotlin/Int| = Int(64)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(8)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(8)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Double.Companion|
@@ -678,10 +678,10 @@ public final class Float : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Float>|,
public final const val POSITIVE_INFINITY: R|kotlin/Float| = Float(Infinity)
public get(): R|kotlin/Float|
@R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BITS: R|kotlin/Int| = Int(32)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BITS: R|kotlin/Int| = Int(32)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(4)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.4)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(4)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Float.Companion|
@@ -837,10 +837,10 @@ public final class Int : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Int>|, R|j
public final const val MIN_VALUE: R|kotlin/Int| = Int(-2147483648)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(32)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(32)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(4)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(4)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Int.Companion|
@@ -993,10 +993,10 @@ public final class Long : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Long>|, R
public final const val MIN_VALUE: R|kotlin/Long| = Long(-9223372036854775808)
public get(): R|kotlin/Long|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(64)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(64)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(8)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(8)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Long.Companion|
@@ -1183,10 +1183,10 @@ public final class Short : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Short>|,
public final const val MIN_VALUE: R|kotlin/Short| = Short(-32768)
public get(): R|kotlin/Short|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(16)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BITS: R|kotlin/Int| = Int(16)
public get(): R|kotlin/Int|
@R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(2)
@PROPERTY:R|kotlin/SinceKotlin|(version = String(1.3)) public final const val SIZE_BYTES: R|kotlin/Int| = Int(2)
public get(): R|kotlin/Int|
private constructor(): R|kotlin/Short.Companion|
@@ -7,7 +7,7 @@ public final class Class : R|kotlin/Any| {
public constructor(): R|test/Class|
public final companion object Companion : R|kotlin/Any| {
public final var property: R|kotlin/Int|
@FIELD:R|test/Anno|() public final var property: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
}
public final class Class : R|kotlin/Any| {
public final val x: R|kotlin/Int|
@PROPERTY:R|test/Anno|() public final val x: R|kotlin/Int|
public get(): R|kotlin/Int|
public constructor(): R|test/Class|
@@ -9,7 +9,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
public final class Class : R|kotlin/Any| {
@R|test/Anno|(t = R|java/lang/annotation/ElementType.METHOD|()) public final fun foo(): R|kotlin/Unit|
public final var bar: R|kotlin/Int|
@FIELD:R|test/Anno|(t = R|java/lang/annotation/ElementType.FIELD|()) public final var bar: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
}
public final class Class : R|kotlin/Any| {
public final var property: R|kotlin/Int|
@FIELD:R|test/Anno|() public final var property: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
}
public final class Class : R|kotlin/Any| {
public final val property: R|kotlin/Int|
@PROPERTY:R|test/Anno|() public final val property: R|kotlin/Int|
public get(): R|kotlin/Int|
public constructor(): R|test/Class|
@@ -1,11 +1,11 @@
public final class Class : R|kotlin/Any| {
public final val R|kotlin/Double|.extension: R|kotlin/Int|
@PROPERTY:R|test/DoubleAnno|() public final val R|kotlin/Double|.extension: R|kotlin/Int|
public get(): R|kotlin/Int|
public final val R|kotlin/Int|.extension: R|kotlin/Int|
@PROPERTY:R|test/IntAnno|() public final val R|kotlin/Int|.extension: R|kotlin/Int|
public get(): R|kotlin/Int|
public final val R|kotlin/String|.extension: R|kotlin/String|
@PROPERTY:R|test/StringAnno|() public final val R|kotlin/String|.extension: R|kotlin/String|
public get(): R|kotlin/String|
public constructor(): R|test/Class|
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
}
public final class Class : R|kotlin/Any| {
public final val property: R|kotlin/String|
@PROPERTY_DELEGATE_FIELD:R|test/Anno|() public final val property: R|kotlin/String|
public get(): R|kotlin/String|
public constructor(): R|test/Class|
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
}
public final class Class : R|kotlin/Any| {
public final var property: R|kotlin/Int|
@FIELD:R|test/Anno|() public final var property: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@@ -6,11 +6,14 @@
package org.jetbrains.kotlin.fir.java.deserialization
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.MemberSignature
import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -23,7 +26,6 @@ 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
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class JvmBinaryAnnotationDeserializer(
@@ -60,6 +62,63 @@ class JvmBinaryAnnotationDeserializer(
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
}
override fun loadPropertyAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
val signature = getPropertySignature(propertyProto, nameResolver, typeTable, synthetic = true) ?: return emptyList()
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature).map {
buildAnnotationCall {
annotationTypeRef = it.annotationTypeRef
argumentList = it.argumentList
useSiteTarget = AnnotationUseSiteTarget.PROPERTY
}
}
}
private val MemberSignature.isDelegated: Boolean
get() = JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX in this.signature
override fun loadPropertyBackingFieldAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
val signature = getPropertySignature(propertyProto, nameResolver, typeTable, field = true) ?: return emptyList()
if (signature.isDelegated) {
return emptyList()
}
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature).map {
buildAnnotationCall {
annotationTypeRef = it.annotationTypeRef
argumentList = it.argumentList
useSiteTarget = AnnotationUseSiteTarget.FIELD
}
}
}
override fun loadPropertyDelegatedFieldAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
val signature = getPropertySignature(propertyProto, nameResolver, typeTable, field = true) ?: return emptyList()
if (!signature.isDelegated) {
return emptyList()
}
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature).map {
buildAnnotationCall {
annotationTypeRef = it.annotationTypeRef
argumentList = it.argumentList
useSiteTarget = AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}
}
}
override fun loadPropertyGetterAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
@@ -116,7 +175,8 @@ class JvmBinaryAnnotationDeserializer(
proto: MessageLite,
nameResolver: NameResolver,
typeTable: TypeTable,
kind: CallableKind = CallableKind.OTHERS
kind: CallableKind = CallableKind.OTHERS,
requireHasFieldFlagForField: Boolean = false
): MemberSignature? {
return when (proto) {
is ProtoBuf.Constructor -> {
@@ -135,7 +195,12 @@ class JvmBinaryAnnotationDeserializer(
if (signature.hasGetter()) MemberSignature.fromMethod(nameResolver, signature.getter) else null
CallableKind.PROPERTY_SETTER ->
if (signature.hasSetter()) MemberSignature.fromMethod(nameResolver, signature.setter) else null
// TODO: PROPERTY
CallableKind.PROPERTY ->
getPropertySignature(
proto, nameResolver, typeTable,
field = true,
requireHasFieldFlagForField = requireHasFieldFlagForField
)
else ->
null
}
@@ -144,6 +209,27 @@ class JvmBinaryAnnotationDeserializer(
}
}
private fun getPropertySignature(
proto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable,
field: Boolean = false,
synthetic: Boolean = false,
requireHasFieldFlagForField: Boolean = true
): MemberSignature? {
val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature) ?: return null
if (field) {
val fieldSignature =
JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable, requireHasFieldFlagForField) ?: return null
return MemberSignature.fromJvmMemberSignature(fieldSignature)
} else if (synthetic && signature.hasSyntheticMethod()) {
return MemberSignature.fromMethod(nameResolver, signature.syntheticMethod)
}
return null
}
private fun findJvmBinaryClassAndLoadMemberAnnotations(
containerSource: DeserializedContainerSource?,
memberSignature: MemberSignature
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.deserialization
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
@@ -43,6 +44,7 @@ abstract class AbstractAnnotationDeserializer(
protected val protocol = BuiltInSerializerProtocol
enum class CallableKind {
PROPERTY,
PROPERTY_GETTER,
PROPERTY_SETTER,
OTHERS
@@ -65,10 +67,33 @@ abstract class AbstractAnnotationDeserializer(
return annotations.map { deserializeAnnotation(it, nameResolver) }
}
fun loadPropertyAnnotations(propertyProto: ProtoBuf.Property, nameResolver: NameResolver): List<FirAnnotationCall> {
open fun loadPropertyAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(propertyProto.flags)) return emptyList()
val annotations = propertyProto.getExtension(protocol.propertyAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it, nameResolver) }
return annotations.map { deserializeAnnotation(it, nameResolver, AnnotationUseSiteTarget.PROPERTY) }
}
open fun loadPropertyBackingFieldAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
return emptyList()
}
open fun loadPropertyDelegatedFieldAnnotations(
containerSource: DeserializedContainerSource?,
propertyProto: ProtoBuf.Property,
nameResolver: NameResolver,
typeTable: TypeTable
): List<FirAnnotationCall> {
return emptyList()
}
open fun loadPropertyGetterAnnotations(
@@ -80,7 +105,7 @@ abstract class AbstractAnnotationDeserializer(
): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(getterFlags)) return emptyList()
val annotations = propertyProto.getExtension(protocol.propertyGetterAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it, nameResolver) }
return annotations.map { deserializeAnnotation(it, nameResolver, AnnotationUseSiteTarget.PROPERTY_GETTER) }
}
open fun loadPropertySetterAnnotations(
@@ -92,7 +117,7 @@ abstract class AbstractAnnotationDeserializer(
): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(setterFlags)) return emptyList()
val annotations = propertyProto.getExtension(protocol.propertySetterAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it, nameResolver) }
return annotations.map { deserializeAnnotation(it, nameResolver, AnnotationUseSiteTarget.PROPERTY_SETTER) }
}
open fun loadConstructorAnnotations(
@@ -122,7 +147,11 @@ abstract class AbstractAnnotationDeserializer(
abstract fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotationCall>
fun deserializeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): FirAnnotationCall {
fun deserializeAnnotation(
proto: ProtoBuf.Annotation,
nameResolver: NameResolver,
useSiteTarget: AnnotationUseSiteTarget? = null
): FirAnnotationCall {
val classId = nameResolver.getClassId(proto.id)
val lookupTag = ConeClassLikeLookupTagImpl(classId)
val symbol = lookupTag.toSymbol(session)
@@ -156,6 +185,9 @@ abstract class AbstractAnnotationDeserializer(
argumentList = buildArgumentList {
this.arguments += arguments
}
useSiteTarget?.let {
this.useSiteTarget = it
}
}
}
@@ -270,7 +270,16 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
annotations += c.annotationDeserializer.loadPropertyAnnotations(proto, local.nameResolver)
annotations +=
c.annotationDeserializer.loadPropertyAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
annotations +=
c.annotationDeserializer.loadPropertyBackingFieldAnnotations(
c.containerSource, proto, local.nameResolver, local.typeTable
)
annotations +=
c.annotationDeserializer.loadPropertyDelegatedFieldAnnotations(
c.containerSource, proto, local.nameResolver, local.typeTable
)
this.getter = getter
this.setter = setter
this.containerSource = c.containerSource
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TODO: investigate should it be ran for JS or not
// TARGET_BACKEND: JVM
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TODO: investigate should it be ran for JS or not
// TARGET_BACKEND: JVM
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature
// The purpose of this class is to hold a unique signature of either a method or a field, so that annotations on a member can be put
// into a map indexed by these signatures
@Suppress("DataClassPrivateConstructor")
data class MemberSignature private constructor(internal val signature: String) {
data class MemberSignature private constructor(val signature: String) {
companion object {
@JvmStatic
fun fromMethod(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): MemberSignature {