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

Thu, 13 Sep 2012 14:29:36 -0700

author
jjg
date
Thu, 13 Sep 2012 14:29:36 -0700
changeset 1326
30c36e23f154
parent 1300
f071cd32d297
child 1347
1408af4cd8b0
permissions
-rw-r--r--

7177970: fix issues in langtools doc comments
Reviewed-by: mcimadamore

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

mercurial