Support generation of new annotations

This commit is contained in:
Yan Zhulanow
2015-08-06 21:49:57 +03:00
parent 3624c4e5dc
commit b8d2ba23e3
8 changed files with 168 additions and 121 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.*;
@@ -50,7 +51,7 @@ public abstract class AnnotationCodegen {
}
public boolean hasAnnotation(@NotNull Annotated annotated) {
return annotated.getAnnotations().findAnnotation(fqName) != null;
return Annotations.Companion.findAnyAnnotation(annotated.getAnnotations(), fqName) != null;
}
public int getJvmFlag() {
@@ -84,7 +85,7 @@ public abstract class AnnotationCodegen {
genAnnotations(annotated, returnType, null);
}
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType, @Nullable AnnotationUseSiteTarget target) {
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType, @Nullable AnnotationUseSiteTarget allowedTarget) {
if (annotated == null) {
return;
}
@@ -93,18 +94,16 @@ public abstract class AnnotationCodegen {
Annotations annotations = annotated.getAnnotations();
if (target != null) {
for (AnnotationWithTarget annotationWithTarget : annotations.getUseSiteTargetedAnnotations()) {
if (target != annotationWithTarget.getTarget()) continue;
for (AnnotationWithTarget annotationWithTarget : annotations.getAllAnnotations()) {
AnnotationDescriptor annotation = annotationWithTarget.getAnnotation();
AnnotationUseSiteTarget annotationTarget = annotationWithTarget.getTarget();
String descriptor = genAnnotation(annotationWithTarget.getAnnotation());
if (descriptor != null) {
annotationDescriptorsAlreadyPresent.add(descriptor);
}
}
}
// Skip targeted annotations by default
if (allowedTarget == null && annotationTarget != null) continue;
// Skip if the target is not the same
if (allowedTarget != null && annotationTarget != null && allowedTarget != annotationTarget) continue;
for (AnnotationDescriptor annotation : annotations) {
String descriptor = genAnnotation(annotation);
if (descriptor != null) {
annotationDescriptorsAlreadyPresent.add(descriptor);
@@ -119,8 +118,13 @@ public abstract class AnnotationCodegen {
@Nullable Type returnType,
@NotNull Set<String> annotationDescriptorsAlreadyPresent
) {
if (annotated instanceof CallableDescriptor) {
CallableDescriptor descriptor = (CallableDescriptor) annotated;
Annotated unwrapped = annotated;
if (annotated instanceof WrappedAnnotated) {
unwrapped = ((WrappedAnnotated) annotated).getOriginalAnnotated();
}
if (unwrapped instanceof CallableDescriptor) {
CallableDescriptor descriptor = (CallableDescriptor) unwrapped;
// No need to annotate privates, synthetic accessors and their parameters
if (isInvisibleFromTheOutside(descriptor)) return;
@@ -130,8 +134,8 @@ public abstract class AnnotationCodegen {
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
}
}
if (annotated instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) annotated;
if (unwrapped instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped;
if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
generateDocumentedAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
generateRetentionAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithAdditionalAnnotations;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.PackageContext;
@@ -170,7 +170,7 @@ public class FunctionCodegen {
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
}
generateTargetedAnnotations(functionDescriptor, asmMethod, mv);
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));
@@ -215,7 +215,7 @@ public class FunctionCodegen {
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
}
private void generateTargetedAnnotations(
private void generateMethodAnnotations(
@NotNull FunctionDescriptor functionDescriptor,
Method asmMethod,
MethodVisitor mv
@@ -224,13 +224,11 @@ public class FunctionCodegen {
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER;
Annotated annotated = new AnnotatedWithAdditionalAnnotations(
null, ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty());
annotationCodegen.genAnnotations(annotated, asmMethod.getReturnType(), target);
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType(), target);
}
else {
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
}
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
}
private void generateParameterAnnotations(
@@ -256,7 +254,7 @@ public class FunctionCodegen {
if (functionDescriptor instanceof PropertySetterDescriptor) {
PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
Annotated targetedAnnotations = new AnnotatedWithAdditionalAnnotations(null, propertyDescriptor);
Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(propertyDescriptor);
annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
}
@@ -273,7 +271,7 @@ public class FunctionCodegen {
: functionDescriptor).getExtensionReceiverParameter();
if (receiver != null) {
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
Annotated targetedAnnotations = new AnnotatedWithAdditionalAnnotations(null, receiver.getType());
Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(receiver.getType());
annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
}
}
@@ -20,12 +20,14 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithFakeAnnotations;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
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.Annotations;
import org.jetbrains.kotlin.descriptors.annotations.*;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
@@ -39,6 +41,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.kotlin.util.AnnotationSplitter;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -112,12 +115,16 @@ public class PropertyCodegen {
else {
assert declaration != null : "Declaration is null for different context: " + context;
List<AnnotationDescriptor> propertyTargetedAnnotations =
descriptor.getAnnotations().getUseSiteTargetedAnnotations(AnnotationUseSiteTarget.PROPERTY);
boolean hasBackingField = hasBackingField(declaration, descriptor);
if (!generateBackingField(declaration, descriptor) || !propertyTargetedAnnotations.isEmpty()) {
generateSyntheticMethodIfNeeded(descriptor, !propertyTargetedAnnotations.isEmpty());
}
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(
descriptor.getAnnotations(), false, hasBackingField, descriptor.isVar());
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
generateBackingField(declaration, descriptor, fieldAnnotations);
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
}
if (isAccessorNeeded(declaration, descriptor, getter)) {
@@ -163,7 +170,15 @@ public class PropertyCodegen {
}
public void generatePrimaryConstructorProperty(JetParameter p, PropertyDescriptor descriptor) {
generateBackingField(p, descriptor);
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(
descriptor.getAnnotations(), true, hasBackingField(p, descriptor), descriptor.isVar());
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
generateBackingField(p, descriptor, fieldAnnotations);
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
if (!Visibilities.isPrivate(descriptor.getVisibility())) {
generateGetter(p, descriptor, null);
if (descriptor.isVar()) {
@@ -196,16 +211,29 @@ public class PropertyCodegen {
mv.visitEnd();
}
private boolean generateBackingField(@NotNull JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor) {
private boolean hasBackingField(@NotNull JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor) {
if (isInterface(descriptor.getContainingDeclaration()) ||
kind == OwnerKind.TRAIT_IMPL ||
Boolean.FALSE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
return false;
}
else return true;
}
private boolean generateBackingField(
@NotNull JetNamedDeclaration p,
@NotNull PropertyDescriptor descriptor,
@NotNull Annotations annotations
) {
if (isInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.TRAIT_IMPL) {
return false;
}
if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) {
generatePropertyDelegateAccess((JetProperty) p, descriptor);
generatePropertyDelegateAccess((JetProperty) p, descriptor, annotations);
}
else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
generateBackingFieldAccess(p, descriptor);
generateBackingFieldAccess(p, descriptor, annotations);
}
else {
return false;
@@ -213,10 +241,10 @@ public class PropertyCodegen {
return true;
}
// Annotations on properties without backing fields are stored in bytecode on an empty synthetic method. This way they're still
// Annotations on properties are stored in bytecode on an empty synthetic method. This way they're still
// accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, boolean hasPropertyTargetedAnnotations) {
if (descriptor.getAnnotations().isEmpty() && !hasPropertyTargetedAnnotations) return;
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, Annotations annotations) {
if (annotations.getAllAnnotations().isEmpty()) return;
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
@@ -225,7 +253,8 @@ public class PropertyCodegen {
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null);
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY);
AnnotationCodegen.forMethod(mv, typeMapper)
.genAnnotations(new AnnotatedImpl(annotations), Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
@@ -240,7 +269,14 @@ public class PropertyCodegen {
}
}
private void generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
private void generateBackingField(
JetNamedDeclaration element,
PropertyDescriptor propertyDescriptor,
boolean isDelegate,
JetType jetType,
Object defaultValue,
Annotations annotations
) {
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
@@ -299,10 +335,12 @@ public class PropertyCodegen {
FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
typeMapper.mapFieldSignature(jetType), defaultValue);
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type, AnnotationUseSiteTarget.FIELD);
Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations);
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(fieldAnnotated, type, AnnotationUseSiteTarget.FIELD);
}
private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor, Annotations annotations) {
JetExpression delegateExpression = p.getDelegateExpression();
JetType delegateType = delegateExpression != null ? bindingContext.getType(p.getDelegateExpression()) : null;
if (delegateType == null) {
@@ -310,10 +348,10 @@ public class PropertyCodegen {
delegateType = ErrorUtils.createErrorType("Delegate type");
}
generateBackingField(p, propertyDescriptor, true, delegateType, null);
generateBackingField(p, propertyDescriptor, true, delegateType, null, annotations);
}
private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, Annotations annotations) {
Object value = null;
if (shouldWriteFieldInitializer(propertyDescriptor)) {
@@ -323,7 +361,7 @@ public class PropertyCodegen {
}
}
generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value, annotations);
}
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
@@ -338,7 +376,7 @@ public class PropertyCodegen {
private void generateGetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor, @Nullable JetPropertyAccessor getter) {
generateAccessor(p, getter, descriptor.getGetter() != null
? descriptor.getGetter()
: DescriptorFactory.createDefaultGetter(descriptor));
: DescriptorFactory.createDefaultGetter(descriptor, Annotations.EMPTY));
}
private void generateSetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor, @Nullable JetPropertyAccessor setter) {
@@ -346,7 +384,7 @@ public class PropertyCodegen {
generateAccessor(p, setter, descriptor.getSetter() != null
? descriptor.getSetter()
: DescriptorFactory.createDefaultSetter(descriptor));
: DescriptorFactory.createDefaultSetter(descriptor, Annotations.EMPTY));
}
private void generateAccessor(
@@ -114,7 +114,7 @@ public class PropertyReferenceCodegen(
target as PropertyDescriptor
val getter = target.getGetter() ?: run {
val defaultGetter = DescriptorFactory.createDefaultGetter(target)
val defaultGetter = DescriptorFactory.createDefaultGetter(target, Annotations.EMPTY)
defaultGetter.initialize(target.getType())
defaultGetter
}
@@ -1,54 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.annotation
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName
public class AnnotatedWithAdditionalAnnotations(
delegate: Annotated?,
additional: Annotated
) : Annotated {
private val annotations: Annotations = UseSiteTargetedAnnotations(delegate?.annotations ?: Annotations.EMPTY, additional.annotations)
override fun getAnnotations() = annotations
private class UseSiteTargetedAnnotations(
private val original: Annotations,
private val additionalAnnotations: Annotations
) : Annotations {
override fun isEmpty() = original.isEmpty()
override fun findAnnotation(fqName: FqName) = original.findAnnotation(fqName)
override fun findExternalAnnotation(fqName: FqName) = original.findExternalAnnotation(fqName)
private fun getAdditionalTargetedAnnotations() = additionalAnnotations.getUseSiteTargetedAnnotations()
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
return original.getUseSiteTargetedAnnotations() + getAdditionalTargetedAnnotations()
}
override fun getAllAnnotations(): List<AnnotationWithTarget> {
return original.getAllAnnotations() + getAdditionalTargetedAnnotations()
}
override fun iterator() = original.iterator()
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.annotation
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName
public interface WrappedAnnotated : Annotated {
public val originalAnnotated: Annotated
}
public class AnnotatedWithFakeAnnotations(override val originalAnnotated: Annotated, private val actual: Annotations) : WrappedAnnotated {
override fun getAnnotations() = actual
}
public class AnnotatedWithOnlyTargetedAnnotations(private val original: Annotated) : Annotated {
private val annotations: Annotations = UseSiteTargetedAnnotations(original.annotations)
override fun getAnnotations() = annotations
private class UseSiteTargetedAnnotations(private val additionalAnnotations: Annotations) : Annotations {
override fun isEmpty() = true
override fun findAnnotation(fqName: FqName) = null
override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations() = getAdditionalTargetedAnnotations()
override fun getAllAnnotations() = getAdditionalTargetedAnnotations()
override fun iterator() = emptyList<AnnotationDescriptor>().iterator()
private fun getAdditionalTargetedAnnotations() = additionalAnnotations.getUseSiteTargetedAnnotations()
}
}
public class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)
@@ -1033,7 +1033,7 @@ public class KotlinBuiltIns {
AnnotationUseSiteTarget associatedUseSiteTarget = AnnotationUseSiteTarget.Companion.getAssociatedUseSiteTarget(descriptor);
if (associatedUseSiteTarget != null) {
if (annotations.findUseSiteTargetedAnnotation(associatedUseSiteTarget, annotationClassFqName) != null) {
if (Annotations.Companion.findUseSiteTargetedAnnotation(annotations, associatedUseSiteTarget, annotationClassFqName) != null) {
return true;
}
}
@@ -30,22 +30,6 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
public fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget>
public fun getUseSiteTargetedAnnotations(target: AnnotationUseSiteTarget): List<AnnotationDescriptor> {
return getUseSiteTargetedAnnotations().fold(arrayListOf<AnnotationDescriptor>()) { list, targeted ->
if (target == targeted.target) {
list.add(targeted.annotation)
}
list
}
}
public fun findUseSiteTargetedAnnotation(target: AnnotationUseSiteTarget, fqName: FqName): AnnotationDescriptor? {
return getUseSiteTargetedAnnotations(target).firstOrNull {
val descriptor = it.type.constructor.declarationDescriptor
descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
}
}
// Returns both targeted and annotations without target. Annotation order is preserved.
public fun getAllAnnotations(): List<AnnotationWithTarget>
@@ -65,9 +49,31 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
override fun toString() = "EMPTY"
}
public fun findAnyAnnotation(annotations: Annotations, fqName: FqName): AnnotationWithTarget? {
return annotations.getAllAnnotations().firstOrNull { checkAnnotationName(it.annotation, fqName) }
}
public fun findUseSiteTargetedAnnotation(annotations: Annotations, target: AnnotationUseSiteTarget, fqName: FqName): AnnotationDescriptor? {
return getUseSiteTargetedAnnotations(annotations, target).firstOrNull { checkAnnotationName(it, fqName) }
}
private fun getUseSiteTargetedAnnotations(annotations: Annotations, target: AnnotationUseSiteTarget): List<AnnotationDescriptor> {
return annotations.getUseSiteTargetedAnnotations().fold(arrayListOf<AnnotationDescriptor>()) { list, targeted ->
if (target == targeted.target) {
list.add(targeted.annotation)
}
list
}
}
}
}
private fun checkAnnotationName(annotation: AnnotationDescriptor, fqName: FqName): Boolean {
val descriptor = annotation.type.constructor.declarationDescriptor
return descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
}
class FilteredAnnotations(
private val delegate: Annotations,
private val fqNameFilter: (FqName) -> Boolean