Home » openjdk-7 » com.sun.tools » javac » tree » [javadoc | source]

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

Home » openjdk-7 » com.sun.tools » javac » tree » [javadoc | source]