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.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
} }
@@ -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); 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