Support generation of new annotations
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
-54
@@ -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()
|
||||
}
|
||||
}
|
||||
+55
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user