From c746a5040618583ff1c66b58eae250377c1ea1f1 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 12 Mar 2012 16:52:49 +0200 Subject: [PATCH] annotations with parameters --- .../jet/codegen/AnnotationCodegen.java | 55 ++++++++++++++----- .../jet/lang/psi/JetModifierList.java | 1 + .../jet/lang/resolve/AnnotationResolver.java | 1 + 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java index f3a90417b06..92e9c70c55d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java @@ -16,9 +16,14 @@ package org.jetbrains.jet.codegen; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.AnnotationVisitor; @@ -28,6 +33,7 @@ import org.objectweb.asm.MethodVisitor; import java.lang.annotation.RetentionPolicy; import java.util.List; +import java.util.Map; /** * @author alex.tkachman @@ -36,13 +42,32 @@ public abstract class AnnotationCodegen { public void genAnnotations(Annotated annotated, JetTypeMapper typeMapper) { if(annotated == null) return; - - List annotations = annotated.getAnnotations(); - if(annotations == null) + + if(!(annotated instanceof DeclarationDescriptor)) return; - for (AnnotationDescriptor annotationDescriptor : annotations) { - List> valueArguments = annotationDescriptor.getValueArguments(); + BindingContext bindingContext = typeMapper.bindingContext; + PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, (DeclarationDescriptor) annotated); + + JetModifierList modifierList = null; + if(annotated instanceof ConstructorDescriptor && psiElement instanceof JetClass) { + modifierList = ((JetClass)psiElement).getPrimaryConstructorModifierList(); + } + else if (psiElement instanceof JetModifierListOwner) { + modifierList = ((JetModifierListOwner) psiElement).getModifierList(); + } + + if(modifierList == null) + return; + + List annotationEntries = modifierList.getAnnotationEntries(); + for (JetAnnotationEntry annotationEntry : annotationEntries) { + ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, annotationEntry.getCalleeExpression()); + assert resolvedCall != null; + + AnnotationDescriptor annotationDescriptor = bindingContext.get(BindingContext.ANNOTATION, annotationEntry); + assert annotationDescriptor != null; + JetType type = annotationDescriptor.getType(); ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor(); RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper); @@ -50,13 +75,13 @@ public abstract class AnnotationCodegen { String internalName = typeMapper.mapType(type).getDescriptor(); AnnotationVisitor annotationVisitor = visitAnnotation(internalName, rp == RetentionPolicy.RUNTIME); - if(!valueArguments.isEmpty()) { - // todo: temporary hack for intrinsics in stdlib - if(valueArguments.size()==1 && "Intrinsic".equals(annotationDescriptor.getType().getConstructor().getDeclarationDescriptor().getName())) { - annotationVisitor.visit("value", valueArguments.get(0).getValue()); - } - else - throw new UnsupportedOperationException("Only annotations without values are supported by backend so far"); + for (Map.Entry entry : resolvedCall.getValueArguments().entrySet()) { + List valueArguments = entry.getValue().getArgumentExpressions(); + assert valueArguments.size() == 1; // todo + CompileTimeConstant compileTimeConstant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, valueArguments.get(0)); + assert compileTimeConstant != null; + + annotationVisitor.visit(entry.getKey().getName(), compileTimeConstant.getValue()); } annotationVisitor.visitEnd(); @@ -100,11 +125,11 @@ public abstract class AnnotationCodegen { }; } - public static AnnotationCodegen forField(final FieldVisitor mv) { + public static AnnotationCodegen forField(final FieldVisitor fv) { return new AnnotationCodegen() { @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { - return mv.visitAnnotation(descr, visible); + return fv.visitAnnotation(descr, visible); } }; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java index 1cb66e51d79..ea0a61ea029 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetModifierList.java @@ -50,6 +50,7 @@ public class JetModifierList extends JetElement { return findChildrenByType(JetNodeTypes.ANNOTATION); } + @NotNull public List getAnnotationEntries() { List entries = findChildrenByType(JetNodeTypes.ANNOTATION_ENTRY); List answer = entries.isEmpty() ? null : Lists.newArrayList(entries); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 32252e33747..6da3c4edf2b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -75,6 +75,7 @@ public class AnnotationResolver { for (JetAnnotationEntry entryElement : annotationEntryElements) { AnnotationDescriptor descriptor = new AnnotationDescriptor(); resolveAnnotationStub(scope, entryElement, descriptor, trace); + trace.record(BindingContext.ANNOTATION, entryElement, descriptor); result.add(descriptor); } return result;