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