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

Tue, 09 Oct 2012 19:31:58 -0700

author
jjg
date
Tue, 09 Oct 2012 19:31:58 -0700
changeset 1358
fc123bdeddb8
parent 1352
d4b3cb1ece84
child 1366
12cf6bfd8c05
permissions
-rw-r--r--

8000208: fix langtools javadoc comment issues
Reviewed-by: bpatel, 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     /** Return true if a a tree corresponds to a poly expression. */
   249     public static boolean isPoly(JCTree tree, JCTree origin) {
   250         switch (tree.getTag()) {
   251             case APPLY:
   252             case NEWCLASS:
   253             case CONDEXPR:
   254                 return !origin.hasTag(TYPECAST);
   255             case LAMBDA:
   256             case REFERENCE:
   257                 return true;
   258             case PARENS:
   259                 return isPoly(((JCParens)tree).expr, origin);
   260             default:
   261                 return false;
   262         }
   263     }
   265     public static boolean isExplicitLambda(JCLambda lambda) {
   266         return lambda.params.isEmpty() ||
   267                 lambda.params.head.vartype != null;
   268     }
   269     /**
   270      * Return true if the AST corresponds to a static select of the kind A.B
   271      */
   272     public static boolean isStaticSelector(JCTree base, Names names) {
   273         if (base == null)
   274             return false;
   275         switch (base.getTag()) {
   276             case IDENT:
   277                 JCIdent id = (JCIdent)base;
   278                 return id.name != names._this &&
   279                         id.name != names._super &&
   280                         isStaticSym(base);
   281             case SELECT:
   282                 return isStaticSym(base) &&
   283                     isStaticSelector(((JCFieldAccess)base).selected, names);
   284             case TYPEAPPLY:
   285             case TYPEARRAY:
   286                 return true;
   287             default:
   288                 return false;
   289         }
   290     }
   291     //where
   292         private static boolean isStaticSym(JCTree tree) {
   293             Symbol sym = symbol(tree);
   294             return (sym.kind == Kinds.TYP ||
   295                     sym.kind == Kinds.PCK);
   296         }
   298     /** Return true if a tree represents the null literal. */
   299     public static boolean isNull(JCTree tree) {
   300         if (!tree.hasTag(LITERAL))
   301             return false;
   302         JCLiteral lit = (JCLiteral) tree;
   303         return (lit.typetag == TypeTags.BOT);
   304     }
   306     public static String getCommentText(Env<?> env, JCTree tree) {
   307         DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL))
   308                 ? ((JCCompilationUnit) tree).docComments
   309                 : env.toplevel.docComments;
   310         return (docComments == null) ? null : docComments.getCommentText(tree);
   311     }
   313     /** The position of the first statement in a block, or the position of
   314      *  the block itself if it is empty.
   315      */
   316     public static int firstStatPos(JCTree tree) {
   317         if (tree.hasTag(BLOCK) && ((JCBlock) tree).stats.nonEmpty())
   318             return ((JCBlock) tree).stats.head.pos;
   319         else
   320             return tree.pos;
   321     }
   323     /** The end position of given tree, if it is a block with
   324      *  defined endpos.
   325      */
   326     public static int endPos(JCTree tree) {
   327         if (tree.hasTag(BLOCK) && ((JCBlock) tree).endpos != Position.NOPOS)
   328             return ((JCBlock) tree).endpos;
   329         else if (tree.hasTag(SYNCHRONIZED))
   330             return endPos(((JCSynchronized) tree).body);
   331         else if (tree.hasTag(TRY)) {
   332             JCTry t = (JCTry) tree;
   333             return endPos((t.finalizer != null) ? t.finalizer
   334                           : (t.catchers.nonEmpty() ? t.catchers.last().body : t.body));
   335         } else
   336             return tree.pos;
   337     }
   340     /** Get the start position for a tree node.  The start position is
   341      * defined to be the position of the first character of the first
   342      * token of the node's source text.
   343      * @param tree  The tree node
   344      */
   345     public static int getStartPos(JCTree tree) {
   346         if (tree == null)
   347             return Position.NOPOS;
   349         switch(tree.getTag()) {
   350             case APPLY:
   351                 return getStartPos(((JCMethodInvocation) tree).meth);
   352             case ASSIGN:
   353                 return getStartPos(((JCAssign) tree).lhs);
   354             case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
   355             case SL_ASG: case SR_ASG: case USR_ASG:
   356             case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
   357             case DIV_ASG: case MOD_ASG:
   358                 return getStartPos(((JCAssignOp) tree).lhs);
   359             case OR: case AND: case BITOR:
   360             case BITXOR: case BITAND: case EQ:
   361             case NE: case LT: case GT:
   362             case LE: case GE: case SL:
   363             case SR: case USR: case PLUS:
   364             case MINUS: case MUL: case DIV:
   365             case MOD:
   366                 return getStartPos(((JCBinary) tree).lhs);
   367             case CLASSDEF: {
   368                 JCClassDecl node = (JCClassDecl)tree;
   369                 if (node.mods.pos != Position.NOPOS)
   370                     return node.mods.pos;
   371                 break;
   372             }
   373             case CONDEXPR:
   374                 return getStartPos(((JCConditional) tree).cond);
   375             case EXEC:
   376                 return getStartPos(((JCExpressionStatement) tree).expr);
   377             case INDEXED:
   378                 return getStartPos(((JCArrayAccess) tree).indexed);
   379             case METHODDEF: {
   380                 JCMethodDecl node = (JCMethodDecl)tree;
   381                 if (node.mods.pos != Position.NOPOS)
   382                     return node.mods.pos;
   383                 if (node.typarams.nonEmpty()) // List.nil() used for no typarams
   384                     return getStartPos(node.typarams.head);
   385                 return node.restype == null ? node.pos : getStartPos(node.restype);
   386             }
   387             case SELECT:
   388                 return getStartPos(((JCFieldAccess) tree).selected);
   389             case TYPEAPPLY:
   390                 return getStartPos(((JCTypeApply) tree).clazz);
   391             case TYPEARRAY:
   392                 return getStartPos(((JCArrayTypeTree) tree).elemtype);
   393             case TYPETEST:
   394                 return getStartPos(((JCInstanceOf) tree).expr);
   395             case POSTINC:
   396             case POSTDEC:
   397                 return getStartPos(((JCUnary) tree).arg);
   398             case NEWCLASS: {
   399                 JCNewClass node = (JCNewClass)tree;
   400                 if (node.encl != null)
   401                     return getStartPos(node.encl);
   402                 break;
   403             }
   404             case VARDEF: {
   405                 JCVariableDecl node = (JCVariableDecl)tree;
   406                 if (node.mods.pos != Position.NOPOS) {
   407                     return node.mods.pos;
   408                 } else if (node.vartype == null) {
   409                     //if there's no type (partially typed lambda parameter)
   410                     //simply return node position
   411                     return node.pos;
   412                 } else {
   413                     return getStartPos(node.vartype);
   414                 }
   415             }
   416             case ERRONEOUS: {
   417                 JCErroneous node = (JCErroneous)tree;
   418                 if (node.errs != null && node.errs.nonEmpty())
   419                     return getStartPos(node.errs.head);
   420             }
   421         }
   422         return tree.pos;
   423     }
   425     /** The end position of given tree, given  a table of end positions generated by the parser
   426      */
   427     public static int getEndPos(JCTree tree, EndPosTable endPosTable) {
   428         if (tree == null)
   429             return Position.NOPOS;
   431         if (endPosTable == null) {
   432             // fall back on limited info in the tree
   433             return endPos(tree);
   434         }
   436         int mapPos = endPosTable.getEndPos(tree);
   437         if (mapPos != Position.NOPOS)
   438             return mapPos;
   440         switch(tree.getTag()) {
   441             case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
   442             case SL_ASG: case SR_ASG: case USR_ASG:
   443             case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
   444             case DIV_ASG: case MOD_ASG:
   445                 return getEndPos(((JCAssignOp) tree).rhs, endPosTable);
   446             case OR: case AND: case BITOR:
   447             case BITXOR: case BITAND: case EQ:
   448             case NE: case LT: case GT:
   449             case LE: case GE: case SL:
   450             case SR: case USR: case PLUS:
   451             case MINUS: case MUL: case DIV:
   452             case MOD:
   453                 return getEndPos(((JCBinary) tree).rhs, endPosTable);
   454             case CASE:
   455                 return getEndPos(((JCCase) tree).stats.last(), endPosTable);
   456             case CATCH:
   457                 return getEndPos(((JCCatch) tree).body, endPosTable);
   458             case CONDEXPR:
   459                 return getEndPos(((JCConditional) tree).falsepart, endPosTable);
   460             case FORLOOP:
   461                 return getEndPos(((JCForLoop) tree).body, endPosTable);
   462             case FOREACHLOOP:
   463                 return getEndPos(((JCEnhancedForLoop) tree).body, endPosTable);
   464             case IF: {
   465                 JCIf node = (JCIf)tree;
   466                 if (node.elsepart == null) {
   467                     return getEndPos(node.thenpart, endPosTable);
   468                 } else {
   469                     return getEndPos(node.elsepart, endPosTable);
   470                 }
   471             }
   472             case LABELLED:
   473                 return getEndPos(((JCLabeledStatement) tree).body, endPosTable);
   474             case MODIFIERS:
   475                 return getEndPos(((JCModifiers) tree).annotations.last(), endPosTable);
   476             case SYNCHRONIZED:
   477                 return getEndPos(((JCSynchronized) tree).body, endPosTable);
   478             case TOPLEVEL:
   479                 return getEndPos(((JCCompilationUnit) tree).defs.last(), endPosTable);
   480             case TRY: {
   481                 JCTry node = (JCTry)tree;
   482                 if (node.finalizer != null) {
   483                     return getEndPos(node.finalizer, endPosTable);
   484                 } else if (!node.catchers.isEmpty()) {
   485                     return getEndPos(node.catchers.last(), endPosTable);
   486                 } else {
   487                     return getEndPos(node.body, endPosTable);
   488                 }
   489             }
   490             case WILDCARD:
   491                 return getEndPos(((JCWildcard) tree).inner, endPosTable);
   492             case TYPECAST:
   493                 return getEndPos(((JCTypeCast) tree).expr, endPosTable);
   494             case TYPETEST:
   495                 return getEndPos(((JCInstanceOf) tree).clazz, endPosTable);
   496             case POS:
   497             case NEG:
   498             case NOT:
   499             case COMPL:
   500             case PREINC:
   501             case PREDEC:
   502                 return getEndPos(((JCUnary) tree).arg, endPosTable);
   503             case WHILELOOP:
   504                 return getEndPos(((JCWhileLoop) tree).body, endPosTable);
   505             case ERRONEOUS: {
   506                 JCErroneous node = (JCErroneous)tree;
   507                 if (node.errs != null && node.errs.nonEmpty())
   508                     return getEndPos(node.errs.last(), endPosTable);
   509             }
   510         }
   511         return Position.NOPOS;
   512     }
   515     /** A DiagnosticPosition with the preferred position set to the
   516      *  end position of given tree, if it is a block with
   517      *  defined endpos.
   518      */
   519     public static DiagnosticPosition diagEndPos(final JCTree tree) {
   520         final int endPos = TreeInfo.endPos(tree);
   521         return new DiagnosticPosition() {
   522             public JCTree getTree() { return tree; }
   523             public int getStartPosition() { return TreeInfo.getStartPos(tree); }
   524             public int getPreferredPosition() { return endPos; }
   525             public int getEndPosition(EndPosTable endPosTable) {
   526                 return TreeInfo.getEndPos(tree, endPosTable);
   527             }
   528         };
   529     }
   531     /** The position of the finalizer of given try/synchronized statement.
   532      */
   533     public static int finalizerPos(JCTree tree) {
   534         if (tree.hasTag(TRY)) {
   535             JCTry t = (JCTry) tree;
   536             Assert.checkNonNull(t.finalizer);
   537             return firstStatPos(t.finalizer);
   538         } else if (tree.hasTag(SYNCHRONIZED)) {
   539             return endPos(((JCSynchronized) tree).body);
   540         } else {
   541             throw new AssertionError();
   542         }
   543     }
   545     /** Find the position for reporting an error about a symbol, where
   546      *  that symbol is defined somewhere in the given tree. */
   547     public static int positionFor(final Symbol sym, final JCTree tree) {
   548         JCTree decl = declarationFor(sym, tree);
   549         return ((decl != null) ? decl : tree).pos;
   550     }
   552     /** Find the position for reporting an error about a symbol, where
   553      *  that symbol is defined somewhere in the given tree. */
   554     public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) {
   555         JCTree decl = declarationFor(sym, tree);
   556         return ((decl != null) ? decl : tree).pos();
   557     }
   559     /** Find the declaration for a symbol, where
   560      *  that symbol is defined somewhere in the given tree. */
   561     public static JCTree declarationFor(final Symbol sym, final JCTree tree) {
   562         class DeclScanner extends TreeScanner {
   563             JCTree result = null;
   564             public void scan(JCTree tree) {
   565                 if (tree!=null && result==null)
   566                     tree.accept(this);
   567             }
   568             public void visitTopLevel(JCCompilationUnit that) {
   569                 if (that.packge == sym) result = that;
   570                 else super.visitTopLevel(that);
   571             }
   572             public void visitClassDef(JCClassDecl that) {
   573                 if (that.sym == sym) result = that;
   574                 else super.visitClassDef(that);
   575             }
   576             public void visitMethodDef(JCMethodDecl that) {
   577                 if (that.sym == sym) result = that;
   578                 else super.visitMethodDef(that);
   579             }
   580             public void visitVarDef(JCVariableDecl that) {
   581                 if (that.sym == sym) result = that;
   582                 else super.visitVarDef(that);
   583             }
   584             public void visitTypeParameter(JCTypeParameter that) {
   585                 if (that.type != null && that.type.tsym == sym) result = that;
   586                 else super.visitTypeParameter(that);
   587             }
   588         }
   589         DeclScanner s = new DeclScanner();
   590         tree.accept(s);
   591         return s.result;
   592     }
   594     public static Env<AttrContext> scopeFor(JCTree node, JCCompilationUnit unit) {
   595         return scopeFor(pathFor(node, unit));
   596     }
   598     public static Env<AttrContext> scopeFor(List<JCTree> path) {
   599         // TODO: not implemented yet
   600         throw new UnsupportedOperationException("not implemented yet");
   601     }
   603     public static List<JCTree> pathFor(final JCTree node, final JCCompilationUnit unit) {
   604         class Result extends Error {
   605             static final long serialVersionUID = -5942088234594905625L;
   606             List<JCTree> path;
   607             Result(List<JCTree> path) {
   608                 this.path = path;
   609             }
   610         }
   611         class PathFinder extends TreeScanner {
   612             List<JCTree> path = List.nil();
   613             public void scan(JCTree tree) {
   614                 if (tree != null) {
   615                     path = path.prepend(tree);
   616                     if (tree == node)
   617                         throw new Result(path);
   618                     super.scan(tree);
   619                     path = path.tail;
   620                 }
   621             }
   622         }
   623         try {
   624             new PathFinder().scan(unit);
   625         } catch (Result result) {
   626             return result.path;
   627         }
   628         return List.nil();
   629     }
   631     /** Return the statement referenced by a label.
   632      *  If the label refers to a loop or switch, return that switch
   633      *  otherwise return the labelled statement itself
   634      */
   635     public static JCTree referencedStatement(JCLabeledStatement tree) {
   636         JCTree t = tree;
   637         do t = ((JCLabeledStatement) t).body;
   638         while (t.hasTag(LABELLED));
   639         switch (t.getTag()) {
   640         case DOLOOP: case WHILELOOP: case FORLOOP: case FOREACHLOOP: case SWITCH:
   641             return t;
   642         default:
   643             return tree;
   644         }
   645     }
   647     /** Skip parens and return the enclosed expression
   648      */
   649     public static JCExpression skipParens(JCExpression tree) {
   650         while (tree.hasTag(PARENS)) {
   651             tree = ((JCParens) tree).expr;
   652         }
   653         return tree;
   654     }
   656     /** Skip parens and return the enclosed expression
   657      */
   658     public static JCTree skipParens(JCTree tree) {
   659         if (tree.hasTag(PARENS))
   660             return skipParens((JCParens)tree);
   661         else
   662             return tree;
   663     }
   665     /** Return the types of a list of trees.
   666      */
   667     public static List<Type> types(List<? extends JCTree> trees) {
   668         ListBuffer<Type> ts = new ListBuffer<Type>();
   669         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
   670             ts.append(l.head.type);
   671         return ts.toList();
   672     }
   674     /** If this tree is an identifier or a field or a parameterized type,
   675      *  return its name, otherwise return null.
   676      */
   677     public static Name name(JCTree tree) {
   678         switch (tree.getTag()) {
   679         case IDENT:
   680             return ((JCIdent) tree).name;
   681         case SELECT:
   682             return ((JCFieldAccess) tree).name;
   683         case TYPEAPPLY:
   684             return name(((JCTypeApply) tree).clazz);
   685         default:
   686             return null;
   687         }
   688     }
   690     /** If this tree is a qualified identifier, its return fully qualified name,
   691      *  otherwise return null.
   692      */
   693     public static Name fullName(JCTree tree) {
   694         tree = skipParens(tree);
   695         switch (tree.getTag()) {
   696         case IDENT:
   697             return ((JCIdent) tree).name;
   698         case SELECT:
   699             Name sname = fullName(((JCFieldAccess) tree).selected);
   700             return sname == null ? null : sname.append('.', name(tree));
   701         default:
   702             return null;
   703         }
   704     }
   706     public static Symbol symbolFor(JCTree node) {
   707         node = skipParens(node);
   708         switch (node.getTag()) {
   709         case CLASSDEF:
   710             return ((JCClassDecl) node).sym;
   711         case METHODDEF:
   712             return ((JCMethodDecl) node).sym;
   713         case VARDEF:
   714             return ((JCVariableDecl) node).sym;
   715         default:
   716             return null;
   717         }
   718     }
   720     public static boolean isDeclaration(JCTree node) {
   721         node = skipParens(node);
   722         switch (node.getTag()) {
   723         case CLASSDEF:
   724         case METHODDEF:
   725         case VARDEF:
   726             return true;
   727         default:
   728             return false;
   729         }
   730     }
   732     /** If this tree is an identifier or a field, return its symbol,
   733      *  otherwise return null.
   734      */
   735     public static Symbol symbol(JCTree tree) {
   736         tree = skipParens(tree);
   737         switch (tree.getTag()) {
   738         case IDENT:
   739             return ((JCIdent) tree).sym;
   740         case SELECT:
   741             return ((JCFieldAccess) tree).sym;
   742         case TYPEAPPLY:
   743             return symbol(((JCTypeApply) tree).clazz);
   744         default:
   745             return null;
   746         }
   747     }
   749     /** Return true if this is a nonstatic selection. */
   750     public static boolean nonstaticSelect(JCTree tree) {
   751         tree = skipParens(tree);
   752         if (!tree.hasTag(SELECT)) return false;
   753         JCFieldAccess s = (JCFieldAccess) tree;
   754         Symbol e = symbol(s.selected);
   755         return e == null || (e.kind != Kinds.PCK && e.kind != Kinds.TYP);
   756     }
   758     /** If this tree is an identifier or a field, set its symbol, otherwise skip.
   759      */
   760     public static void setSymbol(JCTree tree, Symbol sym) {
   761         tree = skipParens(tree);
   762         switch (tree.getTag()) {
   763         case IDENT:
   764             ((JCIdent) tree).sym = sym; break;
   765         case SELECT:
   766             ((JCFieldAccess) tree).sym = sym; break;
   767         default:
   768         }
   769     }
   771     /** If this tree is a declaration or a block, return its flags field,
   772      *  otherwise return 0.
   773      */
   774     public static long flags(JCTree tree) {
   775         switch (tree.getTag()) {
   776         case VARDEF:
   777             return ((JCVariableDecl) tree).mods.flags;
   778         case METHODDEF:
   779             return ((JCMethodDecl) tree).mods.flags;
   780         case CLASSDEF:
   781             return ((JCClassDecl) tree).mods.flags;
   782         case BLOCK:
   783             return ((JCBlock) tree).flags;
   784         default:
   785             return 0;
   786         }
   787     }
   789     /** Return first (smallest) flag in `flags':
   790      *  pre: flags != 0
   791      */
   792     public static long firstFlag(long flags) {
   793         int flag = 1;
   794         while ((flag & StandardFlags) != 0 && (flag & flags) == 0)
   795             flag = flag << 1;
   796         return flag;
   797     }
   799     /** Return flags as a string, separated by " ".
   800      */
   801     public static String flagNames(long flags) {
   802         return Flags.toString(flags & StandardFlags).trim();
   803     }
   805     /** Operator precedences values.
   806      */
   807     public static final int
   808         notExpression = -1,   // not an expression
   809         noPrec = 0,           // no enclosing expression
   810         assignPrec = 1,
   811         assignopPrec = 2,
   812         condPrec = 3,
   813         orPrec = 4,
   814         andPrec = 5,
   815         bitorPrec = 6,
   816         bitxorPrec = 7,
   817         bitandPrec = 8,
   818         eqPrec = 9,
   819         ordPrec = 10,
   820         shiftPrec = 11,
   821         addPrec = 12,
   822         mulPrec = 13,
   823         prefixPrec = 14,
   824         postfixPrec = 15,
   825         precCount = 16;
   828     /** Map operators to their precedence levels.
   829      */
   830     public static int opPrec(JCTree.Tag op) {
   831         switch(op) {
   832         case POS:
   833         case NEG:
   834         case NOT:
   835         case COMPL:
   836         case PREINC:
   837         case PREDEC: return prefixPrec;
   838         case POSTINC:
   839         case POSTDEC:
   840         case NULLCHK: return postfixPrec;
   841         case ASSIGN: return assignPrec;
   842         case BITOR_ASG:
   843         case BITXOR_ASG:
   844         case BITAND_ASG:
   845         case SL_ASG:
   846         case SR_ASG:
   847         case USR_ASG:
   848         case PLUS_ASG:
   849         case MINUS_ASG:
   850         case MUL_ASG:
   851         case DIV_ASG:
   852         case MOD_ASG: return assignopPrec;
   853         case OR: return orPrec;
   854         case AND: return andPrec;
   855         case EQ:
   856         case NE: return eqPrec;
   857         case LT:
   858         case GT:
   859         case LE:
   860         case GE: return ordPrec;
   861         case BITOR: return bitorPrec;
   862         case BITXOR: return bitxorPrec;
   863         case BITAND: return bitandPrec;
   864         case SL:
   865         case SR:
   866         case USR: return shiftPrec;
   867         case PLUS:
   868         case MINUS: return addPrec;
   869         case MUL:
   870         case DIV:
   871         case MOD: return mulPrec;
   872         case TYPETEST: return ordPrec;
   873         default: throw new AssertionError();
   874         }
   875     }
   877     static Tree.Kind tagToKind(JCTree.Tag tag) {
   878         switch (tag) {
   879         // Postfix expressions
   880         case POSTINC:           // _ ++
   881             return Tree.Kind.POSTFIX_INCREMENT;
   882         case POSTDEC:           // _ --
   883             return Tree.Kind.POSTFIX_DECREMENT;
   885         // Unary operators
   886         case PREINC:            // ++ _
   887             return Tree.Kind.PREFIX_INCREMENT;
   888         case PREDEC:            // -- _
   889             return Tree.Kind.PREFIX_DECREMENT;
   890         case POS:               // +
   891             return Tree.Kind.UNARY_PLUS;
   892         case NEG:               // -
   893             return Tree.Kind.UNARY_MINUS;
   894         case COMPL:             // ~
   895             return Tree.Kind.BITWISE_COMPLEMENT;
   896         case NOT:               // !
   897             return Tree.Kind.LOGICAL_COMPLEMENT;
   899         // Binary operators
   901         // Multiplicative operators
   902         case MUL:               // *
   903             return Tree.Kind.MULTIPLY;
   904         case DIV:               // /
   905             return Tree.Kind.DIVIDE;
   906         case MOD:               // %
   907             return Tree.Kind.REMAINDER;
   909         // Additive operators
   910         case PLUS:              // +
   911             return Tree.Kind.PLUS;
   912         case MINUS:             // -
   913             return Tree.Kind.MINUS;
   915         // Shift operators
   916         case SL:                // <<
   917             return Tree.Kind.LEFT_SHIFT;
   918         case SR:                // >>
   919             return Tree.Kind.RIGHT_SHIFT;
   920         case USR:               // >>>
   921             return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
   923         // Relational operators
   924         case LT:                // <
   925             return Tree.Kind.LESS_THAN;
   926         case GT:                // >
   927             return Tree.Kind.GREATER_THAN;
   928         case LE:                // <=
   929             return Tree.Kind.LESS_THAN_EQUAL;
   930         case GE:                // >=
   931             return Tree.Kind.GREATER_THAN_EQUAL;
   933         // Equality operators
   934         case EQ:                // ==
   935             return Tree.Kind.EQUAL_TO;
   936         case NE:                // !=
   937             return Tree.Kind.NOT_EQUAL_TO;
   939         // Bitwise and logical operators
   940         case BITAND:            // &
   941             return Tree.Kind.AND;
   942         case BITXOR:            // ^
   943             return Tree.Kind.XOR;
   944         case BITOR:             // |
   945             return Tree.Kind.OR;
   947         // Conditional operators
   948         case AND:               // &&
   949             return Tree.Kind.CONDITIONAL_AND;
   950         case OR:                // ||
   951             return Tree.Kind.CONDITIONAL_OR;
   953         // Assignment operators
   954         case MUL_ASG:           // *=
   955             return Tree.Kind.MULTIPLY_ASSIGNMENT;
   956         case DIV_ASG:           // /=
   957             return Tree.Kind.DIVIDE_ASSIGNMENT;
   958         case MOD_ASG:           // %=
   959             return Tree.Kind.REMAINDER_ASSIGNMENT;
   960         case PLUS_ASG:          // +=
   961             return Tree.Kind.PLUS_ASSIGNMENT;
   962         case MINUS_ASG:         // -=
   963             return Tree.Kind.MINUS_ASSIGNMENT;
   964         case SL_ASG:            // <<=
   965             return Tree.Kind.LEFT_SHIFT_ASSIGNMENT;
   966         case SR_ASG:            // >>=
   967             return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT;
   968         case USR_ASG:           // >>>=
   969             return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
   970         case BITAND_ASG:        // &=
   971             return Tree.Kind.AND_ASSIGNMENT;
   972         case BITXOR_ASG:        // ^=
   973             return Tree.Kind.XOR_ASSIGNMENT;
   974         case BITOR_ASG:         // |=
   975             return Tree.Kind.OR_ASSIGNMENT;
   977         // Null check (implementation detail), for example, __.getClass()
   978         case NULLCHK:
   979             return Tree.Kind.OTHER;
   981         default:
   982             return null;
   983         }
   984     }
   986     /**
   987      * Returns the underlying type of the tree if it is annotated type,
   988      * or the tree itself otherwise
   989      */
   990     public static JCExpression typeIn(JCExpression tree) {
   991         switch (tree.getTag()) {
   992         case IDENT: /* simple names */
   993         case TYPEIDENT: /* primitive name */
   994         case SELECT: /* qualified name */
   995         case TYPEARRAY: /* array types */
   996         case WILDCARD: /* wild cards */
   997         case TYPEPARAMETER: /* type parameters */
   998         case TYPEAPPLY: /* parameterized types */
   999             return tree;
  1000         default:
  1001             throw new AssertionError("Unexpected type tree: " + tree);
  1005     public static JCTree innermostType(JCTree type) {
  1006         switch (type.getTag()) {
  1007         case TYPEARRAY:
  1008             return innermostType(((JCArrayTypeTree)type).elemtype);
  1009         case WILDCARD:
  1010             return innermostType(((JCWildcard)type).inner);
  1011         default:
  1012             return type;

mercurial