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

Tue, 28 Dec 2010 15:54:52 -0800

author
ohair
date
Tue, 28 Dec 2010 15:54:52 -0800
changeset 798
4868a36f6fd8
parent 676
bfdfc13fe641
child 992
dc3d9ef880a1
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

     1 /*
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * 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 supported API.
    39  *  If 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             t.type = result;
   186         }
   187         return new Attribute.Compound(a.type, buf.toList());
   188     }
   190     Attribute enterAttributeValue(Type expected,
   191                                   JCExpression tree,
   192                                   Env<AttrContext> env) {
   193         if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) {
   194             Type result = attr.attribExpr(tree, env, expected);
   195             if (result.isErroneous())
   196                 return new Attribute.Error(expected);
   197             if (result.constValue() == null) {
   198                 log.error(tree.pos(), "attribute.value.must.be.constant");
   199                 return new Attribute.Error(expected);
   200             }
   201             result = cfolder.coerce(result, expected);
   202             return new Attribute.Constant(expected, result.constValue());
   203         }
   204         if (expected.tsym == syms.classType.tsym) {
   205             Type result = attr.attribExpr(tree, env, expected);
   206             if (result.isErroneous())
   207                 return new Attribute.Error(expected);
   208             if (TreeInfo.name(tree) != names._class) {
   209                 log.error(tree.pos(), "annotation.value.must.be.class.literal");
   210                 return new Attribute.Error(expected);
   211             }
   212             return new Attribute.Class(types,
   213                                        (((JCFieldAccess) tree).selected).type);
   214         }
   215         if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) {
   216             if (tree.getTag() != JCTree.ANNOTATION) {
   217                 log.error(tree.pos(), "annotation.value.must.be.annotation");
   218                 expected = syms.errorType;
   219             }
   220             return enterAnnotation((JCAnnotation)tree, expected, env);
   221         }
   222         if (expected.tag == TypeTags.ARRAY) { // should really be isArray()
   223             if (tree.getTag() != JCTree.NEWARRAY) {
   224                 tree = make.at(tree.pos).
   225                     NewArray(null, List.<JCExpression>nil(), List.of(tree));
   226             }
   227             JCNewArray na = (JCNewArray)tree;
   228             if (na.elemtype != null) {
   229                 log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
   230                 return new Attribute.Error(expected);
   231             }
   232             ListBuffer<Attribute> buf = new ListBuffer<Attribute>();
   233             for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
   234                 buf.append(enterAttributeValue(types.elemtype(expected),
   235                                                l.head,
   236                                                env));
   237             }
   238             na.type = expected;
   239             return new Attribute.
   240                 Array(expected, buf.toArray(new Attribute[buf.length()]));
   241         }
   242         if (expected.tag == TypeTags.CLASS &&
   243             (expected.tsym.flags() & Flags.ENUM) != 0) {
   244             attr.attribExpr(tree, env, expected);
   245             Symbol sym = TreeInfo.symbol(tree);
   246             if (sym == null ||
   247                 TreeInfo.nonstaticSelect(tree) ||
   248                 sym.kind != Kinds.VAR ||
   249                 (sym.flags() & Flags.ENUM) == 0) {
   250                 log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
   251                 return new Attribute.Error(expected);
   252             }
   253             VarSymbol enumerator = (VarSymbol) sym;
   254             return new Attribute.Enum(expected, enumerator);
   255         }
   256         if (!expected.isErroneous())
   257             log.error(tree.pos(), "annotation.value.not.allowable.type");
   258         return new Attribute.Error(attr.attribExpr(tree, env, expected));
   259     }
   260 }

mercurial