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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.*;
|
import org.jetbrains.kotlin.descriptors.annotations.*;
|
||||||
@@ -50,7 +51,7 @@ public abstract class AnnotationCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAnnotation(@NotNull Annotated annotated) {
|
public boolean hasAnnotation(@NotNull Annotated annotated) {
|
||||||
return annotated.getAnnotations().findAnnotation(fqName) != null;
|
return Annotations.Companion.findAnyAnnotation(annotated.getAnnotations(), fqName) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getJvmFlag() {
|
public int getJvmFlag() {
|
||||||
@@ -84,7 +85,7 @@ public abstract class AnnotationCodegen {
|
|||||||
genAnnotations(annotated, returnType, null);
|
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) {
|
if (annotated == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,18 +94,16 @@ public abstract class AnnotationCodegen {
|
|||||||
|
|
||||||
Annotations annotations = annotated.getAnnotations();
|
Annotations annotations = annotated.getAnnotations();
|
||||||
|
|
||||||
if (target != null) {
|
for (AnnotationWithTarget annotationWithTarget : annotations.getAllAnnotations()) {
|
||||||
for (AnnotationWithTarget annotationWithTarget : annotations.getUseSiteTargetedAnnotations()) {
|
AnnotationDescriptor annotation = annotationWithTarget.getAnnotation();
|
||||||
if (target != annotationWithTarget.getTarget()) continue;
|
AnnotationUseSiteTarget annotationTarget = annotationWithTarget.getTarget();
|
||||||
|
|
||||||
String descriptor = genAnnotation(annotationWithTarget.getAnnotation());
|
// Skip targeted annotations by default
|
||||||
if (descriptor != null) {
|
if (allowedTarget == null && annotationTarget != null) continue;
|
||||||
annotationDescriptorsAlreadyPresent.add(descriptor);
|
|
||||||
}
|
// Skip if the target is not the same
|
||||||
}
|
if (allowedTarget != null && annotationTarget != null && allowedTarget != annotationTarget) continue;
|
||||||
}
|
|
||||||
|
|
||||||
for (AnnotationDescriptor annotation : annotations) {
|
|
||||||
String descriptor = genAnnotation(annotation);
|
String descriptor = genAnnotation(annotation);
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
annotationDescriptorsAlreadyPresent.add(descriptor);
|
annotationDescriptorsAlreadyPresent.add(descriptor);
|
||||||
@@ -119,8 +118,13 @@ public abstract class AnnotationCodegen {
|
|||||||
@Nullable Type returnType,
|
@Nullable Type returnType,
|
||||||
@NotNull Set<String> annotationDescriptorsAlreadyPresent
|
@NotNull Set<String> annotationDescriptorsAlreadyPresent
|
||||||
) {
|
) {
|
||||||
if (annotated instanceof CallableDescriptor) {
|
Annotated unwrapped = annotated;
|
||||||
CallableDescriptor descriptor = (CallableDescriptor) 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
|
// No need to annotate privates, synthetic accessors and their parameters
|
||||||
if (isInvisibleFromTheOutside(descriptor)) return;
|
if (isInvisibleFromTheOutside(descriptor)) return;
|
||||||
@@ -130,8 +134,8 @@ public abstract class AnnotationCodegen {
|
|||||||
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (annotated instanceof ClassDescriptor) {
|
if (unwrapped instanceof ClassDescriptor) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) annotated;
|
ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped;
|
||||||
if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
|
if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
|
||||||
generateDocumentedAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
|
generateDocumentedAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
|
||||||
generateRetentionAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
|
generateRetentionAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage;
|
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.CodegenContext;
|
||||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||||
import org.jetbrains.kotlin.codegen.context.PackageContext;
|
import org.jetbrains.kotlin.codegen.context.PackageContext;
|
||||||
@@ -170,7 +170,7 @@ public class FunctionCodegen {
|
|||||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateTargetedAnnotations(functionDescriptor, asmMethod, mv);
|
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
|
||||||
|
|
||||||
generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));
|
generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ public class FunctionCodegen {
|
|||||||
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateTargetedAnnotations(
|
private void generateMethodAnnotations(
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
Method asmMethod,
|
Method asmMethod,
|
||||||
MethodVisitor mv
|
MethodVisitor mv
|
||||||
@@ -224,13 +224,11 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
|
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
|
||||||
AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER;
|
AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER;
|
||||||
Annotated annotated = new AnnotatedWithAdditionalAnnotations(
|
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType(), target);
|
||||||
null, ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty());
|
}
|
||||||
|
else {
|
||||||
annotationCodegen.genAnnotations(annotated, asmMethod.getReturnType(), target);
|
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
||||||
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateParameterAnnotations(
|
private void generateParameterAnnotations(
|
||||||
@@ -256,7 +254,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
if (functionDescriptor instanceof PropertySetterDescriptor) {
|
if (functionDescriptor instanceof PropertySetterDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
|
PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
|
||||||
Annotated targetedAnnotations = new AnnotatedWithAdditionalAnnotations(null, propertyDescriptor);
|
Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(propertyDescriptor);
|
||||||
annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
|
annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +271,7 @@ public class FunctionCodegen {
|
|||||||
: functionDescriptor).getExtensionReceiverParameter();
|
: functionDescriptor).getExtensionReceiverParameter();
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
|
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);
|
annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ import com.intellij.openapi.util.Pair;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithFakeAnnotations;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
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.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.load.java.JvmAbi;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
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.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils;
|
import org.jetbrains.kotlin.types.ErrorUtils;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
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.FieldVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||||
@@ -112,12 +115,16 @@ public class PropertyCodegen {
|
|||||||
else {
|
else {
|
||||||
assert declaration != null : "Declaration is null for different context: " + context;
|
assert declaration != null : "Declaration is null for different context: " + context;
|
||||||
|
|
||||||
List<AnnotationDescriptor> propertyTargetedAnnotations =
|
boolean hasBackingField = hasBackingField(declaration, descriptor);
|
||||||
descriptor.getAnnotations().getUseSiteTargetedAnnotations(AnnotationUseSiteTarget.PROPERTY);
|
|
||||||
|
|
||||||
if (!generateBackingField(declaration, descriptor) || !propertyTargetedAnnotations.isEmpty()) {
|
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(
|
||||||
generateSyntheticMethodIfNeeded(descriptor, !propertyTargetedAnnotations.isEmpty());
|
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)) {
|
if (isAccessorNeeded(declaration, descriptor, getter)) {
|
||||||
@@ -163,7 +170,15 @@ public class PropertyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generatePrimaryConstructorProperty(JetParameter p, PropertyDescriptor descriptor) {
|
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())) {
|
if (!Visibilities.isPrivate(descriptor.getVisibility())) {
|
||||||
generateGetter(p, descriptor, null);
|
generateGetter(p, descriptor, null);
|
||||||
if (descriptor.isVar()) {
|
if (descriptor.isVar()) {
|
||||||
@@ -196,16 +211,29 @@ public class PropertyCodegen {
|
|||||||
mv.visitEnd();
|
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) {
|
if (isInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.TRAIT_IMPL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) {
|
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))) {
|
else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
|
||||||
generateBackingFieldAccess(p, descriptor);
|
generateBackingFieldAccess(p, descriptor, annotations);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
@@ -213,10 +241,10 @@ public class PropertyCodegen {
|
|||||||
return true;
|
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
|
// accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally
|
||||||
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, boolean hasPropertyTargetedAnnotations) {
|
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, Annotations annotations) {
|
||||||
if (descriptor.getAnnotations().isEmpty() && !hasPropertyTargetedAnnotations) return;
|
if (annotations.getAllAnnotations().isEmpty()) return;
|
||||||
|
|
||||||
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
||||||
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
||||||
@@ -225,7 +253,8 @@ public class PropertyCodegen {
|
|||||||
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
|
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
|
||||||
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
|
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
|
||||||
MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null);
|
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.visitCode();
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
mv.visitEnd();
|
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);
|
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
|
||||||
|
|
||||||
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
|
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(),
|
FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||||
typeMapper.mapFieldSignature(jetType), defaultValue);
|
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();
|
JetExpression delegateExpression = p.getDelegateExpression();
|
||||||
JetType delegateType = delegateExpression != null ? bindingContext.getType(p.getDelegateExpression()) : null;
|
JetType delegateType = delegateExpression != null ? bindingContext.getType(p.getDelegateExpression()) : null;
|
||||||
if (delegateType == null) {
|
if (delegateType == null) {
|
||||||
@@ -310,10 +348,10 @@ public class PropertyCodegen {
|
|||||||
delegateType = ErrorUtils.createErrorType("Delegate type");
|
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;
|
Object value = null;
|
||||||
|
|
||||||
if (shouldWriteFieldInitializer(propertyDescriptor)) {
|
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) {
|
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) {
|
private void generateGetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor, @Nullable JetPropertyAccessor getter) {
|
||||||
generateAccessor(p, getter, descriptor.getGetter() != null
|
generateAccessor(p, getter, descriptor.getGetter() != null
|
||||||
? descriptor.getGetter()
|
? descriptor.getGetter()
|
||||||
: DescriptorFactory.createDefaultGetter(descriptor));
|
: DescriptorFactory.createDefaultGetter(descriptor, Annotations.EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateSetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor, @Nullable JetPropertyAccessor setter) {
|
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
|
generateAccessor(p, setter, descriptor.getSetter() != null
|
||||||
? descriptor.getSetter()
|
? descriptor.getSetter()
|
||||||
: DescriptorFactory.createDefaultSetter(descriptor));
|
: DescriptorFactory.createDefaultSetter(descriptor, Annotations.EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateAccessor(
|
private void generateAccessor(
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class PropertyReferenceCodegen(
|
|||||||
target as PropertyDescriptor
|
target as PropertyDescriptor
|
||||||
|
|
||||||
val getter = target.getGetter() ?: run {
|
val getter = target.getGetter() ?: run {
|
||||||
val defaultGetter = DescriptorFactory.createDefaultGetter(target)
|
val defaultGetter = DescriptorFactory.createDefaultGetter(target, Annotations.EMPTY)
|
||||||
defaultGetter.initialize(target.getType())
|
defaultGetter.initialize(target.getType())
|
||||||
defaultGetter
|
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);
|
AnnotationUseSiteTarget associatedUseSiteTarget = AnnotationUseSiteTarget.Companion.getAssociatedUseSiteTarget(descriptor);
|
||||||
if (associatedUseSiteTarget != null) {
|
if (associatedUseSiteTarget != null) {
|
||||||
if (annotations.findUseSiteTargetedAnnotation(associatedUseSiteTarget, annotationClassFqName) != null) {
|
if (Annotations.Companion.findUseSiteTargetedAnnotation(annotations, associatedUseSiteTarget, annotationClassFqName) != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,22 +30,6 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
|
|||||||
|
|
||||||
public fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget>
|
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.
|
// Returns both targeted and annotations without target. Annotation order is preserved.
|
||||||
public fun getAllAnnotations(): List<AnnotationWithTarget>
|
public fun getAllAnnotations(): List<AnnotationWithTarget>
|
||||||
|
|
||||||
@@ -65,9 +49,31 @@ public interface Annotations : Iterable<AnnotationDescriptor> {
|
|||||||
|
|
||||||
override fun toString() = "EMPTY"
|
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(
|
class FilteredAnnotations(
|
||||||
private val delegate: Annotations,
|
private val delegate: Annotations,
|
||||||
private val fqNameFilter: (FqName) -> Boolean
|
private val fqNameFilter: (FqName) -> Boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user