diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 14c2b434fea..ca29fbf1a74 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -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 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); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 5591804944a..4d479379fec 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -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); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index c406b0dd2f7..9c899851958 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -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 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( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index 940897fd9a5..b0d7d1f96d7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -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 } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/annotation/AnnotatedWithAdditionalAnnotations.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/annotation/AnnotatedWithAdditionalAnnotations.kt deleted file mode 100644 index a10cba18710..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/annotation/AnnotatedWithAdditionalAnnotations.kt +++ /dev/null @@ -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 { - return original.getUseSiteTargetedAnnotations() + getAdditionalTargetedAnnotations() - } - - override fun getAllAnnotations(): List { - return original.getAllAnnotations() + getAdditionalTargetedAnnotations() - } - - override fun iterator() = original.iterator() - } -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/annotation/AnnotatedWithOnlyTargetedAnnotations.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/annotation/AnnotatedWithOnlyTargetedAnnotations.kt new file mode 100644 index 00000000000..323c7f44751 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/annotation/AnnotatedWithOnlyTargetedAnnotations.kt @@ -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().iterator() + + private fun getAdditionalTargetedAnnotations() = additionalAnnotations.getUseSiteTargetedAnnotations() + } +} + +public class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations) \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 0f56a3bb650..07f46d4f6b9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -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; } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt index 43bf3d702b4..3634329319a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt @@ -30,22 +30,6 @@ public interface Annotations : Iterable { public fun getUseSiteTargetedAnnotations(): List - public fun getUseSiteTargetedAnnotations(target: AnnotationUseSiteTarget): List { - return getUseSiteTargetedAnnotations().fold(arrayListOf()) { 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 @@ -65,9 +49,31 @@ public interface Annotations : Iterable { 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 { + return annotations.getUseSiteTargetedAnnotations().fold(arrayListOf()) { 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