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 Annotations {
011      // 7.4.1.1 Package Annotations
012    
013      /* Annotations may be used on package declarations, with the restriction that
014      at most one annotated package declaration is permitted for a given package.
015      The manner in which this restriction is enforced must, of necessity, vary
016      from implementation to implementation. The following scheme is strongly
017      recommended for file-system-based implementations: The sole annotated
018      package declaration, if it exists, is placed in a source file called
019      package-info.java in the directory containing the source files for the
020      package. */
021      public void AnnotatedCompilationUnit.nameCheck() {
022        super.nameCheck();
023        if(!relativeName().endsWith("package-info.java"))
024          error("package annotations should be in a file package-info.java");
025      }
026    
027      // 9.6 Annotation Types
028      
029      /* The Identifier in an annotation type declaration specifies the name of the
030      annotation type. A compile-time error occurs if an annotation type has the same
031      simple name as any of its enclosing classes or interfaces.
032      Comment: This is common for all type declarations and need thus no specific
033      implementation. */
034    
035      // 9.6.1.1
036    
037      /* If an annotation a on an annotation declaration corresponds to an
038      annotation type T, and T has a (meta-)annotation m that corresponds to
039      annotation.Target, then m must have either an element whose matches the 
040      annotated declaration, or a compile-time error occurs.*/
041      public void Annotation.checkModifiers() {
042        super.checkModifiers();
043        if(decl() instanceof AnnotationDecl) {
044          AnnotationDecl T = (AnnotationDecl)decl();
045          Annotation m = T.annotation(lookupType("java.lang.annotation", "Target"));
046          if(m != null && m.getNumElementValuePair() == 1 && m.getElementValuePair(0).getName().equals("value")) {
047            ElementValue v = m.getElementValuePair(0).getElementValue();
048            //System.out.println("ElementValue: \n" + v.dumpTree());
049            //System.out.println("Annotation: \n" + dumpTree());
050            if(!v.validTarget(this))
051              error("annotation type " + T.typeName() + " is not applicable to this kind of declaration");
052          }
053        }
054      }
055      inh TypeDecl Annotation.lookupType(String packageName, String typeName);
056      inh TypeDecl Modifiers.lookupType(String packageName, String typeName);
057      syn boolean ElementValue.validTarget(Annotation a) = false;
058      eq ElementConstantValue.validTarget(Annotation a) {
059        Variable v = getExpr().varDecl();
060        if(v == null) return true;
061        return v.hostType().fullName().equals("java.lang.annotation.ElementType") && a.mayUseAnnotationTarget(v.name());
062      }
063      eq ElementArrayValue.validTarget(Annotation a) {
064        for(int i = 0;  i < getNumElementValue(); i++)
065          if(getElementValue(i).validTarget(a))
066            return true;
067        return false;
068      }
069      inh boolean Annotation.mayUseAnnotationTarget(String name);
070      // 7.4.1
071      eq AnnotatedCompilationUnit.getModifiers().mayUseAnnotationTarget(String name) =
072        name.equals("PACKAGE");
073      // 8.1.1, 9.1.1
074      eq TypeDecl.getModifiers().mayUseAnnotationTarget(String name) =
075        name.equals("TYPE");
076      // 9.6
077      eq AnnotationDecl.getModifiers().mayUseAnnotationTarget(String name) =
078        name.equals("ANNOTATION_TYPE") || name.equals("TYPE");
079      // 8.3.1, 9.3, 8.9
080      eq FieldDeclaration.getModifiers().mayUseAnnotationTarget(String name) =
081        name.equals("FIELD");
082      // 8.4.1
083      eq ParameterDeclaration.getModifiers().mayUseAnnotationTarget(String name) =
084        name.equals("PARAMETER");
085      // 8.4.3, 9.4
086      eq MethodDecl.getModifiers().mayUseAnnotationTarget(String name) =
087        name.equals("METHOD");
088      // 8.8.3
089      eq ConstructorDecl.getModifiers().mayUseAnnotationTarget(String name) =
090        name.equals("CONSTRUCTOR");
091      // 14.4
092      eq VariableDeclaration.getModifiers().mayUseAnnotationTarget(String name) =
093        name.equals("LOCAL_VARIABLE");
094      eq Program.getChild().mayUseAnnotationTarget(String name) = false;
095      eq ElementAnnotationValue.getAnnotation().mayUseAnnotationTarget(String name) = true;
096    
097      /* The direct superinterface of an annotation type is always
098      annotation.Annotation.*/
099      syn lazy List AnnotationDecl.getSuperInterfaceIdList() {
100        return new List().add(new TypeAccess("java.lang.annotation", "Annotation"));
101      }
102    
103      public void AnnotationDecl.typeCheck() {
104        super.typeCheck();
105        for(int i = 0; i < getNumBodyDecl(); i++) {
106          if(getBodyDecl(i) instanceof MethodDecl) {
107            MethodDecl m = (MethodDecl)getBodyDecl(i);
108            if(!m.type().isValidAnnotationMethodReturnType())
109              m.error("invalid type for annotation member");
110            if(m.annotationMethodOverride())
111              m.error("annotation method overrides " + m.signature());
112          }
113        }
114        if(containsElementOf(this))
115          error("cyclic annotation element type");
116      }
117      /* It is a compile-time error if the return type of a method declared in an
118      annotation type is any type other than one of the following: one of the
119      primitive types, String, Class and any invocation of Class, an enum type
120      (�8.9), an annotation type, or an array (�10) of one of the preceding types.*/
121      syn boolean TypeDecl.isValidAnnotationMethodReturnType() = false;
122      eq PrimitiveType.isValidAnnotationMethodReturnType() = true;
123      eq ReferenceType.isValidAnnotationMethodReturnType() {
124        if(isString()) return true;
125        if(fullName().equals("java.lang.Class"))
126          return true;
127        // include generic versions of Class
128        if(erasure().fullName().equals("java.lang.Class"))
129          return true;
130        return false;
131      }
132      eq EnumDecl.isValidAnnotationMethodReturnType() = true;
133      eq ArrayDecl.isValidAnnotationMethodReturnType() = componentType().isValidAnnotationMethodReturnType();
134      eq AnnotationDecl.isValidAnnotationMethodReturnType() = true;
135     
136      /* It is also a compile-time error if any method declared in an annotation type has a
137      signature that is override-equivalent to that of any public or protected method
138      declared in class Object or in the interface annotation.Annotation*/
139      syn boolean MethodDecl.annotationMethodOverride() =
140        !hostType().ancestorMethods(signature()).isEmpty();
141    
142      /* It is a compile-time error if an annotation type T contains an element of
143      type T, either directly or indirectly.*/
144      syn boolean AnnotationDecl.containsElementOf(TypeDecl typeDecl) circular [false] {
145        for(int i = 0; i < getNumBodyDecl(); i++) {
146          if(getBodyDecl(i) instanceof MethodDecl) {
147            MethodDecl m = (MethodDecl)getBodyDecl(i);
148            if(m.type() == typeDecl)
149              return true;
150            if(m.type() instanceof AnnotationDecl && ((AnnotationDecl)m.type()).containsElementOf(typeDecl))
151              return true;
152          }
153        }
154        return false;
155      }
156    
157      /* An ElementValue is used to specify a default value. It is a compile-time error
158      if the type of the element is not commensurate (�9.7) with the default value
159      specified. An ElementValue is always FP-strict (�15.4).*/
160      public void AnnotationMethodDecl.typeCheck() {
161        super.typeCheck();
162        if(hasDefaultValue() && !type().commensurateWith(getDefaultValue()))
163          error(type().typeName() + " is not commensurate with " + getDefaultValue().type().typeName());
164      }
165    
166      // 9.6.1 Predefined Annotation Types
167    
168      // 9.6.1.1 Target
169      public void ElementConstantValue.nameCheck() {
170        if(enclosingAnnotationDecl().fullName().equals("java.lang.annotation.Target")) {
171          Variable v = getExpr().varDecl();
172          if(v != null && v.hostType().fullName().equals("java.lang.annotation.ElementType"))
173            if(lookupElementTypeValue(v.name()) != this)
174              error("repeated annotation target");
175        }
176      }
177      inh ElementValue ElementConstantValue.lookupElementTypeValue(String name);
178      eq ElementArrayValue.getElementValue().lookupElementTypeValue(String name) =
179        definesElementTypeValue(name);
180      eq Program.getChild().lookupElementTypeValue(String name) = null;
181      syn ElementValue ElementValue.definesElementTypeValue(String name) = null;
182      eq ElementConstantValue.definesElementTypeValue(String name) {
183        Variable v = getExpr().varDecl();
184        if(v != null && v.hostType().fullName().equals("java.lang.annotation.ElementType") && v.name().equals(name))
185          return this;
186        return null;
187      }
188      eq ElementArrayValue.definesElementTypeValue(String name) {
189        for(int i = 0; i < getNumElementValue(); i++)
190          if(getElementValue(i).definesElementTypeValue(name) != null)
191            return getElementValue(i).definesElementTypeValue(name);
192        return null;
193      }
194    
195      // 9.6.1.2 Retention TODO
196      
197    
198    
199      // 9.6.1.3 Inherited
200      /* Indicates that an annotation type is automatically inherited.  If an Inherited
201      meta-annotation is present on an annotation type declaration, and the user
202      queries the annotation type on a class declaration, and the class declaration
203      has no annotation for this type, then the class's superclass will automatically
204      be queried for the annotation type.  This process will be repeated until an
205      annotation for this type is found, or the top of the class hierarchy (Object)
206      is reached.  If no superclass has an annotation for this type, then the query
207      will indicate that the class in question has no such annotation.
208    
209      Note that this meta-annotation type has no effect if the annotated type is used
210      to annotate anything other than a class.  Note also that this meta-annotation
211      only causes annotations to be inherited from superclasses; annotations on
212      implemented interfaces have no effect.*/
213    
214      syn Annotation Modifiers.annotation(TypeDecl typeDecl) {
215        for(int i = 0; i < getNumModifier(); i++) {
216          if(getModifier(i) instanceof Annotation) {
217            Annotation a = (Annotation)getModifier(i);
218            if(a.type() == typeDecl)
219              return a;
220          }
221        }
222        return null;
223      }
224    
225      syn Annotation TypeDecl.annotation(TypeDecl typeDecl) =
226        getModifiers().annotation(typeDecl);
227    
228      eq ClassDecl.annotation(TypeDecl typeDecl) {
229        Annotation a = super.annotation(typeDecl);
230        if(a != null) return a;
231        if(hasSuperclass()) {
232          // If the queried annotation is itself annotation with @Inherited then
233          // delegate the query to the superclass
234          if(typeDecl.annotation(lookupType("java.lang.annotation", "Inherited")) != null)
235            return superclass().annotation(typeDecl);
236        }
237        return null;
238      }
239    
240      // 9.6.1.4 Override
241      public void Annotation.checkOverride() {
242        if(decl().fullName().equals("java.lang.Override") && enclosingBodyDecl() instanceof MethodDecl) {
243          MethodDecl m = (MethodDecl)enclosingBodyDecl();
244          if(!m.hostType().isClassDecl())
245            error("override annotation not valid for interface methods");
246          else {
247            boolean found = false;
248            for(Iterator iter = m.hostType().ancestorMethods(m.signature()).iterator(); iter.hasNext(); ) {
249              MethodDecl decl = (MethodDecl)iter.next();
250              if(m.overrides(decl) && decl.hostType().isClassDecl())
251                found = true;
252            }
253            if(!found)
254              error("method does not override a method from its superclass");
255          }
256        }
257      }
258      inh BodyDecl Annotation.enclosingBodyDecl();
259    
260      // 9.6.1.5 SuppressWarnings
261      /* The annotation type SuppressWarnings supports programmer control over warnings
262      otherwise issued by the Java compiler. It contains a single element that is an
263      array of String. If a program declaration is annotated with the annotation
264      @SuppressWarnings(value = {S1, ... , Sk}), then a Java compiler must not report
265      any warning identified by one of S1, ... , Sk if that warning would have been
266      generated as a result of the annotated declaration or any of its parts.
267      Unchecked warnings are identified by the string "unchecked"*/
268      inh boolean Access.withinSuppressWarnings(String s);
269      eq Program.getChild().withinSuppressWarnings(String s) = false;
270    
271      eq TypeDecl.getBodyDecl(int i).withinSuppressWarnings(String s) =
272        getBodyDecl(i).hasAnnotationSuppressWarnings(s) || hasAnnotationSuppressWarnings(s) ||
273        withinSuppressWarnings(s);
274      eq ClassDecl.getSuperClassAccess().withinSuppressWarnings(String s) =
275        hasAnnotationSuppressWarnings(s) || withinSuppressWarnings(s);
276      eq ClassDecl.getImplements().withinSuppressWarnings(String s) =
277        hasAnnotationSuppressWarnings(s) || withinSuppressWarnings(s);
278      eq InterfaceDecl.getSuperInterfaceId().withinSuppressWarnings(String s) =
279        hasAnnotationSuppressWarnings(s) || withinSuppressWarnings(s);
280      inh boolean TypeDecl.withinSuppressWarnings(String s);
281    
282      syn boolean TypeDecl.hasAnnotationSuppressWarnings(String s) = getModifiers().hasAnnotationSuppressWarnings(s);
283      syn boolean BodyDecl.hasAnnotationSuppressWarnings(String s) = false;
284      eq MemberTypeDecl.hasAnnotationSuppressWarnings(String s) = typeDecl().hasAnnotationSuppressWarnings(s);
285      eq MethodDecl.hasAnnotationSuppressWarnings(String s) = getModifiers().hasAnnotationSuppressWarnings(s);
286      eq ConstructorDecl.hasAnnotationSuppressWarnings(String s) = getModifiers().hasAnnotationSuppressWarnings(s);
287      eq FieldDeclaration.hasAnnotationSuppressWarnings(String s) = getModifiers().hasAnnotationSuppressWarnings(s);
288    
289      syn boolean Modifiers.hasAnnotationSuppressWarnings(String s) {
290        Annotation a = annotation(lookupType("java.lang", "SuppressWarnings"));
291        if(a != null && a.getNumElementValuePair() == 1 && a.getElementValuePair(0).getName().equals("value"))
292          return a.getElementValuePair(0).getElementValue().hasValue(s);
293        return false;
294      }
295      syn boolean ElementValue.hasValue(String s) = false;
296      eq ElementConstantValue.hasValue(String s) =
297        getExpr().type().isString() &&
298        getExpr().isConstant() && 
299        getExpr().constant().stringValue().equals(s);
300      eq ElementArrayValue.hasValue(String s) {
301        for(int i = 0;  i < getNumElementValue(); i++)
302          if(getElementValue(i).hasValue(s))
303            return true;
304        return false;
305      }
306    
307      // 9.6.1.6 Deprecated
308      /*A program element annotated @Deprecated is one that programmers are discouraged
309      from using, typically because it is dangerous, or because a better alternative
310      exists. A Java compiler must produce a warning when a deprecated type, method,
311      field, or constructor is used (overridden, invoked, or referenced by name)
312      unless:
313        * The use is within an entity that itself is is annotated with the annotation @Deprecated; or
314        * The declaration and use are both within the same outermost class; or
315        * The use site is within an entity that is annotated to suppress the
316          warning with the annotation @SuppressWarnings("deprecation") 
317      Use of the annotation @Deprecated on a local variable declaration or on a
318      parameter declaration has no effect.*/
319      syn boolean Modifiers.hasDeprecatedAnnotation() = annotation(lookupType("java.lang", "Deprecated")) != null;
320    
321      syn boolean TypeDecl.isDeprecated() = getModifiers().hasDeprecatedAnnotation();
322      syn boolean MemberTypeDecl.isDeprecated() = typeDecl().isDeprecated();
323      syn boolean MethodDecl.isDeprecated() = getModifiers().hasDeprecatedAnnotation();
324      syn boolean ConstructorDecl.isDeprecated() = getModifiers().hasDeprecatedAnnotation();
325      syn boolean FieldDeclaration.isDeprecated() = getModifiers().hasDeprecatedAnnotation();
326      syn boolean BodyDecl.isDeprecated() = false;
327    
328      public void TypeAccess.checkModifiers() {
329        if(decl().isDeprecated() &&
330           !withinDeprecatedAnnotation() &&
331           (hostType() == null || hostType().topLevelType() != decl().topLevelType()) &&
332           !withinSuppressWarnings("deprecation"))
333          warning(decl().typeName() + " has been deprecated");
334      }
335    
336      public void MethodAccess.checkModifiers() {
337        if(decl().isDeprecated() &&
338          !withinDeprecatedAnnotation() &&
339          hostType().topLevelType() != decl().hostType().topLevelType() &&
340          !withinSuppressWarnings("deprecation"))
341            warning(decl().signature() + " in " + decl().hostType().typeName() + " has been deprecated");
342      }
343    
344      public void VarAccess.checkModifiers() {
345        if(decl() instanceof FieldDeclaration) {
346          FieldDeclaration f = (FieldDeclaration)decl();
347          if(f.isDeprecated() &&
348            !withinDeprecatedAnnotation() &&
349            hostType().topLevelType() != f.hostType().topLevelType() &&
350            !withinSuppressWarnings("deprecation"))
351              warning(f.name() + " in " + f.hostType().typeName() + " has been deprecated");
352        }
353      }
354    
355      public void ConstructorAccess.checkModifiers() {
356        if(decl().isDeprecated() &&
357          !withinDeprecatedAnnotation() &&
358          hostType().topLevelType() != decl().hostType().topLevelType() &&
359          !withinSuppressWarnings("deprecation"))
360            warning(decl().signature() + " in " + decl().hostType().typeName() + " has been deprecated");
361      }
362    
363      public void ClassInstanceExpr.checkModifiers() {
364        if(decl().isDeprecated() &&
365          !withinDeprecatedAnnotation() &&
366          hostType().topLevelType() != decl().hostType().topLevelType() &&
367          !withinSuppressWarnings("deprecation"))
368            warning(decl().signature() + " in " + decl().hostType().typeName() + " has been deprecated");
369      }
370    
371      eq Program.getChild().withinDeprecatedAnnotation() = false;
372      inh boolean Access.withinDeprecatedAnnotation();
373    
374      eq TypeDecl.getBodyDecl(int i).withinDeprecatedAnnotation() =
375        getBodyDecl(i).isDeprecated() || isDeprecated() || withinDeprecatedAnnotation();
376      eq ClassDecl.getSuperClassAccess().withinDeprecatedAnnotation() = isDeprecated() || withinDeprecatedAnnotation();
377      eq ClassDecl.getImplements().withinDeprecatedAnnotation() = isDeprecated() || withinDeprecatedAnnotation();
378      eq InterfaceDecl.getSuperInterfaceId().withinDeprecatedAnnotation() = isDeprecated() || withinDeprecatedAnnotation();
379      inh boolean TypeDecl.withinDeprecatedAnnotation();
380    
381      // 9.7 Annotations
382    
383      public void Annotation.typeCheck() {
384        if(!decl().isAnnotationDecl()) {
385          /* TypeName names the annotation type corresponding to the annotation. It is a
386          compile-time error if TypeName does not name an annotation type.*/
387          if(!decl().isUnknown())
388            error(decl().typeName() + " is not an annotation type");
389        } else {
390          TypeDecl typeDecl = decl();
391          /* It is a compile-time error if a declaration is annotated with more than one
392          annotation for a given annotation type.*/
393          if(lookupAnnotation(typeDecl) != this)
394            error("duplicate annotation " + typeDecl.typeName());
395          /* Annotations must contain an element-value pair for every element of the
396          corresponding annotation type, except for those elements with default
397          values, or a compile-time error occurs. Annotations may, but are not
398          required to, contain element-value pairs for elements with default values.*/
399          for(int i = 0; i < typeDecl.getNumBodyDecl(); i++) {
400            if(typeDecl.getBodyDecl(i) instanceof MethodDecl) {
401              MethodDecl decl = (MethodDecl)typeDecl.getBodyDecl(i);
402              if(elementValueFor(decl.name()) == null && (!(decl instanceof AnnotationMethodDecl) || !((AnnotationMethodDecl)decl).hasDefaultValue()))
403                error("missing value for " + decl.name());
404            }
405          }
406          /* The Identifier in an ElementValuePair must be the simple name of one of the
407          elements of the annotation type identified by TypeName in the containing
408          annotation. Otherwise, a compile-time error occurs. (In other words, the
409          identifier in an element-value pair must also be a method name in the interface
410          identified by TypeName.) */
411          for(int i = 0; i < getNumElementValuePair(); i++) {
412            ElementValuePair pair = getElementValuePair(i);
413            if(typeDecl.memberMethods(pair.getName()).isEmpty())
414              error("can not find element named " + pair.getName() + " in " + typeDecl.typeName());
415          }
416        }
417        checkOverride();
418      }
419    
420      syn lazy TypeDecl Annotation.decl() = getAccess().type();
421    
422      inh Annotation Annotation.lookupAnnotation(TypeDecl typeDecl);
423      inh Annotation ElementAnnotationValue.lookupAnnotation(TypeDecl typeDecl);
424      eq Modifiers.getModifier(int index).lookupAnnotation(TypeDecl typeDecl) {
425        return annotation(typeDecl);
426      }
427      eq ElementAnnotationValue.getAnnotation().lookupAnnotation(TypeDecl typeDecl) =
428        getAnnotation().type() == typeDecl ? getAnnotation() : lookupAnnotation(typeDecl);
429    
430      eq Program.getChild(int i).lookupAnnotation(TypeDecl typeDecl) = null;
431    
432      syn ElementValue Annotation.elementValueFor(String name) {
433        for(int i = 0; i < getNumElementValuePair(); i++) {
434          ElementValuePair pair = getElementValuePair(i);
435          if(pair.getName().equals(name))
436            return pair.getElementValue();
437        }
438        return null;
439      }
440    
441      /* The annotation type named by an annotation must be accessible (�6.6) at the
442      point where the annotation is used, or a compile-time error occurs.
443      Comment: This is done by the access control framework*/
444    
445      /**
446       * The return type of this method defines the element type of the element-value
447       * pair. An ElementValueArrayInitializer is similar to a normal array initializer
448       * (�10.6), except that annotations are permitted in place of expressions.
449       */
450      syn lazy TypeDecl ElementValuePair.type() {
451        Map methodMap = enclosingAnnotationDecl().localMethodsSignatureMap();
452        MethodDecl method = (MethodDecl) methodMap.get(getName()+"()");
453        if (method != null)
454          return method.type();
455        else
456          return unknownType();
457      }
458      inh TypeDecl ElementValuePair.unknownType();
459    
460      inh TypeDecl ElementValuePair.enclosingAnnotationDecl();
461      inh TypeDecl ElementValue.enclosingAnnotationDecl();
462      eq Annotation.getElementValuePair().enclosingAnnotationDecl() = decl();
463      eq Program.getChild().enclosingAnnotationDecl() = unknownType();
464        
465      /* An element type T is commensurate with an element value V if and only if one of the following conditions is true:
466        * T is an array type E[] and either:
467              o V is an ElementValueArrayInitializer and each ElementValueInitializer (analogous to a variable initializer in an array initializer) in V is commensurate with E. Or
468              o V is an ElementValue that is commensurate with T. 
469        * The type of V is assignment compatible (�5.2) with T and, furthermore:
470              o If T is a primitive type or String, V is a constant expression (�15.28).
471              o V is not null.
472              o if T is Class, or an invocation of Class, and V is a class literal (�15.8.2).
473              o If T is an enum type, and V is an enum constant. */
474      syn boolean TypeDecl.commensurateWith(ElementValue value) = value.commensurateWithTypeDecl(this);
475      syn boolean ElementValue.commensurateWithTypeDecl(TypeDecl type) = false;
476      eq ElementConstantValue.commensurateWithTypeDecl(TypeDecl type) {
477        Expr v = getExpr();
478        if(!v.type().assignConversionTo(type, v))
479          return false;
480        if((type.isPrimitive() || type.isString()) && !v.isConstant())
481          return false;
482        if(v.type().isNull())
483          return false;
484        if(type.fullName().equals("java.lang.Class") && !v.isClassAccess())
485          return false;
486        if(type.isEnumDecl() && (v.varDecl() == null || !(v.varDecl() instanceof EnumConstant)))
487          return false;
488        return true;
489      }
490      eq ElementAnnotationValue.commensurateWithTypeDecl(TypeDecl type) {
491        return type() == type;
492      }
493    
494      eq ArrayDecl.commensurateWith(ElementValue value) = value.commensurateWithArrayDecl(this);
495      syn boolean ElementValue.commensurateWithArrayDecl(ArrayDecl type) = 
496        type.componentType().commensurateWith(this);
497      eq ElementArrayValue.commensurateWithArrayDecl(ArrayDecl type) {
498        for(int i = 0; i < getNumElementValue(); i++)
499          if(!type.componentType().commensurateWith(getElementValue(i)))
500            return false;
501        return true;
502      }
503      /* It is a compile-time error if the element type is not commensurate with the ElementValue.*/
504      public void ElementValuePair.typeCheck() {
505        if(!type().commensurateWith(getElementValue()))
506          error("can not construct annotation with " + getName() +
507              " = " + getElementValue().toString() + "; " + type().typeName() +
508              " is not commensurate with " + getElementValue().type().typeName());
509      }
510      syn TypeDecl ElementValue.type() = unknownType();
511      eq ElementConstantValue.type() = getExpr().type();
512      eq ElementAnnotationValue.type() = getAnnotation().type();
513    
514      syn TypeDecl Annotation.type() = getAccess().type();
515      inh TypeDecl ElementValue.unknownType();
516    
517      /* If the element type is not an annotation type or an array type, ElementValue
518      must be a ConditionalExpression (�15.25)
519      TODO: How to enforce this. Is this already enforced?
520      */
521    
522      /* If the element type is an array type and the corresponding ElementValue is not
523      an ElementValueArrayInitializer, an array value whose sole element is the value
524      represented by the ElementValue is associated with the element. Otherwise, the
525      value represented by ElementValue is associated with the element. */
526      rewrite ElementValuePair {
527        when(type().isArrayDecl() && getElementValue() instanceof ElementConstantValue)
528        to ElementValuePair {
529          setElementValue(new ElementArrayValue(new List().add(getElementValue())));
530          return this;
531        }
532      }
533    
534      /* An annotation on an annotation type declaration is known as a meta-annotation.
535      An annotation type may be used to annotate its own declaration. More generally,
536      circularities in the transitive closure of the "annotates" relation are
537      permitted. For example, it is legal to annotate an annotation type declaration
538      with another annotation type, and to annotate the latter type's declaration
539      with the former type. (The pre-defined meta-annotation types contain several
540      such circularities.)
541      Comment: no problems with reference attributes.
542      */
543      syn boolean Annotation.isMetaAnnotation() = hostType().isAnnotationDecl();
544      inh TypeDecl Annotation.hostType();
545      syn boolean TypeDecl.isAnnotationDecl() = false;
546      eq AnnotationDecl.isAnnotationDecl() = true;
547    
548      // name binding
549      eq Annotation.getAccess().nameType() = NameType.TYPE_NAME;
550      eq ElementConstantValue.getExpr().nameType() = NameType.AMBIGUOUS_NAME;
551      
552      eq AnnotatedCompilationUnit.getModifiers().hostPackage() = packageName();
553    
554      // provide error message for method calls in 
555      eq ElementConstantValue.getExpr().methodHost() = enclosingAnnotationDecl().typeName();
556    
557      public void AnnotatedCompilationUnit.toString(StringBuffer s) {
558          getModifiers().toString(s);
559          super.toString(s);
560      }
561    
562      public void AnnotationDecl.toString(StringBuffer s) {
563        getModifiers().toString(s);
564        s.append("@interface " + name());
565        s.append(" {");
566        for(int i=0; i < getNumBodyDecl(); i++) {
567          getBodyDecl(i).toString(s);
568        }
569        s.append(indent() + "}");
570      }
571      public void AnnotationMethodDecl.toString(StringBuffer s) {
572        s.append(indent());
573        getModifiers().toString(s);
574        getTypeAccess().toString(s);
575        s.append(" " + name() + "()");
576        if(hasDefaultValue()) {
577          s.append(" default ");
578          getDefaultValue().toString(s);
579        }
580        s.append(";\n");
581      }
582      public void Annotation.toString(StringBuffer s) {
583        s.append("@");
584        getAccess().toString(s);
585        s.append("(");
586        for(int i = 0; i < getNumElementValuePair(); i++) {
587          if(i != 0)
588            s.append(", ");
589          getElementValuePair(i).toString(s);
590        }
591        s.append(")");
592      }
593      public void ElementValuePair.toString(StringBuffer s) {
594        s.append(getName() + " = ");
595        getElementValue().toString(s);
596      }
597      public void ElementConstantValue.toString(StringBuffer s) {
598        getExpr().toString(s);
599      }
600      public void ElementAnnotationValue.toString(StringBuffer s) {
601        getAnnotation().toString(s);
602      }
603      public void ElementArrayValue.toString(StringBuffer s) {
604        s.append("{");
605        for(int i = 0; i < getNumElementValue(); i++) {
606          getElementValue(i).toString(s);
607          s.append(", ");
608        }
609        s.append("}");
610      }
611    
612    }