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