001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 aspect AnnotationsCodegen { 011 refine Attributes eq TypeDecl.attributes() { 012 Collection c = refined(); 013 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 014 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 015 return c; 016 } 017 refine Attributes eq FieldDeclaration.attributes() { 018 Collection c = refined(); 019 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 020 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 021 return c; 022 } 023 refine Attributes eq MethodDecl.attributes() { 024 Collection c = refined(); 025 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 026 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 027 addRuntimeVisibleParameterAnnotationsAttribute(c); 028 addRuntimeInvisibleParameterAnnotationsAttribute(c); 029 return c; 030 } 031 refine Attributes eq ConstructorDecl.attributes() { 032 Collection c = refined(); 033 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 034 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 035 return c; 036 } 037 038 // 4.8.15 039 public void Modifiers.addRuntimeVisibleAnnotationsAttribute(Collection c) { 040 ConstantPool cp = hostType().constantPool(); 041 Collection annotations = runtimeVisibleAnnotations(); 042 if(!annotations.isEmpty()) 043 c.add(new AnnotationsAttribute(cp, annotations, "RuntimeVisibleAnnotations")); 044 } 045 046 // 4.8.16 047 public void Modifiers.addRuntimeInvisibleAnnotationsAttribute(Collection c) { 048 ConstantPool cp = hostType().constantPool(); 049 Collection annotations = runtimeInvisibleAnnotations(); 050 if(!annotations.isEmpty()) 051 c.add(new AnnotationsAttribute(cp, annotations, "RuntimeInvisibleAnnotations")); 052 } 053 054 class AnnotationsAttribute extends Attribute { 055 public AnnotationsAttribute(ConstantPool cp, Collection annotations, String name) { 056 super(cp, name); 057 u2(annotations.size()); 058 for(Iterator iter = annotations.iterator(); iter.hasNext(); ) 059 ((Annotation)iter.next()).appendAsAttributeTo(this); 060 } 061 } 062 063 // 4.8.15 064 syn boolean Modifier.isRuntimeVisible() = false; 065 eq Annotation.isRuntimeVisible() { 066 Annotation a = decl().annotation(lookupType("java.lang.annotation", "Retention")); 067 if(a == null) return false; 068 ElementConstantValue value = (ElementConstantValue)a.getElementValuePair(0).getElementValue(); 069 Variable v = value.getExpr().varDecl(); 070 return v != null && v.name().equals("RUNTIME"); 071 } 072 073 // 4.8.16 074 syn boolean Modifier.isRuntimeInvisible() = false; 075 eq Annotation.isRuntimeInvisible() { 076 Annotation a = decl().annotation(lookupType("java.lang.annotation", "Retention")); 077 if(a == null) return true; // default bahavior if not annotated 078 ElementConstantValue value = (ElementConstantValue)a.getElementValuePair(0).getElementValue(); 079 Variable v = value.getExpr().varDecl(); 080 return v != null && v.name().equals("CLASS"); 081 } 082 083 // 4.8.17 084 public void MethodDecl.addRuntimeVisibleParameterAnnotationsAttribute(Collection c) { 085 boolean foundVisibleAnnotations = false; 086 Collection annotations = new ArrayList(getNumParameter()); 087 for(int i = 0; i < getNumParameter(); i++) { 088 Collection a = getParameter(i).getModifiers().runtimeVisibleAnnotations(); 089 if(!a.isEmpty()) foundVisibleAnnotations = true; 090 annotations.add(a); 091 } 092 if(foundVisibleAnnotations) 093 c.add(new ParameterAnnotationsAttribute(hostType().constantPool(), annotations, "RuntimeVisibleParameterAnnotations")); 094 } 095 096 public Collection Modifiers.runtimeVisibleAnnotations() { 097 Collection annotations = new ArrayList(); 098 for(int i = 0; i < getNumModifier(); i++) 099 if(getModifier(i).isRuntimeVisible()) 100 annotations.add(getModifier(i)); 101 return annotations; 102 } 103 104 // 4.8.18 105 public void MethodDecl.addRuntimeInvisibleParameterAnnotationsAttribute(Collection c) { 106 boolean foundInvisibleAnnotations = false; 107 Collection annotations = new ArrayList(getNumParameter()); 108 for(int i = 0; i < getNumParameter(); i++) { 109 Collection a = getParameter(i).getModifiers().runtimeInvisibleAnnotations(); 110 if(!a.isEmpty()) foundInvisibleAnnotations = true; 111 annotations.add(a); 112 } 113 if(foundInvisibleAnnotations) 114 c.add(new ParameterAnnotationsAttribute(hostType().constantPool(), annotations, "RuntimeInvisibleParameterAnnotations")); 115 } 116 117 public Collection Modifiers.runtimeInvisibleAnnotations() { 118 Collection annotations = new ArrayList(); 119 for(int i = 0; i < getNumModifier(); i++) 120 if(getModifier(i).isRuntimeInvisible()) 121 annotations.add(getModifier(i)); 122 return annotations; 123 } 124 125 class ParameterAnnotationsAttribute extends Attribute { 126 public ParameterAnnotationsAttribute(ConstantPool cp, Collection annotations, String name) { 127 super(cp, name); 128 u1(annotations.size()); 129 for(Iterator iter = annotations.iterator(); iter.hasNext(); ) { 130 Collection c = (Collection)iter.next(); 131 for(Iterator inner = c.iterator(); inner.hasNext(); ) { 132 Annotation a = (Annotation)inner.next(); 133 a.appendAsAttributeTo(this); 134 } 135 } 136 } 137 } 138 139 // Add ACC_ANNOTATION flag to generated class file 140 public static final int Modifiers.ACC_ANNOTATION = 0x2000; 141 eq AnnotationDecl.flags() = super.flags() | Modifiers.ACC_ANNOTATION; 142 143 eq AnnotationMethodDecl.attributes() { 144 Collection c = super.attributes(); 145 // 4.8.19 146 if(hasDefaultValue()) { 147 Attribute attribute = new Attribute(hostType().constantPool(), "AnnotationDefault"); 148 getDefaultValue().appendAsAttributeTo(attribute); 149 c.add(attribute); 150 } 151 return c; 152 } 153 154 // 4.8.15 155 public void Annotation.appendAsAttributeTo(Attribute buf) { 156 ConstantPool cp = hostType().constantPool(); 157 String typeDescriptor = decl().typeDescriptor(); 158 int type_index = cp.addUtf8(typeDescriptor); 159 buf.u2(type_index); 160 buf.u2(getNumElementValuePair()); 161 for(int i = 0; i < getNumElementValuePair(); i++) { 162 int name_index = cp.addUtf8(getElementValuePair(i).getName()); 163 buf.u2(name_index); 164 getElementValuePair(i).getElementValue().appendAsAttributeTo(buf); 165 } 166 } 167 168 /** 169 * Add an annotation parameter constant to the constant pool. 170 * @see AST.TypeDecl#addConstant(ConstantPool, Constant) TypeDecl.addConstant(ConstantPool, Constant) 171 */ 172 public int TypeDecl.addAnnotConstant(ConstantPool p, Constant c) { 173 if(isString()) 174 return p.addUtf8(c.stringValue()); 175 throw new Error("Not supported"); 176 } 177 public int BooleanType.addAnnotConstant(ConstantPool p, Constant c) { 178 return addConstant(p, c); 179 } 180 public int IntegralType.addAnnotConstant(ConstantPool p, Constant c) { 181 return addConstant(p, c); 182 } 183 public int LongType.addAnnotConstant(ConstantPool p, Constant c) { 184 return addConstant(p, c); 185 } 186 public int FloatType.addAnnotConstant(ConstantPool p, Constant c) { 187 return addConstant(p, c); 188 } 189 public int DoubleType.addAnnotConstant(ConstantPool p, Constant c) { 190 return addConstant(p, c); 191 } 192 193 // 4.8.15.1 194 public void ElementValue.appendAsAttributeTo(Attribute buf) { 195 throw new Error(getClass().getName() + " does not support appendAsAttributeTo(Attribute buf)"); 196 } 197 public void ElementConstantValue.appendAsAttributeTo(Attribute buf) { 198 if(getExpr().isConstant() && !getExpr().type().isEnumDecl()) { 199 char tag = getExpr().type().isString() ? 's' : getExpr().type().typeDescriptor().charAt(0); 200 int const_value_index = getExpr().type().addAnnotConstant(hostType().constantPool(), getExpr().constant()); 201 buf.u1(tag); 202 buf.u2(const_value_index); 203 } 204 else if(getExpr().isClassAccess()) { 205 int const_class_index = hostType().constantPool().addUtf8(getExpr().type().typeDescriptor()); 206 buf.u1('c'); 207 buf.u2(const_class_index); 208 } 209 else { 210 Variable v = getExpr().varDecl(); 211 if(v == null) throw new Error("Expected Enumeration constant"); 212 213 int type_name_index = hostType().constantPool().addUtf8(v.type().typeDescriptor()); 214 int const_name_index = hostType().constantPool().addUtf8(v.name()); 215 buf.u1('e'); 216 buf.u2(type_name_index); 217 buf.u2(const_name_index); 218 } 219 } 220 public void ElementAnnotationValue.appendAsAttributeTo(Attribute buf) { 221 buf.u1('@'); 222 getAnnotation().appendAsAttributeTo(buf); 223 } 224 public void ElementArrayValue.appendAsAttributeTo(Attribute buf) { 225 buf.u1('['); 226 buf.u2(getNumElementValue()); 227 for(int i = 0; i < getNumElementValue(); i++) 228 getElementValue(i).appendAsAttributeTo(buf); 229 } 230 231 inh TypeDecl ElementValue.hostType(); 232 }