Deserialize receiver parameter annotations for extension functions

This commit is contained in:
Yan Zhulanow
2015-08-03 21:10:41 +03:00
parent 397da8746a
commit 08c678ef46
12 changed files with 184 additions and 11 deletions
@@ -47,6 +47,14 @@ public interface AnnotationAndConstantLoader<A, C> {
@NotNull ProtoBuf.Callable.ValueParameter proto
);
@NotNull
List<A> loadExtensionReceiverParameterAnnotations(
@NotNull ProtoContainer container,
@NotNull ProtoBuf.Callable callable,
@NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind
);
@NotNull
List<A> loadTypeAnnotations(
@NotNull ProtoBuf.Type type,
@@ -17,6 +17,9 @@
package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
@@ -29,6 +32,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.Callable.CallableKind.VAL
import org.jetbrains.kotlin.serialization.ProtoBuf.Callable.CallableKind.VAR
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
import org.jetbrains.kotlin.utils.toReadOnlyList
import org.jetbrains.kotlin.utils.sure
public class MemberDeserializer(private val c: DeserializationContext) {
public fun loadCallable(proto: Callable): CallableMemberDescriptor {
@@ -43,9 +47,16 @@ public class MemberDeserializer(private val c: DeserializationContext) {
private fun loadProperty(proto: Callable): PropertyDescriptor {
val flags = proto.getFlags()
val hasGetter = Flags.HAS_GETTER.get(flags)
val propertyAnnotations = if (hasGetter)
getAnnotationsWithReceiverTargeted(proto, AnnotatedCallableKind.PROPERTY, AnnotatedCallableKind.PROPERTY_GETTER)
else
getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY)
val property = DeserializedPropertyDescriptor(
c.containingDeclaration, null,
getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
propertyAnnotations,
modality(Flags.MODALITY.get(flags)),
visibility(Flags.VISIBILITY.get(flags)),
Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
@@ -63,7 +74,7 @@ public class MemberDeserializer(private val c: DeserializationContext) {
if (proto.hasReceiverType()) local.typeDeserializer.type(proto.getReceiverType()) else null
)
val getter = if (Flags.HAS_GETTER.get(flags)) {
val getter = if (hasGetter) {
val getterFlags = proto.getGetterFlags()
val isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags)
val getter = if (isNotDefault) {
@@ -128,11 +139,13 @@ public class MemberDeserializer(private val c: DeserializationContext) {
}
private fun loadFunction(proto: Callable): CallableMemberDescriptor {
val annotations = getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION)
val annotations = getAnnotationsWithReceiverTargeted(proto, AnnotatedCallableKind.FUNCTION)
val function = DeserializedSimpleFunctionDescriptor.create(c.containingDeclaration, proto, c.nameResolver, annotations)
val local = c.childContext(function, proto.getTypeParameterList())
val receiverParameterType = if (proto.hasReceiverType()) local.typeDeserializer.type(proto.getReceiverType()) else null
function.initialize(
if (proto.hasReceiverType()) local.typeDeserializer.type(proto.getReceiverType()) else null,
receiverParameterType,
getDispatchReceiverParameter(),
local.typeDeserializer.ownTypeParameters,
local.memberDeserializer.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
@@ -163,6 +176,29 @@ public class MemberDeserializer(private val c: DeserializationContext) {
return descriptor
}
private fun getAnnotationsWithReceiverTargeted(
proto: Callable,
kind: AnnotatedCallableKind,
receiverTargetedKind: AnnotatedCallableKind = kind
): Annotations {
return DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
val annotations = arrayListOf<AnnotationWithTarget>()
val container = c.containingDeclaration.asProtoContainer()
annotations += c.components.annotationAndConstantLoader
.loadCallableAnnotations(container, proto, c.nameResolver, kind)
.map { AnnotationWithTarget(it, null) }
if (proto.hasReceiverType()) {
annotations += c.components.annotationAndConstantLoader
.loadExtensionReceiverParameterAnnotations(container, proto, c.nameResolver, receiverTargetedKind)
.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
}
annotations
}
}
private fun getAnnotations(proto: Callable, flags: Int, kind: AnnotatedCallableKind): Annotations {
if (!Flags.HAS_ANNOTATIONS.get(flags)) {
return Annotations.EMPTY
@@ -28,22 +28,32 @@ import org.jetbrains.kotlin.utils.toReadOnlyList
class DeserializedAnnotations(
storageManager: StorageManager,
compute: () -> List<AnnotationDescriptor>
) : DeserializedAnnotationsWithPossibleTargets(
storageManager,
{ compute().map { AnnotationWithTarget(it, null) } })
open class DeserializedAnnotationsWithPossibleTargets(
storageManager: StorageManager,
compute: () -> List<AnnotationWithTarget>
) : Annotations {
private val annotations = storageManager.createLazyValue { compute().toReadOnlyList() }
override fun isEmpty(): Boolean = annotations().isEmpty()
override fun findAnnotation(fqName: FqName) = annotations().firstOrNull {
annotation ->
val descriptor = annotation.getType().getConstructor().getDeclarationDescriptor()
annotationWithTarget ->
if (annotationWithTarget.target != null) return@firstOrNull false
val descriptor = annotationWithTarget.annotation.type.constructor.declarationDescriptor
descriptor is ClassDescriptor && fqName.equalsTo(DescriptorUtils.getFqName(descriptor))
}
}?.annotation
override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations() = emptyList<AnnotationWithTarget>()
override fun getUseSiteTargetedAnnotations() = annotations().filter { it.target != null }
override fun getAllAnnotations() = this.map { AnnotationWithTarget(it, null) }
override fun getAllAnnotations() = annotations()
override fun iterator(): Iterator<AnnotationDescriptor> = annotations().iterator()
}
override fun iterator(): Iterator<AnnotationDescriptor> {
return annotations().asSequence().filter { it.target == null }.map { it.annotation }.iterator()
}
}