annotations with parameters

This commit is contained in:
Alex Tkachman
2012-03-12 16:52:49 +02:00
parent ae1138c4ba
commit c746a50406
3 changed files with 42 additions and 15 deletions
@@ -16,9 +16,14 @@
package org.jetbrains.jet.codegen; 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.Annotated;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 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.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.AnnotationVisitor;
@@ -28,6 +33,7 @@ import org.objectweb.asm.MethodVisitor;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author alex.tkachman * @author alex.tkachman
@@ -36,13 +42,32 @@ public abstract class AnnotationCodegen {
public void genAnnotations(Annotated annotated, JetTypeMapper typeMapper) { public void genAnnotations(Annotated annotated, JetTypeMapper typeMapper) {
if(annotated == null) if(annotated == null)
return; return;
List<AnnotationDescriptor> annotations = annotated.getAnnotations(); if(!(annotated instanceof DeclarationDescriptor))
if(annotations == null)
return; return;
for (AnnotationDescriptor annotationDescriptor : annotations) { BindingContext bindingContext = typeMapper.bindingContext;
List<CompileTimeConstant<?>> valueArguments = annotationDescriptor.getValueArguments(); 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<JetAnnotationEntry> annotationEntries = modifierList.getAnnotationEntries();
for (JetAnnotationEntry annotationEntry : annotationEntries) {
ResolvedCall<? extends CallableDescriptor> 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(); JetType type = annotationDescriptor.getType();
ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor(); ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor();
RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper); RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper);
@@ -50,13 +75,13 @@ public abstract class AnnotationCodegen {
String internalName = typeMapper.mapType(type).getDescriptor(); String internalName = typeMapper.mapType(type).getDescriptor();
AnnotationVisitor annotationVisitor = visitAnnotation(internalName, rp == RetentionPolicy.RUNTIME); AnnotationVisitor annotationVisitor = visitAnnotation(internalName, rp == RetentionPolicy.RUNTIME);
if(!valueArguments.isEmpty()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
// todo: temporary hack for intrinsics in stdlib List<JetExpression> valueArguments = entry.getValue().getArgumentExpressions();
if(valueArguments.size()==1 && "Intrinsic".equals(annotationDescriptor.getType().getConstructor().getDeclarationDescriptor().getName())) { assert valueArguments.size() == 1; // todo
annotationVisitor.visit("value", valueArguments.get(0).getValue()); CompileTimeConstant<?> compileTimeConstant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, valueArguments.get(0));
} assert compileTimeConstant != null;
else
throw new UnsupportedOperationException("Only annotations without values are supported by backend so far"); annotationVisitor.visit(entry.getKey().getName(), compileTimeConstant.getValue());
} }
annotationVisitor.visitEnd(); 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() { return new AnnotationCodegen() {
@Override @Override
AnnotationVisitor visitAnnotation(String descr, boolean visible) { AnnotationVisitor visitAnnotation(String descr, boolean visible) {
return mv.visitAnnotation(descr, visible); return fv.visitAnnotation(descr, visible);
} }
}; };
} }
@@ -50,6 +50,7 @@ public class JetModifierList extends JetElement {
return findChildrenByType(JetNodeTypes.ANNOTATION); return findChildrenByType(JetNodeTypes.ANNOTATION);
} }
@NotNull
public List<JetAnnotationEntry> getAnnotationEntries() { public List<JetAnnotationEntry> getAnnotationEntries() {
List<JetAnnotationEntry> entries = findChildrenByType(JetNodeTypes.ANNOTATION_ENTRY); List<JetAnnotationEntry> entries = findChildrenByType(JetNodeTypes.ANNOTATION_ENTRY);
List<JetAnnotationEntry> answer = entries.isEmpty() ? null : Lists.newArrayList(entries); List<JetAnnotationEntry> answer = entries.isEmpty() ? null : Lists.newArrayList(entries);
@@ -75,6 +75,7 @@ public class AnnotationResolver {
for (JetAnnotationEntry entryElement : annotationEntryElements) { for (JetAnnotationEntry entryElement : annotationEntryElements) {
AnnotationDescriptor descriptor = new AnnotationDescriptor(); AnnotationDescriptor descriptor = new AnnotationDescriptor();
resolveAnnotationStub(scope, entryElement, descriptor, trace); resolveAnnotationStub(scope, entryElement, descriptor, trace);
trace.record(BindingContext.ANNOTATION, entryElement, descriptor);
result.add(descriptor); result.add(descriptor);
} }
return result; return result;