src/share/classes/com/sun/tools/javac/tree/TreeInfo.java

Mon, 26 Mar 2012 15:27:51 +0100

author
mcimadamore
date
Mon, 26 Mar 2012 15:27:51 +0100
changeset 1237
568e70bbd9aa
parent 1219
48ee63caaa93
child 1269
37dc15c68760
permissions
-rw-r--r--

7151580: Separate DA/DU logic from exception checking logic in Flow.java
Summary: DA/DU analysis and exception checking analysis should live in two separate tree visitors
Reviewed-by: gafter, dlsmith, jjg

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

mercurial