diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt index c2c9d357dfb..811d5d2210c 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt @@ -1,10 +1,10 @@ public final class A : R|kotlin/Any| { - public final fun R|kotlin/String|.myLength(@R|test/Ann|() q: R|kotlin/String|): R|kotlin/Int| + @R|test/Ann|() public final fun R|kotlin/String|.myLength(@R|test/Ann|() q: R|kotlin/String|): R|kotlin/Int| - public final val R|kotlin/String|.myLength2: R|kotlin/Int| + @R|test/Ann|() public final val R|kotlin/String|.myLength2: R|kotlin/Int| public get(): R|kotlin/Int| - public final var R|kotlin/String|.myLength3: R|kotlin/Int| + @R|test/Ann|() public final var R|kotlin/String|.myLength3: R|kotlin/Int| public get(): R|kotlin/Int| public set(v: R|kotlin/Int|): R|kotlin/Unit| diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt index bde6b457105..5f70793efee 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt @@ -160,6 +160,18 @@ class JvmBinaryAnnotationDeserializer( return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, paramSignature) } + override fun loadExtensionReceiverParameterAnnotations( + containerSource: DeserializedContainerSource?, + callableProto: MessageLite, + nameResolver: NameResolver, + typeTable: TypeTable, + kind: CallableKind + ): List { + val methodSignature = getCallableSignature(callableProto, nameResolver, typeTable, kind) ?: return emptyList() + val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, 0) + return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, paramSignature) + } + private fun computeJvmParameterIndexShift(classProto: ProtoBuf.Class?, message: MessageLite): Int { return when (message) { is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0 diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt index 14a3fe89d76..00e8a1b07c2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt @@ -148,6 +148,16 @@ abstract class AbstractAnnotationDeserializer( return annotations.map { deserializeAnnotation(it, nameResolver) } } + open fun loadExtensionReceiverParameterAnnotations( + containerSource: DeserializedContainerSource?, + callableProto: MessageLite, + nameResolver: NameResolver, + typeTable: TypeTable, + kind: CallableKind + ): List { + return emptyList() + } + abstract fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List fun deserializeAnnotation( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt index b3b7529e4eb..971f953602d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt @@ -195,7 +195,16 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { val returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local) - val getter = if (Flags.HAS_GETTER.get(flags)) { + val hasGetter = Flags.HAS_GETTER.get(flags) + val receiverAnnotations = if (hasGetter && proto.hasReceiver()) { + c.annotationDeserializer.loadExtensionReceiverParameterAnnotations( + c.containerSource, proto, local.nameResolver, local.typeTable, AbstractAnnotationDeserializer.CallableKind.PROPERTY_GETTER + ) + } else { + emptyList() + } + + val getter = if (hasGetter) { 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)) @@ -254,7 +263,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { session = c.session origin = FirDeclarationOrigin.Library this.returnTypeRef = returnTypeRef - receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local) + receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local).apply { + annotations += receiverAnnotations + } name = callableName this.isVar = isVar this.symbol = symbol @@ -292,9 +303,13 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { fun loadFunction(proto: ProtoBuf.Function, classProto: ProtoBuf.Class? = null): FirSimpleFunction { val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags) - val receiverAnnotations = - // TODO: support annotations - Annotations.EMPTY + val receiverAnnotations = if (proto.hasReceiver()) { + c.annotationDeserializer.loadExtensionReceiverParameterAnnotations( + c.containerSource, proto, c.nameResolver, c.typeTable, AbstractAnnotationDeserializer.CallableKind.OTHERS + ) + } else { + emptyList() + } val versionRequirementTable = // TODO: Support case for KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME @@ -309,7 +324,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { session = c.session origin = FirDeclarationOrigin.Library returnTypeRef = proto.returnType(local.typeTable).toTypeRef(local) - receiverTypeRef = proto.receiverType(local.typeTable)?.toTypeRef(local) + receiverTypeRef = proto.receiverType(local.typeTable)?.toTypeRef(local).apply { + annotations += receiverAnnotations + } name = callableName status = FirDeclarationStatusImpl( ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),