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

Tue, 11 Aug 2009 01:13:14 +0100

author
mcimadamore
date
Tue, 11 Aug 2009 01:13:14 +0100
changeset 359
8227961c64d3
parent 308
03944ee4fac4
child 383
8109aa93b212
permissions
-rw-r--r--

6521805: Regression: JDK5/JDK6 javac allows write access to outer class reference
Summary: javac should warn/complain about identifiers with the same name as synthetic symbol
Reviewed-by: jjg

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

mercurial