src/share/classes/com/sun/tools/javac/comp/Annotate.java

Thu, 02 Oct 2008 19:58:40 -0700

author
xdono
date
Thu, 02 Oct 2008 19:58:40 -0700
changeset 117
24a47c3062fe
parent 113
eff38cc97183
child 554
9d9f26857129
permissions
-rw-r--r--

6754988: Update copyright year
Summary: Update for files that have been modified starting July 2008
Reviewed-by: ohair, tbell

     1 /*
     2  * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.javac.comp;
    28 import com.sun.tools.javac.util.*;
    29 import com.sun.tools.javac.code.*;
    30 import com.sun.tools.javac.code.Symbol.*;
    31 import com.sun.tools.javac.tree.*;
    32 import com.sun.tools.javac.tree.JCTree.*;
    34 /** Enter annotations on symbols.  Annotations accumulate in a queue,
    35  *  which is processed at the top level of any set of recursive calls
    36  *  requesting it be processed.
    37  *
    38  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    39  *  you write code that depends on this, you do so at your own risk.
    40  *  This code and its internal interfaces are subject to change or
    41  *  deletion without notice.</b>
    42  */
    43 public class Annotate {
    44     protected static final Context.Key<Annotate> annotateKey =
    45         new Context.Key<Annotate>();
    47     public static Annotate instance(Context context) {
    48         Annotate instance = context.get(annotateKey);
    49         if (instance == null)
    50             instance = new Annotate(context);
    51         return instance;
    52     }
    54     final Attr attr;
    55     final TreeMaker make;
    56     final Log log;
    57     final Symtab syms;
    58     final Names names;
    59     final Resolve rs;
    60     final Types types;
    61     final ConstFold cfolder;
    62     final Check chk;
    64     protected Annotate(Context context) {
    65         context.put(annotateKey, this);
    66         attr = Attr.instance(context);
    67         make = TreeMaker.instance(context);
    68         log = Log.instance(context);
    69         syms = Symtab.instance(context);
    70         names = Names.instance(context);
    71         rs = Resolve.instance(context);
    72         types = Types.instance(context);
    73         cfolder = ConstFold.instance(context);
    74         chk = Check.instance(context);
    75     }
    77 /* ********************************************************************
    78  * Queue maintenance
    79  *********************************************************************/
    81     private int enterCount = 0;
    83     ListBuffer<Annotator> q = new ListBuffer<Annotator>();
    85     public void later(Annotator a) {
    86         q.append(a);
    87     }
    89     public void earlier(Annotator a) {
    90         q.prepend(a);
    91     }
    93     /** Called when the Enter phase starts. */
    94     public void enterStart() {
    95         enterCount++;
    96     }
    98     /** Called after the Enter phase completes. */
    99     public void enterDone() {
   100         enterCount--;
   101         flush();
   102     }
   104     public void flush() {
   105         if (enterCount != 0) return;
   106         enterCount++;
   107         try {
   108             while (q.nonEmpty())
   109                 q.next().enterAnnotation();
   110         } finally {
   111             enterCount--;
   112         }
   113     }
   115     /** A client that has annotations to add registers an annotator,
   116      *  the method it will use to add the annotation.  There are no
   117      *  parameters; any needed data should be captured by the
   118      *  Annotator.
   119      */
   120     public interface Annotator {
   121         void enterAnnotation();
   122         String toString();
   123     }
   126 /* ********************************************************************
   127  * Compute an attribute from its annotation.
   128  *********************************************************************/
   130     /** Process a single compound annotation, returning its
   131      *  Attribute. Used from MemberEnter for attaching the attributes
   132      *  to the annotated symbol.
   133      */
   134     Attribute.Compound enterAnnotation(JCAnnotation a,
   135                                        Type expected,
   136                                        Env<AttrContext> env) {
   137         // The annotation might have had its type attributed (but not checked)
   138         // by attr.attribAnnotationTypes during MemberEnter, in which case we do not
   139         // need to do it again.
   140         Type at = (a.annotationType.type != null ? a.annotationType.type
   141                   : attr.attribType(a.annotationType, env));
   142         a.type = chk.checkType(a.annotationType.pos(), at, expected);
   143         if (a.type.isErroneous())
   144             return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
   145         if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) {
   146             log.error(a.annotationType.pos(),
   147                       "not.annotation.type", a.type.toString());
   148             return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
   149         }
   150         List<JCExpression> args = a.args;
   151         if (args.length() == 1 && args.head.getTag() != JCTree.ASSIGN) {
   152             // special case: elided "value=" assumed
   153             args.head = make.at(args.head.pos).
   154                 Assign(make.Ident(names.value), args.head);
   155         }
   156         ListBuffer<Pair<MethodSymbol,Attribute>> buf =
   157             new ListBuffer<Pair<MethodSymbol,Attribute>>();
   158         for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
   159             JCExpression t = tl.head;
   160             if (t.getTag() != JCTree.ASSIGN) {
   161                 log.error(t.pos(), "annotation.value.must.be.name.value");
   162                 continue;
   163             }
   164             JCAssign assign = (JCAssign)t;
   165             if (assign.lhs.getTag() != JCTree.IDENT) {
   166                 log.error(t.pos(), "annotation.value.must.be.name.value");
   167                 continue;
   168             }
   169             JCIdent left = (JCIdent)assign.lhs;
   170             Symbol method = rs.resolveQualifiedMethod(left.pos(),
   171                                                       env,
   172                                                       a.type,
   173                                                       left.name,
   174                                                       List.<Type>nil(),
   175                                                       null);
   176             left.sym = method;
   177             left.type = method.type;
   178             if (method.owner != a.type.tsym)
   179                 log.error(left.pos(), "no.annotation.member", left.name, a.type);
   180             Type result = method.type.getReturnType();
   181             Attribute value = enterAttributeValue(result, assign.rhs, env);
   182             if (!method.type.isErroneous())
   183                 buf.append(new Pair<MethodSymbol,Attribute>
   184                            ((MethodSymbol)method, value));
   185         }
   186         return new Attribute.Compound(a.type, buf.toList());
   187     }
   189     Attribute enterAttributeValue(Type expected,
   190                                   JCExpression tree,
   191                                   Env<AttrContext> env) {
   192         if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) {
   193             Type result = attr.attribExpr(tree, env, expected);
   194             if (result.isErroneous())
   195                 return new Attribute.Error(expected);
   196             if (result.constValue() == null) {
   197                 log.error(tree.pos(), "attribute.value.must.be.constant");
   198                 return new Attribute.Error(expected);
   199             }
   200             result = cfolder.coerce(result, expected);
   201             return new Attribute.Constant(expected, result.constValue());
   202         }
   203         if (expected.tsym == syms.classType.tsym) {
   204             Type result = attr.attribExpr(tree, env, expected);
   205             if (result.isErroneous())
   206                 return new Attribute.Error(expected);
   207             if (TreeInfo.name(tree) != names._class) {
   208                 log.error(tree.pos(), "annotation.value.must.be.class.literal");
   209                 return new Attribute.Error(expected);
   210             }
   211             return new Attribute.Class(types,
   212                                        (((JCFieldAccess) tree).selected).type);
   213         }
   214         if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) {
   215             if (tree.getTag() != JCTree.ANNOTATION) {
   216                 log.error(tree.pos(), "annotation.value.must.be.annotation");
   217                 expected = syms.errorType;
   218             }
   219             return enterAnnotation((JCAnnotation)tree, expected, env);
   220         }
   221         if (expected.tag == TypeTags.ARRAY) { // should really be isArray()
   222             if (tree.getTag() != JCTree.NEWARRAY) {
   223                 tree = make.at(tree.pos).
   224                     NewArray(null, List.<JCExpression>nil(), List.of(tree));
   225             }
   226             JCNewArray na = (JCNewArray)tree;
   227             if (na.elemtype != null) {
   228                 log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
   229                 return new Attribute.Error(expected);
   230             }
   231             ListBuffer<Attribute> buf = new ListBuffer<Attribute>();
   232             for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
   233                 buf.append(enterAttributeValue(types.elemtype(expected),
   234                                                l.head,
   235                                                env));
   236             }
   237             return new Attribute.
   238                 Array(expected, buf.toArray(new Attribute[buf.length()]));
   239         }
   240         if (expected.tag == TypeTags.CLASS &&
   241             (expected.tsym.flags() & Flags.ENUM) != 0) {
   242             attr.attribExpr(tree, env, expected);
   243             Symbol sym = TreeInfo.symbol(tree);
   244             if (sym == null ||
   245                 TreeInfo.nonstaticSelect(tree) ||
   246                 sym.kind != Kinds.VAR ||
   247                 (sym.flags() & Flags.ENUM) == 0) {
   248                 log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
   249                 return new Attribute.Error(expected);
   250             }
   251             VarSymbol enumerator = (VarSymbol) sym;
   252             return new Attribute.Enum(expected, enumerator);
   253         }
   254         if (!expected.isErroneous())
   255             log.error(tree.pos(), "annotation.value.not.allowable.type");
   256         return new Attribute.Error(attr.attribExpr(tree, env, expected));
   257     }
   258 }

mercurial