001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 aspect AnnotationsCodegen { 032 refine Attributes eq TypeDecl.attributes() { 033 Collection c = refined(); 034 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 035 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 036 return c; 037 } 038 refine Attributes eq FieldDeclaration.attributes() { 039 Collection c = refined(); 040 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 041 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 042 return c; 043 } 044 refine Attributes eq MethodDecl.attributes() { 045 Collection c = refined(); 046 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 047 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 048 addRuntimeVisibleParameterAnnotationsAttribute(c); 049 addRuntimeInvisibleParameterAnnotationsAttribute(c); 050 return c; 051 } 052 refine Attributes eq ConstructorDecl.attributes() { 053 Collection c = refined(); 054 getModifiers().addRuntimeVisibleAnnotationsAttribute(c); 055 getModifiers().addRuntimeInvisibleAnnotationsAttribute(c); 056 return c; 057 } 058 059 // 4.8.15 060 public void Modifiers.addRuntimeVisibleAnnotationsAttribute(Collection c) { 061 ConstantPool cp = hostType().constantPool(); 062 Collection annotations = runtimeVisibleAnnotations(); 063 if (!annotations.isEmpty()) { 064 c.add(new AnnotationsAttribute(cp, annotations, "RuntimeVisibleAnnotations")); 065 } 066 } 067 068 // 4.8.16 069 public void Modifiers.addRuntimeInvisibleAnnotationsAttribute(Collection c) { 070 ConstantPool cp = hostType().constantPool(); 071 Collection annotations = runtimeInvisibleAnnotations(); 072 if (!annotations.isEmpty()) { 073 c.add(new AnnotationsAttribute(cp, annotations, "RuntimeInvisibleAnnotations")); 074 } 075 } 076 077 class AnnotationsAttribute extends Attribute { 078 public AnnotationsAttribute(ConstantPool cp, Collection annotations, String name) { 079 super(cp, name); 080 u2(annotations.size()); 081 for (Iterator iter = annotations.iterator(); iter.hasNext(); ) { 082 ((Annotation) iter.next()).appendAsAttributeTo(this); 083 } 084 } 085 } 086 087 // 4.8.15 088 syn boolean Modifier.isRuntimeVisible() = false; 089 eq Annotation.isRuntimeVisible() { 090 Annotation a = decl().annotation(lookupType("java.lang.annotation", "Retention")); 091 if (a == null) { 092 return false; 093 } 094 ElementConstantValue value = (ElementConstantValue) a.getElementValuePair(0).getElementValue(); 095 Variable v = value.getExpr().varDecl(); 096 return v != null && v.name().equals("RUNTIME"); 097 } 098 099 // 4.8.16 100 syn boolean Modifier.isRuntimeInvisible() = false; 101 eq Annotation.isRuntimeInvisible() { 102 Annotation a = decl().annotation(lookupType("java.lang.annotation", "Retention")); 103 if (a == null) return true; // default bahavior if not annotated 104 ElementConstantValue value = (ElementConstantValue) a.getElementValuePair(0).getElementValue(); 105 Variable v = value.getExpr().varDecl(); 106 return v != null && v.name().equals("CLASS"); 107 } 108 109 // 4.8.17 110 public void MethodDecl.addRuntimeVisibleParameterAnnotationsAttribute(Collection c) { 111 boolean foundVisibleAnnotations = false; 112 Collection annotations = new ArrayList(getNumParameter()); 113 for (int i = 0; i < getNumParameter(); i++) { 114 Collection a = getParameter(i).getModifiers().runtimeVisibleAnnotations(); 115 if (!a.isEmpty()) { 116 foundVisibleAnnotations = true; 117 } 118 annotations.add(a); 119 } 120 if (foundVisibleAnnotations) { 121 c.add(new ParameterAnnotationsAttribute(hostType().constantPool(), annotations, "RuntimeVisibleParameterAnnotations")); 122 } 123 } 124 125 public Collection Modifiers.runtimeVisibleAnnotations() { 126 Collection annotations = new ArrayList(); 127 for (int i = 0; i < getNumModifier(); i++) { 128 if (getModifier(i).isRuntimeVisible()) { 129 annotations.add(getModifier(i)); 130 } 131 } 132 return annotations; 133 } 134 135 // 4.8.18 136 public void MethodDecl.addRuntimeInvisibleParameterAnnotationsAttribute(Collection c) { 137 boolean foundInvisibleAnnotations = false; 138 Collection annotations = new ArrayList(getNumParameter()); 139 for (int i = 0; i < getNumParameter(); i++) { 140 Collection a = getParameter(i).getModifiers().runtimeInvisibleAnnotations(); 141 if (!a.isEmpty()) { 142 foundInvisibleAnnotations = true; 143 } 144 annotations.add(a); 145 } 146 if (foundInvisibleAnnotations) { 147 c.add(new ParameterAnnotationsAttribute(hostType().constantPool(), annotations, "RuntimeInvisibleParameterAnnotations")); 148 } 149 } 150 151 public Collection Modifiers.runtimeInvisibleAnnotations() { 152 Collection annotations = new ArrayList(); 153 for (int i = 0; i < getNumModifier(); i++) { 154 if (getModifier(i).isRuntimeInvisible()) { 155 annotations.add(getModifier(i)); 156 } 157 } 158 return annotations; 159 } 160 161 class ParameterAnnotationsAttribute extends Attribute { 162 public ParameterAnnotationsAttribute(ConstantPool cp, Collection annotations, String name) { 163 super(cp, name); 164 u1(annotations.size()); 165 for (Iterator iter = annotations.iterator(); iter.hasNext(); ) { 166 Collection c = (Collection) iter.next(); 167 for (Iterator inner = c.iterator(); inner.hasNext(); ) { 168 Annotation a = (Annotation) inner.next(); 169 a.appendAsAttributeTo(this); 170 } 171 } 172 } 173 } 174 175 // Add ACC_ANNOTATION flag to generated class file 176 public static final int Modifiers.ACC_ANNOTATION = 0x2000; 177 eq AnnotationDecl.flags() = super.flags() | Modifiers.ACC_ANNOTATION; 178 179 eq AnnotationMethodDecl.attributes() { 180 Collection c = super.attributes(); 181 // 4.8.19 182 if (hasDefaultValue()) { 183 Attribute attribute = new Attribute(hostType().constantPool(), "AnnotationDefault"); 184 getDefaultValue().appendAsAttributeTo(attribute); 185 c.add(attribute); 186 } 187 return c; 188 } 189 190 // 4.8.15 191 public void Annotation.appendAsAttributeTo(Attribute buf) { 192 ConstantPool cp = hostType().constantPool(); 193 String typeDescriptor = decl().typeDescriptor(); 194 int type_index = cp.addUtf8(typeDescriptor); 195 buf.u2(type_index); 196 buf.u2(getNumElementValuePair()); 197 for (int i = 0; i < getNumElementValuePair(); i++) { 198 int name_index = cp.addUtf8(getElementValuePair(i).getName()); 199 buf.u2(name_index); 200 getElementValuePair(i).getElementValue().appendAsAttributeTo(buf); 201 } 202 } 203 204 /** 205 * Add an annotation parameter constant to the constant pool. 206 * @see AST.TypeDecl#addConstant(ConstantPool, Constant) TypeDecl.addConstant(ConstantPool, Constant) 207 */ 208 public int TypeDecl.addAnnotConstant(ConstantPool p, Constant c) { 209 if (isString()) { 210 return p.addUtf8(c.stringValue()); 211 } 212 throw new Error("Not supported"); 213 } 214 public int BooleanType.addAnnotConstant(ConstantPool p, Constant c) { 215 return addConstant(p, c); 216 } 217 public int IntegralType.addAnnotConstant(ConstantPool p, Constant c) { 218 return addConstant(p, c); 219 } 220 public int LongType.addAnnotConstant(ConstantPool p, Constant c) { 221 return addConstant(p, c); 222 } 223 public int FloatType.addAnnotConstant(ConstantPool p, Constant c) { 224 return addConstant(p, c); 225 } 226 public int DoubleType.addAnnotConstant(ConstantPool p, Constant c) { 227 return addConstant(p, c); 228 } 229 230 // 4.8.15.1 231 public void ElementValue.appendAsAttributeTo(Attribute buf) { 232 throw new Error(getClass().getName() + " does not support appendAsAttributeTo(Attribute buf)"); 233 } 234 235 /** 236 * Finds the host type declaration of a class access. 237 * Call this attribute only on expressions that return true for 238 * isClassAccess or it may throw an error! 239 * @return The TypeDecl corresponding to the accesssed class 240 */ 241 syn TypeDecl Expr.classAccess() { 242 throw new Error( 243 "Class access can only be computed for class access expressions"); 244 } 245 246 eq AbstractDot.classAccess() { 247 if (getRight() instanceof ClassAccess) { 248 return getLeft().classAccess(); 249 } else { 250 return getRight().classAccess(); 251 } 252 } 253 254 eq TypeAccess.classAccess() = type(); 255 256 public void ElementConstantValue.appendAsAttributeTo(Attribute buf) { 257 if (getExpr().isConstant() && !getExpr().type().isEnumDecl()) { 258 TypeDecl targetType = declType(); 259 char tag = targetType.isString() ? 's' : targetType.typeDescriptor().charAt(0); 260 int const_value_index = targetType.addAnnotConstant(hostType().constantPool(), getExpr().constant()); 261 buf.u1(tag); 262 buf.u2(const_value_index); 263 } else if (getExpr().isClassAccess()) { 264 int const_class_index = hostType().constantPool().addUtf8(getExpr().classAccess().typeDescriptor()); 265 buf.u1('c'); 266 buf.u2(const_class_index); 267 } else { 268 Variable v = getExpr().varDecl(); 269 if (v == null) { 270 throw new Error("Expected Enumeration constant"); 271 } 272 273 int type_name_index = hostType().constantPool().addUtf8(v.type().typeDescriptor()); 274 int const_name_index = hostType().constantPool().addUtf8(v.name()); 275 buf.u1('e'); 276 buf.u2(type_name_index); 277 buf.u2(const_name_index); 278 } 279 } 280 public void ElementAnnotationValue.appendAsAttributeTo(Attribute buf) { 281 buf.u1('@'); 282 getAnnotation().appendAsAttributeTo(buf); 283 } 284 public void ElementArrayValue.appendAsAttributeTo(Attribute buf) { 285 buf.u1('['); 286 buf.u2(getNumElementValue()); 287 for (int i = 0; i < getNumElementValue(); i++) { 288 getElementValue(i).appendAsAttributeTo(buf); 289 } 290 } 291 292 inh TypeDecl ElementValue.hostType(); 293 }