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