Coverage Report - com.sun.tools.javafx.comp.JavafxAnnotate
 
Classes in this File Line Coverage Branch Coverage Complexity
JavafxAnnotate
27%
29/108
8%
5/66
0
JavafxAnnotate$Annotator
N/A
N/A
0
 
 1  
 /*
 2  
  * Copyright 2003-2007 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  
  */
 25  
 
 26  
 package com.sun.tools.javafx.comp;
 27  
 
 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.*;
 33  
 
 34  
 import com.sun.tools.javafx.tree.JavafxTreeMaker;
 35  
 import com.sun.tools.javafx.comp.JavafxAttr.Sequenceness;
 36  
 import com.sun.tools.javafx.util.MsgSym;
 37  
 
 38  
 /** Enter annotations on symbols.  Annotations accumulate in a queue,
 39  
  *  which is processed at the top level of any set of recursive calls
 40  
  *  requesting it be processed.
 41  
  *
 42  
  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
 43  
  *  you write code that depends on this, you do so at your own risk.
 44  
  *  This code and its internal interfaces are subject to change or
 45  
  *  deletion without notice.</b>
 46  
  */
 47  
 public class JavafxAnnotate {
 48  12
     protected static final Context.Key<JavafxAnnotate> javafxAnnotateKey =
 49  
         new Context.Key<JavafxAnnotate>();
 50  
 
 51  
     public static JavafxAnnotate instance(Context context) {
 52  1197
         JavafxAnnotate instance = context.get(javafxAnnotateKey);
 53  1197
         if (instance == null)
 54  399
             instance = new JavafxAnnotate(context);
 55  1197
         return instance;
 56  
     }
 57  
 
 58  
     final JavafxAttr attr;
 59  
     final TreeMaker make;
 60  
     final Log log;
 61  
     final Symtab syms;
 62  
     final Name.Table names;
 63  
     final JavafxResolve rs;
 64  
     final Types types;
 65  
 //TODO:?    final ConstFold cfolder;
 66  
     final JavafxCheck chk;
 67  
 
 68  399
     protected JavafxAnnotate(Context context) {
 69  399
         context.put(javafxAnnotateKey, this);
 70  399
         attr = JavafxAttr.instance(context);
 71  399
         make = JavafxTreeMaker.instance(context);
 72  399
         log = Log.instance(context);
 73  399
         syms = Symtab.instance(context);
 74  399
         names = Name.Table.instance(context);
 75  399
         rs = JavafxResolve.instance(context);
 76  399
         types = Types.instance(context);
 77  
 //TODO:?        cfolder = ConstFold.instance(context);
 78  399
         chk = (JavafxCheck)JavafxCheck.instance(context);
 79  399
     }
 80  
 
 81  
 /* ********************************************************************
 82  
  * Queue maintenance
 83  
  *********************************************************************/
 84  
 
 85  399
     private int enterCount = 0;
 86  
 
 87  399
     ListBuffer<Annotator> q = new ListBuffer<Annotator>();
 88  
 
 89  
     public void later(Annotator a) {
 90  0
         q.append(a);
 91  0
     }
 92  
 
 93  
     public void earlier(Annotator a) {
 94  0
         q.prepend(a);
 95  0
     }
 96  
 
 97  
     /** Called when the Enter phase starts. */
 98  
     public void enterStart() {
 99  383
         enterCount++;
 100  383
     }
 101  
 
 102  
     /** Called after the Enter phase completes. */
 103  
     public void enterDone() {
 104  383
         enterCount--;
 105  383
         flush();
 106  383
     }
 107  
 
 108  
     public void flush() {
 109  1018
         if (enterCount != 0) return;
 110  409
         enterCount++;
 111  
         try {
 112  409
             while (q.nonEmpty())
 113  0
                 q.next().enterAnnotation();
 114  
         } finally {
 115  409
             enterCount--;
 116  409
         }
 117  409
     }
 118  
 
 119  
     /** A client that has annotations to add registers an annotator,
 120  
      *  the method it will use to add the annotation.  There are no
 121  
      *  parameters; any needed data should be captured by the
 122  
      *  Annotator.
 123  
      */
 124  
     public interface Annotator {
 125  
         void enterAnnotation();
 126  
         String toString();
 127  
     }
 128  
 
 129  
 
 130  
 /* ********************************************************************
 131  
  * Compute an attribute from its annotation.
 132  
  *********************************************************************/
 133  
 
 134  
     /** Process a single compound annotation, returning its
 135  
      *  Attribute. Used from MemberEnter for attaching the attributes
 136  
      *  to the annotated symbol.
 137  
      */
 138  
     Attribute.Compound enterAnnotation(JCAnnotation a,
 139  
                                        Type expected,
 140  
                                        JavafxEnv<JavafxAttrContext> env) {
 141  
         // The annotation might have had its type attributed (but not checked)
 142  
         // by attr.attribAnnotationTypes during MemberEnter, in which case we do not
 143  
         // need to do it again.
 144  0
         Type at = (a.annotationType.type != null ? a.annotationType.type
 145  
                   : attr.attribType(a.annotationType, env));
 146  0
         a.type = chk.checkType(a.annotationType.pos(), at, expected, Sequenceness.DISALLOWED);
 147  0
         if (a.type.isErroneous())
 148  0
             return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
 149  0
         if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) {
 150  0
             log.error(a.annotationType.pos(), 
 151  
                       MsgSym.MESSAGE_NOT_ANNOTATION_TYPE, a.type.toString());
 152  0
             return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
 153  
         }
 154  0
         List<JCExpression> args = a.args;
 155  0
         if (args.length() == 1 && args.head.getTag() != JCTree.ASSIGN) {
 156  
             // special case: elided "value=" assumed
 157  0
             args.head = make.at(args.head.pos).
 158  
                 Assign(make.Ident(names.value), args.head);
 159  
         }
 160  0
         ListBuffer<Pair<MethodSymbol,Attribute>> buf =
 161  
             new ListBuffer<Pair<MethodSymbol,Attribute>>();
 162  0
         for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
 163  0
             JCExpression t = tl.head;
 164  0
             if (t.getTag() != JCTree.ASSIGN) {
 165  0
                 log.error(t.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_NAME_VALUE);
 166  0
                 continue;
 167  
             }
 168  0
             JCAssign assign = (JCAssign)t;
 169  0
             if (assign.lhs.getTag() != JCTree.IDENT) {
 170  0
                 log.error(t.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_NAME_VALUE);
 171  0
                 continue;
 172  
             }
 173  0
             JCIdent left = (JCIdent)assign.lhs;
 174  0
             Symbol method = rs.resolveQualifiedMethod(left.pos(),
 175  
                                                       env,
 176  
                                                       a.type,
 177  
                                                       left.name,
 178  
                                                       rs.newMethTemplate(List.<Type>nil(), null));
 179  0
             left.sym = method;
 180  0
             left.type = method.type;
 181  0
             if (method.owner != a.type.tsym)
 182  0
                 log.error(left.pos(), MsgSym.MESSAGE_NO_ANNOTATION_MEMBER, left.name, a.type);
 183  0
             Type result = method.type.getReturnType();
 184  0
             Attribute value = enterAttributeValue(result, assign.rhs, env);
 185  0
             if (!method.type.isErroneous())
 186  0
                 buf.append(new Pair<MethodSymbol,Attribute>
 187  
                            ((MethodSymbol)method, value));
 188  
         }
 189  0
         return new Attribute.Compound(a.type, buf.toList());
 190  
     }
 191  
 
 192  
     Attribute enterAttributeValue(Type expected,
 193  
                                   JCExpression tree,
 194  
                                   JavafxEnv<JavafxAttrContext> env) {
 195  0
         if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) {
 196  0
             Type result = attr.attribExpr(tree, env, expected);
 197  0
             if (result.isErroneous())
 198  0
                 return new Attribute.Error(expected);
 199  0
             if (result.constValue() == null) {
 200  0
                 log.error(tree.pos(), MsgSym.MESSAGE_ATTRIBUTE_VALUE_MUST_BE_CONSTANT);
 201  0
                 return new Attribute.Error(expected);
 202  
             }
 203  
 //TODO:?            result = cfolder.coerce(result, expected);
 204  0
             return new Attribute.Constant(expected, result.constValue());
 205  
         }
 206  0
         if (expected.tsym == syms.classType.tsym) {
 207  0
             Type result = attr.attribExpr(tree, env, expected);
 208  0
             if (result.isErroneous())
 209  0
                 return new Attribute.Error(expected);
 210  0
             if (TreeInfo.name(tree) != names._class) {
 211  0
                 log.error(tree.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_CLASS_LITERAL);
 212  0
                 return new Attribute.Error(expected);
 213  
             }
 214  0
             return new Attribute.Class(types,
 215  
                                        (((JCFieldAccess) tree).selected).type);
 216  
         }
 217  0
         if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) {
 218  0
             if (tree.getTag() != JCTree.ANNOTATION) {
 219  0
                 log.error(tree.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_ANNOTATION);
 220  0
                 expected = syms.errorType;
 221  
             }
 222  0
             return enterAnnotation((JCAnnotation)tree, expected, env);
 223  
         }
 224  0
         if (expected.tag == TypeTags.ARRAY) { // should really be isArray()
 225  0
             if (tree.getTag() != JCTree.NEWARRAY) {
 226  0
                 tree = make.at(tree.pos).
 227  
                     NewArray(null, List.<JCExpression>nil(), List.of(tree));
 228  
             }
 229  0
             JCNewArray na = (JCNewArray)tree;
 230  0
             if (na.elemtype != null) {
 231  0
                 log.error(na.elemtype.pos(), MsgSym.MESSAGE_NEW_NOT_ALLOWED_IN_ANNOTATION);
 232  0
                 return new Attribute.Error(expected);
 233  
             }
 234  0
             ListBuffer<Attribute> buf = new ListBuffer<Attribute>();
 235  0
             for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
 236  0
                 buf.append(enterAttributeValue(types.elemtype(expected),
 237  
                                                l.head,
 238  
                                                env));
 239  
             }
 240  0
             return new Attribute.
 241  
                 Array(expected, buf.toArray(new Attribute[buf.length()]));
 242  
         }
 243  0
         if (expected.tag == TypeTags.CLASS &&
 244  
             (expected.tsym.flags() & Flags.ENUM) != 0) {
 245  0
             attr.attribExpr(tree, env, expected);
 246  0
             Symbol sym = TreeInfo.symbol(tree);
 247  0
             if (sym == null ||
 248  
                 TreeInfo.nonstaticSelect(tree) ||
 249  
                 sym.kind != Kinds.VAR ||
 250  
                 (sym.flags() & Flags.ENUM) == 0) {
 251  0
                 log.error(tree.pos(), MsgSym.MESSAGE_ENUM_ANNOTATION_MUST_BE_ENUM_CONSTANT);
 252  0
                 return new Attribute.Error(expected);
 253  
             }
 254  0
             VarSymbol enumerator = (VarSymbol) sym;
 255  0
             return new Attribute.Enum(expected, enumerator);
 256  
         }
 257  0
         if (!expected.isErroneous())
 258  0
             log.error(tree.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_NOT_ALLOWABLE_TYPE);
 259  0
         return new Attribute.Error(attr.attribExpr(tree, env, expected));
 260  
     }
 261  
 }