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