src/share/classes/com/sun/tools/javac/tree/TreeInfo.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 308
03944ee4fac4
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 1999-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.tree;
    28 import com.sun.source.tree.Tree;
    29 import com.sun.tools.javac.comp.AttrContext;
    30 import com.sun.tools.javac.comp.Env;
    31 import java.util.Map;
    32 import com.sun.tools.javac.util.*;
    33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    34 import com.sun.tools.javac.code.*;
    35 import com.sun.tools.javac.tree.JCTree.*;
    37 import static com.sun.tools.javac.code.Flags.*;
    39 /** Utility class containing inspector methods for trees.
    40  *
    41  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    42  *  you write code that depends on this, you do so at your own risk.
    43  *  This code and its internal interfaces are subject to change or
    44  *  deletion without notice.</b>
    45  */
    46 public class TreeInfo {
    47     protected static final Context.Key<TreeInfo> treeInfoKey =
    48         new Context.Key<TreeInfo>();
    50     public static TreeInfo instance(Context context) {
    51         TreeInfo instance = context.get(treeInfoKey);
    52         if (instance == null)
    53             instance = new TreeInfo(context);
    54         return instance;
    55     }
    57     /** The names of all operators.
    58      */
    59     private Name[] opname = new Name[JCTree.MOD - JCTree.POS + 1];
    61     private TreeInfo(Context context) {
    62         context.put(treeInfoKey, this);
    64         Names names = Names.instance(context);
    65         opname[JCTree.POS     - JCTree.POS] = names.fromString("+");
    66         opname[JCTree.NEG     - JCTree.POS] = names.hyphen;
    67         opname[JCTree.NOT     - JCTree.POS] = names.fromString("!");
    68         opname[JCTree.COMPL   - JCTree.POS] = names.fromString("~");
    69         opname[JCTree.PREINC  - JCTree.POS] = names.fromString("++");
    70         opname[JCTree.PREDEC  - JCTree.POS] = names.fromString("--");
    71         opname[JCTree.POSTINC - JCTree.POS] = names.fromString("++");
    72         opname[JCTree.POSTDEC - JCTree.POS] = names.fromString("--");
    73         opname[JCTree.NULLCHK - JCTree.POS] = names.fromString("<*nullchk*>");
    74         opname[JCTree.OR      - JCTree.POS] = names.fromString("||");
    75         opname[JCTree.AND     - JCTree.POS] = names.fromString("&&");
    76         opname[JCTree.EQ      - JCTree.POS] = names.fromString("==");
    77         opname[JCTree.NE      - JCTree.POS] = names.fromString("!=");
    78         opname[JCTree.LT      - JCTree.POS] = names.fromString("<");
    79         opname[JCTree.GT      - JCTree.POS] = names.fromString(">");
    80         opname[JCTree.LE      - JCTree.POS] = names.fromString("<=");
    81         opname[JCTree.GE      - JCTree.POS] = names.fromString(">=");
    82         opname[JCTree.BITOR   - JCTree.POS] = names.fromString("|");
    83         opname[JCTree.BITXOR  - JCTree.POS] = names.fromString("^");
    84         opname[JCTree.BITAND  - JCTree.POS] = names.fromString("&");
    85         opname[JCTree.SL      - JCTree.POS] = names.fromString("<<");
    86         opname[JCTree.SR      - JCTree.POS] = names.fromString(">>");
    87         opname[JCTree.USR     - JCTree.POS] = names.fromString(">>>");
    88         opname[JCTree.PLUS    - JCTree.POS] = names.fromString("+");
    89         opname[JCTree.MINUS   - JCTree.POS] = names.hyphen;
    90         opname[JCTree.MUL     - JCTree.POS] = names.asterisk;
    91         opname[JCTree.DIV     - JCTree.POS] = names.slash;
    92         opname[JCTree.MOD     - JCTree.POS] = names.fromString("%");
    93     }
    96     /** Return name of operator with given tree tag.
    97      */
    98     public Name operatorName(int tag) {
    99         return opname[tag - JCTree.POS];
   100     }
   102     /** Is tree a constructor declaration?
   103      */
   104     public static boolean isConstructor(JCTree tree) {
   105         if (tree.getTag() == JCTree.METHODDEF) {
   106             Name name = ((JCMethodDecl) tree).name;
   107             return name == name.table.names.init;
   108         } else {
   109             return false;
   110         }
   111     }
   113     /** Is there a constructor declaration in the given list of trees?
   114      */
   115     public static boolean hasConstructors(List<JCTree> trees) {
   116         for (List<JCTree> l = trees; l.nonEmpty(); l = l.tail)
   117             if (isConstructor(l.head)) return true;
   118         return false;
   119     }
   121     /** Is statement an initializer for a synthetic field?
   122      */
   123     public static boolean isSyntheticInit(JCTree stat) {
   124         if (stat.getTag() == JCTree.EXEC) {
   125             JCExpressionStatement exec = (JCExpressionStatement)stat;
   126             if (exec.expr.getTag() == JCTree.ASSIGN) {
   127                 JCAssign assign = (JCAssign)exec.expr;
   128                 if (assign.lhs.getTag() == JCTree.SELECT) {
   129                     JCFieldAccess select = (JCFieldAccess)assign.lhs;
   130                     if (select.sym != null &&
   131                         (select.sym.flags() & SYNTHETIC) != 0) {
   132                         Name selected = name(select.selected);
   133                         if (selected != null && selected == selected.table.names._this)
   134                             return true;
   135                     }
   136                 }
   137             }
   138         }
   139         return false;
   140     }
   142     /** If the expression is a method call, return the method name, null
   143      *  otherwise. */
   144     public static Name calledMethodName(JCTree tree) {
   145         if (tree.getTag() == JCTree.EXEC) {
   146             JCExpressionStatement exec = (JCExpressionStatement)tree;
   147             if (exec.expr.getTag() == JCTree.APPLY) {
   148                 Name mname = TreeInfo.name(((JCMethodInvocation) exec.expr).meth);
   149                 return mname;
   150             }
   151         }
   152         return null;
   153     }
   155     /** Is this a call to this or super?
   156      */
   157     public static boolean isSelfCall(JCTree tree) {
   158         Name name = calledMethodName(tree);
   159         if (name != null) {
   160             Names names = name.table.names;
   161             return name==names._this || name==names._super;
   162         } else {
   163             return false;
   164         }
   165     }
   167     /** Is this a call to super?
   168      */
   169     public static boolean isSuperCall(JCTree tree) {
   170         Name name = calledMethodName(tree);
   171         if (name != null) {
   172             Names names = name.table.names;
   173             return name==names._super;
   174         } else {
   175             return false;
   176         }
   177     }
   179     /** Is this a constructor whose first (non-synthetic) statement is not
   180      *  of the form this(...)?
   181      */
   182     public static boolean isInitialConstructor(JCTree tree) {
   183         JCMethodInvocation app = firstConstructorCall(tree);
   184         if (app == null) return false;
   185         Name meth = name(app.meth);
   186         return meth == null || meth != meth.table.names._this;
   187     }
   189     /** Return the first call in a constructor definition. */
   190     public static JCMethodInvocation firstConstructorCall(JCTree tree) {
   191         if (tree.getTag() != JCTree.METHODDEF) return null;
   192         JCMethodDecl md = (JCMethodDecl) tree;
   193         Names names = md.name.table.names;
   194         if (md.name != names.init) return null;
   195         if (md.body == null) return null;
   196         List<JCStatement> stats = md.body.stats;
   197         // Synthetic initializations can appear before the super call.
   198         while (stats.nonEmpty() && isSyntheticInit(stats.head))
   199             stats = stats.tail;
   200         if (stats.isEmpty()) return null;
   201         if (stats.head.getTag() != JCTree.EXEC) return null;
   202         JCExpressionStatement exec = (JCExpressionStatement) stats.head;
   203         if (exec.expr.getTag() != JCTree.APPLY) return null;
   204         return (JCMethodInvocation)exec.expr;
   205     }
   207     /** Return true if a tree represents the null literal. */
   208     public static boolean isNull(JCTree tree) {
   209         if (tree.getTag() != JCTree.LITERAL)
   210             return false;
   211         JCLiteral lit = (JCLiteral) tree;
   212         return (lit.typetag == TypeTags.BOT);
   213     }
   215     /** The position of the first statement in a block, or the position of
   216      *  the block itself if it is empty.
   217      */
   218     public static int firstStatPos(JCTree tree) {
   219         if (tree.getTag() == JCTree.BLOCK && ((JCBlock) tree).stats.nonEmpty())
   220             return ((JCBlock) tree).stats.head.pos;
   221         else
   222             return tree.pos;
   223     }
   225     /** The end position of given tree, if it is a block with
   226      *  defined endpos.
   227      */
   228     public static int endPos(JCTree tree) {
   229         if (tree.getTag() == JCTree.BLOCK && ((JCBlock) tree).endpos != Position.NOPOS)
   230             return ((JCBlock) tree).endpos;
   231         else if (tree.getTag() == JCTree.SYNCHRONIZED)
   232             return endPos(((JCSynchronized) tree).body);
   233         else if (tree.getTag() == JCTree.TRY) {
   234             JCTry t = (JCTry) tree;
   235             return endPos((t.finalizer != null)
   236                           ? t.finalizer
   237                           : t.catchers.last().body);
   238         } else
   239             return tree.pos;
   240     }
   243     /** Get the start position for a tree node.  The start position is
   244      * defined to be the position of the first character of the first
   245      * token of the node's source text.
   246      * @param tree  The tree node
   247      */
   248     public static int getStartPos(JCTree tree) {
   249         if (tree == null)
   250             return Position.NOPOS;
   252         switch(tree.getTag()) {
   253         case(JCTree.APPLY):
   254             return getStartPos(((JCMethodInvocation) tree).meth);
   255         case(JCTree.ASSIGN):
   256             return getStartPos(((JCAssign) tree).lhs);
   257         case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG):
   258         case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG):
   259         case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG):
   260         case(JCTree.DIV_ASG): case(JCTree.MOD_ASG):
   261             return getStartPos(((JCAssignOp) tree).lhs);
   262         case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR):
   263         case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ):
   264         case(JCTree.NE): case(JCTree.LT): case(JCTree.GT):
   265         case(JCTree.LE): case(JCTree.GE): case(JCTree.SL):
   266         case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS):
   267         case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV):
   268         case(JCTree.MOD):
   269             return getStartPos(((JCBinary) tree).lhs);
   270         case(JCTree.CLASSDEF): {
   271             JCClassDecl node = (JCClassDecl)tree;
   272             if (node.mods.pos != Position.NOPOS)
   273                 return node.mods.pos;
   274             break;
   275         }
   276         case(JCTree.CONDEXPR):
   277             return getStartPos(((JCConditional) tree).cond);
   278         case(JCTree.EXEC):
   279             return getStartPos(((JCExpressionStatement) tree).expr);
   280         case(JCTree.INDEXED):
   281             return getStartPos(((JCArrayAccess) tree).indexed);
   282         case(JCTree.METHODDEF): {
   283             JCMethodDecl node = (JCMethodDecl)tree;
   284             if (node.mods.pos != Position.NOPOS)
   285                 return node.mods.pos;
   286             if (node.typarams.nonEmpty()) // List.nil() used for no typarams
   287                 return getStartPos(node.typarams.head);
   288             return node.restype == null ? node.pos : getStartPos(node.restype);
   289         }
   290         case(JCTree.SELECT):
   291             return getStartPos(((JCFieldAccess) tree).selected);
   292         case(JCTree.TYPEAPPLY):
   293             return getStartPos(((JCTypeApply) tree).clazz);
   294         case(JCTree.TYPEARRAY):
   295             return getStartPos(((JCArrayTypeTree) tree).elemtype);
   296         case(JCTree.TYPETEST):
   297             return getStartPos(((JCInstanceOf) tree).expr);
   298         case(JCTree.POSTINC):
   299         case(JCTree.POSTDEC):
   300             return getStartPos(((JCUnary) tree).arg);
   301         case(JCTree.VARDEF): {
   302             JCVariableDecl node = (JCVariableDecl)tree;
   303             if (node.mods.pos != Position.NOPOS) {
   304                 return node.mods.pos;
   305             } else {
   306                 return getStartPos(node.vartype);
   307             }
   308         }
   309         case(JCTree.ERRONEOUS): {
   310             JCErroneous node = (JCErroneous)tree;
   311             if (node.errs != null && node.errs.nonEmpty())
   312                 return getStartPos(node.errs.head);
   313         }
   314         }
   315         return tree.pos;
   316     }
   318     /** The end position of given tree, given  a table of end positions generated by the parser
   319      */
   320     public static int getEndPos(JCTree tree, Map<JCTree, Integer> endPositions) {
   321         if (tree == null)
   322             return Position.NOPOS;
   324         if (endPositions == null) {
   325             // fall back on limited info in the tree
   326             return endPos(tree);
   327         }
   329         Integer mapPos = endPositions.get(tree);
   330         if (mapPos != null)
   331             return mapPos;
   333         switch(tree.getTag()) {
   334         case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG):
   335         case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG):
   336         case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG):
   337         case(JCTree.DIV_ASG): case(JCTree.MOD_ASG):
   338             return getEndPos(((JCAssignOp) tree).rhs, endPositions);
   339         case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR):
   340         case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ):
   341         case(JCTree.NE): case(JCTree.LT): case(JCTree.GT):
   342         case(JCTree.LE): case(JCTree.GE): case(JCTree.SL):
   343         case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS):
   344         case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV):
   345         case(JCTree.MOD):
   346             return getEndPos(((JCBinary) tree).rhs, endPositions);
   347         case(JCTree.CASE):
   348             return getEndPos(((JCCase) tree).stats.last(), endPositions);
   349         case(JCTree.CATCH):
   350             return getEndPos(((JCCatch) tree).body, endPositions);
   351         case(JCTree.CONDEXPR):
   352             return getEndPos(((JCConditional) tree).falsepart, endPositions);
   353         case(JCTree.FORLOOP):
   354             return getEndPos(((JCForLoop) tree).body, endPositions);
   355         case(JCTree.FOREACHLOOP):
   356             return getEndPos(((JCEnhancedForLoop) tree).body, endPositions);
   357         case(JCTree.IF): {
   358             JCIf node = (JCIf)tree;
   359             if (node.elsepart == null) {
   360                 return getEndPos(node.thenpart, endPositions);
   361             } else {
   362                 return getEndPos(node.elsepart, endPositions);
   363             }
   364         }
   365         case(JCTree.LABELLED):
   366             return getEndPos(((JCLabeledStatement) tree).body, endPositions);
   367         case(JCTree.MODIFIERS):
   368             return getEndPos(((JCModifiers) tree).annotations.last(), endPositions);
   369         case(JCTree.SYNCHRONIZED):
   370             return getEndPos(((JCSynchronized) tree).body, endPositions);
   371         case(JCTree.TOPLEVEL):
   372             return getEndPos(((JCCompilationUnit) tree).defs.last(), endPositions);
   373         case(JCTree.TRY): {
   374             JCTry node = (JCTry)tree;
   375             if (node.finalizer != null) {
   376                 return getEndPos(node.finalizer, endPositions);
   377             } else if (!node.catchers.isEmpty()) {
   378                 return getEndPos(node.catchers.last(), endPositions);
   379             } else {
   380                 return getEndPos(node.body, endPositions);
   381             }
   382         }
   383         case(JCTree.WILDCARD):
   384             return getEndPos(((JCWildcard) tree).inner, endPositions);
   385         case(JCTree.TYPECAST):
   386             return getEndPos(((JCTypeCast) tree).expr, endPositions);
   387         case(JCTree.TYPETEST):
   388             return getEndPos(((JCInstanceOf) tree).clazz, endPositions);
   389         case(JCTree.POS):
   390         case(JCTree.NEG):
   391         case(JCTree.NOT):
   392         case(JCTree.COMPL):
   393         case(JCTree.PREINC):
   394         case(JCTree.PREDEC):
   395             return getEndPos(((JCUnary) tree).arg, endPositions);
   396         case(JCTree.WHILELOOP):
   397             return getEndPos(((JCWhileLoop) tree).body, endPositions);
   398         case(JCTree.ERRONEOUS): {
   399             JCErroneous node = (JCErroneous)tree;
   400             if (node.errs != null && node.errs.nonEmpty())
   401                 return getEndPos(node.errs.last(), endPositions);
   402         }
   403         }
   404         return Position.NOPOS;
   405     }
   408     /** A DiagnosticPosition with the preferred position set to the
   409      *  end position of given tree, if it is a block with
   410      *  defined endpos.
   411      */
   412     public static DiagnosticPosition diagEndPos(final JCTree tree) {
   413         final int endPos = TreeInfo.endPos(tree);
   414         return new DiagnosticPosition() {
   415             public JCTree getTree() { return tree; }
   416             public int getStartPosition() { return TreeInfo.getStartPos(tree); }
   417             public int getPreferredPosition() { return endPos; }
   418             public int getEndPosition(Map<JCTree, Integer> endPosTable) {
   419                 return TreeInfo.getEndPos(tree, endPosTable);
   420             }
   421         };
   422     }
   424     /** The position of the finalizer of given try/synchronized statement.
   425      */
   426     public static int finalizerPos(JCTree tree) {
   427         if (tree.getTag() == JCTree.TRY) {
   428             JCTry t = (JCTry) tree;
   429             assert t.finalizer != null;
   430             return firstStatPos(t.finalizer);
   431         } else if (tree.getTag() == JCTree.SYNCHRONIZED) {
   432             return endPos(((JCSynchronized) tree).body);
   433         } else {
   434             throw new AssertionError();
   435         }
   436     }
   438     /** Find the position for reporting an error about a symbol, where
   439      *  that symbol is defined somewhere in the given tree. */
   440     public static int positionFor(final Symbol sym, final JCTree tree) {
   441         JCTree decl = declarationFor(sym, tree);
   442         return ((decl != null) ? decl : tree).pos;
   443     }
   445     /** Find the position for reporting an error about a symbol, where
   446      *  that symbol is defined somewhere in the given tree. */
   447     public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) {
   448         JCTree decl = declarationFor(sym, tree);
   449         return ((decl != null) ? decl : tree).pos();
   450     }
   452     /** Find the declaration for a symbol, where
   453      *  that symbol is defined somewhere in the given tree. */
   454     public static JCTree declarationFor(final Symbol sym, final JCTree tree) {
   455         class DeclScanner extends TreeScanner {
   456             JCTree result = null;
   457             public void scan(JCTree tree) {
   458                 if (tree!=null && result==null)
   459                     tree.accept(this);
   460             }
   461             public void visitTopLevel(JCCompilationUnit that) {
   462                 if (that.packge == sym) result = that;
   463                 else super.visitTopLevel(that);
   464             }
   465             public void visitClassDef(JCClassDecl that) {
   466                 if (that.sym == sym) result = that;
   467                 else super.visitClassDef(that);
   468             }
   469             public void visitMethodDef(JCMethodDecl that) {
   470                 if (that.sym == sym) result = that;
   471                 else super.visitMethodDef(that);
   472             }
   473             public void visitVarDef(JCVariableDecl that) {
   474                 if (that.sym == sym) result = that;
   475                 else super.visitVarDef(that);
   476             }
   477         }
   478         DeclScanner s = new DeclScanner();
   479         tree.accept(s);
   480         return s.result;
   481     }
   483     public static Env<AttrContext> scopeFor(JCTree node, JCCompilationUnit unit) {
   484         return scopeFor(pathFor(node, unit));
   485     }
   487     public static Env<AttrContext> scopeFor(List<JCTree> path) {
   488         // TODO: not implemented yet
   489         throw new UnsupportedOperationException("not implemented yet");
   490     }
   492     public static List<JCTree> pathFor(final JCTree node, final JCCompilationUnit unit) {
   493         class Result extends Error {
   494             static final long serialVersionUID = -5942088234594905625L;
   495             List<JCTree> path;
   496             Result(List<JCTree> path) {
   497                 this.path = path;
   498             }
   499         }
   500         class PathFinder extends TreeScanner {
   501             List<JCTree> path = List.nil();
   502             public void scan(JCTree tree) {
   503                 if (tree != null) {
   504                     path = path.prepend(tree);
   505                     if (tree == node)
   506                         throw new Result(path);
   507                     super.scan(tree);
   508                     path = path.tail;
   509                 }
   510             }
   511         }
   512         try {
   513             new PathFinder().scan(unit);
   514         } catch (Result result) {
   515             return result.path;
   516         }
   517         return List.nil();
   518     }
   520     /** Return the statement referenced by a label.
   521      *  If the label refers to a loop or switch, return that switch
   522      *  otherwise return the labelled statement itself
   523      */
   524     public static JCTree referencedStatement(JCLabeledStatement tree) {
   525         JCTree t = tree;
   526         do t = ((JCLabeledStatement) t).body;
   527         while (t.getTag() == JCTree.LABELLED);
   528         switch (t.getTag()) {
   529         case JCTree.DOLOOP: case JCTree.WHILELOOP: case JCTree.FORLOOP: case JCTree.FOREACHLOOP: case JCTree.SWITCH:
   530             return t;
   531         default:
   532             return tree;
   533         }
   534     }
   536     /** Skip parens and return the enclosed expression
   537      */
   538     public static JCExpression skipParens(JCExpression tree) {
   539         while (tree.getTag() == JCTree.PARENS) {
   540             tree = ((JCParens) tree).expr;
   541         }
   542         return tree;
   543     }
   545     /** Skip parens and return the enclosed expression
   546      */
   547     public static JCTree skipParens(JCTree tree) {
   548         if (tree.getTag() == JCTree.PARENS)
   549             return skipParens((JCParens)tree);
   550         else
   551             return tree;
   552     }
   554     /** Return the types of a list of trees.
   555      */
   556     public static List<Type> types(List<? extends JCTree> trees) {
   557         ListBuffer<Type> ts = new ListBuffer<Type>();
   558         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
   559             ts.append(l.head.type);
   560         return ts.toList();
   561     }
   563     /** If this tree is an identifier or a field or a parameterized type,
   564      *  return its name, otherwise return null.
   565      */
   566     public static Name name(JCTree tree) {
   567         switch (tree.getTag()) {
   568         case JCTree.IDENT:
   569             return ((JCIdent) tree).name;
   570         case JCTree.SELECT:
   571             return ((JCFieldAccess) tree).name;
   572         case JCTree.TYPEAPPLY:
   573             return name(((JCTypeApply) tree).clazz);
   574         default:
   575             return null;
   576         }
   577     }
   579     /** If this tree is a qualified identifier, its return fully qualified name,
   580      *  otherwise return null.
   581      */
   582     public static Name fullName(JCTree tree) {
   583         tree = skipParens(tree);
   584         switch (tree.getTag()) {
   585         case JCTree.IDENT:
   586             return ((JCIdent) tree).name;
   587         case JCTree.SELECT:
   588             Name sname = fullName(((JCFieldAccess) tree).selected);
   589             return sname == null ? null : sname.append('.', name(tree));
   590         default:
   591             return null;
   592         }
   593     }
   595     public static Symbol symbolFor(JCTree node) {
   596         node = skipParens(node);
   597         switch (node.getTag()) {
   598         case JCTree.CLASSDEF:
   599             return ((JCClassDecl) node).sym;
   600         case JCTree.METHODDEF:
   601             return ((JCMethodDecl) node).sym;
   602         case JCTree.VARDEF:
   603             return ((JCVariableDecl) node).sym;
   604         default:
   605             return null;
   606         }
   607     }
   609     /** If this tree is an identifier or a field, return its symbol,
   610      *  otherwise return null.
   611      */
   612     public static Symbol symbol(JCTree tree) {
   613         tree = skipParens(tree);
   614         switch (tree.getTag()) {
   615         case JCTree.IDENT:
   616             return ((JCIdent) tree).sym;
   617         case JCTree.SELECT:
   618             return ((JCFieldAccess) tree).sym;
   619         case JCTree.TYPEAPPLY:
   620             return symbol(((JCTypeApply) tree).clazz);
   621         default:
   622             return null;
   623         }
   624     }
   626     /** Return true if this is a nonstatic selection. */
   627     public static boolean nonstaticSelect(JCTree tree) {
   628         tree = skipParens(tree);
   629         if (tree.getTag() != JCTree.SELECT) return false;
   630         JCFieldAccess s = (JCFieldAccess) tree;
   631         Symbol e = symbol(s.selected);
   632         return e == null || (e.kind != Kinds.PCK && e.kind != Kinds.TYP);
   633     }
   635     /** If this tree is an identifier or a field, set its symbol, otherwise skip.
   636      */
   637     public static void setSymbol(JCTree tree, Symbol sym) {
   638         tree = skipParens(tree);
   639         switch (tree.getTag()) {
   640         case JCTree.IDENT:
   641             ((JCIdent) tree).sym = sym; break;
   642         case JCTree.SELECT:
   643             ((JCFieldAccess) tree).sym = sym; break;
   644         default:
   645         }
   646     }
   648     /** If this tree is a declaration or a block, return its flags field,
   649      *  otherwise return 0.
   650      */
   651     public static long flags(JCTree tree) {
   652         switch (tree.getTag()) {
   653         case JCTree.VARDEF:
   654             return ((JCVariableDecl) tree).mods.flags;
   655         case JCTree.METHODDEF:
   656             return ((JCMethodDecl) tree).mods.flags;
   657         case JCTree.CLASSDEF:
   658             return ((JCClassDecl) tree).mods.flags;
   659         case JCTree.BLOCK:
   660             return ((JCBlock) tree).flags;
   661         default:
   662             return 0;
   663         }
   664     }
   666     /** Return first (smallest) flag in `flags':
   667      *  pre: flags != 0
   668      */
   669     public static long firstFlag(long flags) {
   670         int flag = 1;
   671         while ((flag & StandardFlags) != 0 && (flag & flags) == 0)
   672             flag = flag << 1;
   673         return flag;
   674     }
   676     /** Return flags as a string, separated by " ".
   677      */
   678     public static String flagNames(long flags) {
   679         return Flags.toString(flags & StandardFlags).trim();
   680     }
   682     /** Operator precedences values.
   683      */
   684     public static final int
   685         notExpression = -1,   // not an expression
   686         noPrec = 0,           // no enclosing expression
   687         assignPrec = 1,
   688         assignopPrec = 2,
   689         condPrec = 3,
   690         orPrec = 4,
   691         andPrec = 5,
   692         bitorPrec = 6,
   693         bitxorPrec = 7,
   694         bitandPrec = 8,
   695         eqPrec = 9,
   696         ordPrec = 10,
   697         shiftPrec = 11,
   698         addPrec = 12,
   699         mulPrec = 13,
   700         prefixPrec = 14,
   701         postfixPrec = 15,
   702         precCount = 16;
   705     /** Map operators to their precedence levels.
   706      */
   707     public static int opPrec(int op) {
   708         switch(op) {
   709         case JCTree.POS:
   710         case JCTree.NEG:
   711         case JCTree.NOT:
   712         case JCTree.COMPL:
   713         case JCTree.PREINC:
   714         case JCTree.PREDEC: return prefixPrec;
   715         case JCTree.POSTINC:
   716         case JCTree.POSTDEC:
   717         case JCTree.NULLCHK: return postfixPrec;
   718         case JCTree.ASSIGN: return assignPrec;
   719         case JCTree.BITOR_ASG:
   720         case JCTree.BITXOR_ASG:
   721         case JCTree.BITAND_ASG:
   722         case JCTree.SL_ASG:
   723         case JCTree.SR_ASG:
   724         case JCTree.USR_ASG:
   725         case JCTree.PLUS_ASG:
   726         case JCTree.MINUS_ASG:
   727         case JCTree.MUL_ASG:
   728         case JCTree.DIV_ASG:
   729         case JCTree.MOD_ASG: return assignopPrec;
   730         case JCTree.OR: return orPrec;
   731         case JCTree.AND: return andPrec;
   732         case JCTree.EQ:
   733         case JCTree.NE: return eqPrec;
   734         case JCTree.LT:
   735         case JCTree.GT:
   736         case JCTree.LE:
   737         case JCTree.GE: return ordPrec;
   738         case JCTree.BITOR: return bitorPrec;
   739         case JCTree.BITXOR: return bitxorPrec;
   740         case JCTree.BITAND: return bitandPrec;
   741         case JCTree.SL:
   742         case JCTree.SR:
   743         case JCTree.USR: return shiftPrec;
   744         case JCTree.PLUS:
   745         case JCTree.MINUS: return addPrec;
   746         case JCTree.MUL:
   747         case JCTree.DIV:
   748         case JCTree.MOD: return mulPrec;
   749         case JCTree.TYPETEST: return ordPrec;
   750         default: throw new AssertionError();
   751         }
   752     }
   754     static Tree.Kind tagToKind(int tag) {
   755         switch (tag) {
   756         // Postfix expressions
   757         case JCTree.POSTINC:           // _ ++
   758             return Tree.Kind.POSTFIX_INCREMENT;
   759         case JCTree.POSTDEC:           // _ --
   760             return Tree.Kind.POSTFIX_DECREMENT;
   762         // Unary operators
   763         case JCTree.PREINC:            // ++ _
   764             return Tree.Kind.PREFIX_INCREMENT;
   765         case JCTree.PREDEC:            // -- _
   766             return Tree.Kind.PREFIX_DECREMENT;
   767         case JCTree.POS:               // +
   768             return Tree.Kind.UNARY_PLUS;
   769         case JCTree.NEG:               // -
   770             return Tree.Kind.UNARY_MINUS;
   771         case JCTree.COMPL:             // ~
   772             return Tree.Kind.BITWISE_COMPLEMENT;
   773         case JCTree.NOT:               // !
   774             return Tree.Kind.LOGICAL_COMPLEMENT;
   776         // Binary operators
   778         // Multiplicative operators
   779         case JCTree.MUL:               // *
   780             return Tree.Kind.MULTIPLY;
   781         case JCTree.DIV:               // /
   782             return Tree.Kind.DIVIDE;
   783         case JCTree.MOD:               // %
   784             return Tree.Kind.REMAINDER;
   786         // Additive operators
   787         case JCTree.PLUS:              // +
   788             return Tree.Kind.PLUS;
   789         case JCTree.MINUS:             // -
   790             return Tree.Kind.MINUS;
   792         // Shift operators
   793         case JCTree.SL:                // <<
   794             return Tree.Kind.LEFT_SHIFT;
   795         case JCTree.SR:                // >>
   796             return Tree.Kind.RIGHT_SHIFT;
   797         case JCTree.USR:               // >>>
   798             return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
   800         // Relational operators
   801         case JCTree.LT:                // <
   802             return Tree.Kind.LESS_THAN;
   803         case JCTree.GT:                // >
   804             return Tree.Kind.GREATER_THAN;
   805         case JCTree.LE:                // <=
   806             return Tree.Kind.LESS_THAN_EQUAL;
   807         case JCTree.GE:                // >=
   808             return Tree.Kind.GREATER_THAN_EQUAL;
   810         // Equality operators
   811         case JCTree.EQ:                // ==
   812             return Tree.Kind.EQUAL_TO;
   813         case JCTree.NE:                // !=
   814             return Tree.Kind.NOT_EQUAL_TO;
   816         // Bitwise and logical operators
   817         case JCTree.BITAND:            // &
   818             return Tree.Kind.AND;
   819         case JCTree.BITXOR:            // ^
   820             return Tree.Kind.XOR;
   821         case JCTree.BITOR:             // |
   822             return Tree.Kind.OR;
   824         // Conditional operators
   825         case JCTree.AND:               // &&
   826             return Tree.Kind.CONDITIONAL_AND;
   827         case JCTree.OR:                // ||
   828             return Tree.Kind.CONDITIONAL_OR;
   830         // Assignment operators
   831         case JCTree.MUL_ASG:           // *=
   832             return Tree.Kind.MULTIPLY_ASSIGNMENT;
   833         case JCTree.DIV_ASG:           // /=
   834             return Tree.Kind.DIVIDE_ASSIGNMENT;
   835         case JCTree.MOD_ASG:           // %=
   836             return Tree.Kind.REMAINDER_ASSIGNMENT;
   837         case JCTree.PLUS_ASG:          // +=
   838             return Tree.Kind.PLUS_ASSIGNMENT;
   839         case JCTree.MINUS_ASG:         // -=
   840             return Tree.Kind.MINUS_ASSIGNMENT;
   841         case JCTree.SL_ASG:            // <<=
   842             return Tree.Kind.LEFT_SHIFT_ASSIGNMENT;
   843         case JCTree.SR_ASG:            // >>=
   844             return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT;
   845         case JCTree.USR_ASG:           // >>>=
   846             return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
   847         case JCTree.BITAND_ASG:        // &=
   848             return Tree.Kind.AND_ASSIGNMENT;
   849         case JCTree.BITXOR_ASG:        // ^=
   850             return Tree.Kind.XOR_ASSIGNMENT;
   851         case JCTree.BITOR_ASG:         // |=
   852             return Tree.Kind.OR_ASSIGNMENT;
   854         // Null check (implementation detail), for example, __.getClass()
   855         case JCTree.NULLCHK:
   856             return Tree.Kind.OTHER;
   858         default:
   859             return null;
   860         }
   861     }
   862 }

mercurial