FIR deserializer: signature-aware annotation loading for functions
This commit is contained in:
committed by
Denis Zharkov
parent
11a680d7d8
commit
b076bec07f
+1
-1
@@ -1,5 +1,5 @@
|
||||
public open class AnnotatedMethod : R|kotlin/Any| {
|
||||
public open fun f(): R|kotlin/Unit|
|
||||
@R|kotlin/Deprecated|(message = String(Deprecated in Java)) public open fun f(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/AnnotatedMethod|
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ public final annotation class EnumAnno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class EnumArgumentWithCustomToString : R|kotlin/Any| {
|
||||
public final fun annotated(): R|kotlin/Unit|
|
||||
@R|test/EnumAnno|(value = R|test/E.CAKE|()) @R|test/EnumArrayAnno|(value = <implicitArrayOf>(R|test/E.CAKE|(), R|test/E.CAKE|())) public final fun annotated(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/EnumArgumentWithCustomToString|
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public abstract interface T : R|kotlin/Any| {
|
||||
public abstract fun foo(): R|kotlin/Array<kotlin/Array<kotlin/Array<test/T>>>|
|
||||
@R|test/Anno|(s = String(foo)) public abstract fun foo(): R|kotlin/Array<kotlin/Array<kotlin/Array<test/T>>>|
|
||||
|
||||
public abstract val bar: R|kotlin/Array<kotlin/Array<kotlin/BooleanArray>>|
|
||||
public get(): R|kotlin/Array<kotlin/Array<kotlin/BooleanArray>>|
|
||||
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class Class : R|kotlin/Any| {
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = R|java/lang/annotation/ElementType.METHOD|()) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final var bar: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class Class : R|kotlin/Any| {
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|() public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/Class|
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ public final class A : R|kotlin/Any| {
|
||||
}
|
||||
|
||||
@R|test/A.Anno|() public final class B : R|kotlin/Any| {
|
||||
public final fun f(): R|kotlin/Unit|
|
||||
@R|test/A.Anno|() public final fun f(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/B|
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = R|java/lang/annotation/ElementType.METHOD|()) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final val t: R|java/lang/annotation/ElementType|
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
public final fun baz(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>()) public final fun baz(): R|kotlin/Unit|
|
||||
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.FIELD|())) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final val t: R|kotlin/Array<out java/lang/annotation/ElementType>|
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
public final fun function(): R|kotlin/Unit|
|
||||
@R|test/Anno|() public final fun function(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public constructor(): R|test/Anno|
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
public final fun baz(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>()) public final fun baz(): R|kotlin/Unit|
|
||||
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>(String(live), String(long))) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final val t: R|kotlin/Array<out kotlin/String>|
|
||||
|
||||
+39
-7
@@ -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
|
||||
|
||||
+9
-1
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value.Type.*
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
@@ -45,7 +46,12 @@ abstract class AbstractAnnotationDeserializer(
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
fun loadFunctionAnnotations(functionProto: ProtoBuf.Function, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
open fun loadFunctionAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
functionProto: ProtoBuf.Function,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(functionProto.flags)) return emptyList()
|
||||
val annotations = functionProto.getExtension(protocol.functionAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
@@ -61,6 +67,7 @@ abstract class AbstractAnnotationDeserializer(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
getterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(getterFlags)) return emptyList()
|
||||
@@ -72,6 +79,7 @@ abstract class AbstractAnnotationDeserializer(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
setterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(setterFlags)) return emptyList()
|
||||
|
||||
+8
-3
@@ -196,7 +196,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
isGetter = true
|
||||
status = FirDeclarationStatusImpl(visibility, modality)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertyGetterAnnotations(c.containerSource, proto, local.nameResolver, getterFlags)
|
||||
c.annotationDeserializer.loadPropertyGetterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, getterFlags
|
||||
)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
}
|
||||
} else {
|
||||
@@ -218,7 +220,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
isGetter = false
|
||||
status = FirDeclarationStatusImpl(visibility, modality)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertySetterAnnotations(c.containerSource, proto, local.nameResolver, setterFlags)
|
||||
c.annotationDeserializer.loadPropertySetterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, setterFlags
|
||||
)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
valueParameters += proto.setterValueParameter.let {
|
||||
val parameterFlags = if (it.hasFlags()) it.flags else 0
|
||||
@@ -316,7 +320,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
valueParameters += local.memberDeserializer.valueParameters(proto.valueParameterList)
|
||||
annotations += local.annotationDeserializer.loadFunctionAnnotations(proto, local.nameResolver)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadFunctionAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
this.containerSource = c.containerSource
|
||||
}
|
||||
if (proto.hasContract()) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
fun foo(): Array<Boolean> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
fun foo(): Array<Boolean> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun inInt(x: Long): Boolean {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
Reference in New Issue
Block a user