TreeInfo.java revision 3792:d516975e8110
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 MODULEDEF: {
382                JCModuleDecl md = (JCModuleDecl)tree;
383                return md.mods.annotations.isEmpty() ? md.pos :
384                       md.mods.annotations.head.pos;
385            }
386            case PACKAGEDEF: {
387                JCPackageDecl pd = (JCPackageDecl)tree;
388                return pd.annotations.isEmpty() ? pd.pos :
389                       pd.annotations.head.pos;
390            }
391            case APPLY:
392                return getStartPos(((JCMethodInvocation) tree).meth);
393            case ASSIGN:
394                return getStartPos(((JCAssign) tree).lhs);
395            case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
396            case SL_ASG: case SR_ASG: case USR_ASG:
397            case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
398            case DIV_ASG: case MOD_ASG:
399            case OR: case AND: case BITOR:
400            case BITXOR: case BITAND: case EQ:
401            case NE: case LT: case GT:
402            case LE: case GE: case SL:
403            case SR: case USR: case PLUS:
404            case MINUS: case MUL: case DIV:
405            case MOD:
406            case POSTINC:
407            case POSTDEC:
408                return getStartPos(((JCOperatorExpression) tree).getOperand(LEFT));
409            case CLASSDEF: {
410                JCClassDecl node = (JCClassDecl)tree;
411                if (node.mods.pos != Position.NOPOS)
412                    return node.mods.pos;
413                break;
414            }
415            case CONDEXPR:
416                return getStartPos(((JCConditional) tree).cond);
417            case EXEC:
418                return getStartPos(((JCExpressionStatement) tree).expr);
419            case INDEXED:
420                return getStartPos(((JCArrayAccess) tree).indexed);
421            case METHODDEF: {
422                JCMethodDecl node = (JCMethodDecl)tree;
423                if (node.mods.pos != Position.NOPOS)
424                    return node.mods.pos;
425                if (node.typarams.nonEmpty()) // List.nil() used for no typarams
426                    return getStartPos(node.typarams.head);
427                return node.restype == null ? node.pos : getStartPos(node.restype);
428            }
429            case SELECT:
430                return getStartPos(((JCFieldAccess) tree).selected);
431            case TYPEAPPLY:
432                return getStartPos(((JCTypeApply) tree).clazz);
433            case TYPEARRAY:
434                return getStartPos(((JCArrayTypeTree) tree).elemtype);
435            case TYPETEST:
436                return getStartPos(((JCInstanceOf) tree).expr);
437            case ANNOTATED_TYPE: {
438                JCAnnotatedType node = (JCAnnotatedType) tree;
439                if (node.annotations.nonEmpty()) {
440                    if (node.underlyingType.hasTag(TYPEARRAY) ||
441                            node.underlyingType.hasTag(SELECT)) {
442                        return getStartPos(node.underlyingType);
443                    } else {
444                        return getStartPos(node.annotations.head);
445                    }
446                } else {
447                    return getStartPos(node.underlyingType);
448                }
449            }
450            case NEWCLASS: {
451                JCNewClass node = (JCNewClass)tree;
452                if (node.encl != null)
453                    return getStartPos(node.encl);
454                break;
455            }
456            case VARDEF: {
457                JCVariableDecl node = (JCVariableDecl)tree;
458                if (node.mods.pos != Position.NOPOS) {
459                    return node.mods.pos;
460                } else if (node.vartype == null) {
461                    //if there's no type (partially typed lambda parameter)
462                    //simply return node position
463                    return node.pos;
464                } else {
465                    return getStartPos(node.vartype);
466                }
467            }
468            case ERRONEOUS: {
469                JCErroneous node = (JCErroneous)tree;
470                if (node.errs != null && node.errs.nonEmpty())
471                    return getStartPos(node.errs.head);
472            }
473        }
474        return tree.pos;
475    }
476
477    /** The end position of given tree, given  a table of end positions generated by the parser
478     */
479    public static int getEndPos(JCTree tree, EndPosTable endPosTable) {
480        if (tree == null)
481            return Position.NOPOS;
482
483        if (endPosTable == null) {
484            // fall back on limited info in the tree
485            return endPos(tree);
486        }
487
488        int mapPos = endPosTable.getEndPos(tree);
489        if (mapPos != Position.NOPOS)
490            return mapPos;
491
492        switch(tree.getTag()) {
493            case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
494            case SL_ASG: case SR_ASG: case USR_ASG:
495            case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
496            case DIV_ASG: case MOD_ASG:
497            case OR: case AND: case BITOR:
498            case BITXOR: case BITAND: case EQ:
499            case NE: case LT: case GT:
500            case LE: case GE: case SL:
501            case SR: case USR: case PLUS:
502            case MINUS: case MUL: case DIV:
503            case MOD:
504            case POS:
505            case NEG:
506            case NOT:
507            case COMPL:
508            case PREINC:
509            case PREDEC:
510                return getEndPos(((JCOperatorExpression) tree).getOperand(RIGHT), endPosTable);
511            case CASE:
512                return getEndPos(((JCCase) tree).stats.last(), endPosTable);
513            case CATCH:
514                return getEndPos(((JCCatch) tree).body, endPosTable);
515            case CONDEXPR:
516                return getEndPos(((JCConditional) tree).falsepart, endPosTable);
517            case FORLOOP:
518                return getEndPos(((JCForLoop) tree).body, endPosTable);
519            case FOREACHLOOP:
520                return getEndPos(((JCEnhancedForLoop) tree).body, endPosTable);
521            case IF: {
522                JCIf node = (JCIf)tree;
523                if (node.elsepart == null) {
524                    return getEndPos(node.thenpart, endPosTable);
525                } else {
526                    return getEndPos(node.elsepart, endPosTable);
527                }
528            }
529            case LABELLED:
530                return getEndPos(((JCLabeledStatement) tree).body, endPosTable);
531            case MODIFIERS:
532                return getEndPos(((JCModifiers) tree).annotations.last(), endPosTable);
533            case SYNCHRONIZED:
534                return getEndPos(((JCSynchronized) tree).body, endPosTable);
535            case TOPLEVEL:
536                return getEndPos(((JCCompilationUnit) tree).defs.last(), endPosTable);
537            case TRY: {
538                JCTry node = (JCTry)tree;
539                if (node.finalizer != null) {
540                    return getEndPos(node.finalizer, endPosTable);
541                } else if (!node.catchers.isEmpty()) {
542                    return getEndPos(node.catchers.last(), endPosTable);
543                } else {
544                    return getEndPos(node.body, endPosTable);
545                }
546            }
547            case WILDCARD:
548                return getEndPos(((JCWildcard) tree).inner, endPosTable);
549            case TYPECAST:
550                return getEndPos(((JCTypeCast) tree).expr, endPosTable);
551            case TYPETEST:
552                return getEndPos(((JCInstanceOf) tree).clazz, endPosTable);
553            case WHILELOOP:
554                return getEndPos(((JCWhileLoop) tree).body, endPosTable);
555            case ANNOTATED_TYPE:
556                return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable);
557            case ERRONEOUS: {
558                JCErroneous node = (JCErroneous)tree;
559                if (node.errs != null && node.errs.nonEmpty())
560                    return getEndPos(node.errs.last(), endPosTable);
561            }
562        }
563        return Position.NOPOS;
564    }
565
566
567    /** A DiagnosticPosition with the preferred position set to the
568     *  end position of given tree, if it is a block with
569     *  defined endpos.
570     */
571    public static DiagnosticPosition diagEndPos(final JCTree tree) {
572        final int endPos = TreeInfo.endPos(tree);
573        return new DiagnosticPosition() {
574            public JCTree getTree() { return tree; }
575            public int getStartPosition() { return TreeInfo.getStartPos(tree); }
576            public int getPreferredPosition() { return endPos; }
577            public int getEndPosition(EndPosTable endPosTable) {
578                return TreeInfo.getEndPos(tree, endPosTable);
579            }
580        };
581    }
582
583    /** The position of the finalizer of given try/synchronized statement.
584     */
585    public static int finalizerPos(JCTree tree) {
586        if (tree.hasTag(TRY)) {
587            JCTry t = (JCTry) tree;
588            Assert.checkNonNull(t.finalizer);
589            return firstStatPos(t.finalizer);
590        } else if (tree.hasTag(SYNCHRONIZED)) {
591            return endPos(((JCSynchronized) tree).body);
592        } else {
593            throw new AssertionError();
594        }
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 int positionFor(final Symbol sym, final JCTree tree) {
600        JCTree decl = declarationFor(sym, tree);
601        return ((decl != null) ? decl : tree).pos;
602    }
603
604    /** Find the position for reporting an error about a symbol, where
605     *  that symbol is defined somewhere in the given tree. */
606    public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) {
607        JCTree decl = declarationFor(sym, tree);
608        return ((decl != null) ? decl : tree).pos();
609    }
610
611    /** Find the declaration for a symbol, where
612     *  that symbol is defined somewhere in the given tree. */
613    public static JCTree declarationFor(final Symbol sym, final JCTree tree) {
614        class DeclScanner extends TreeScanner {
615            JCTree result = null;
616            public void scan(JCTree tree) {
617                if (tree!=null && result==null)
618                    tree.accept(this);
619            }
620            public void visitTopLevel(JCCompilationUnit that) {
621                if (that.packge == sym) result = that;
622                else super.visitTopLevel(that);
623            }
624            public void visitModuleDef(JCModuleDecl that) {
625                if (that.sym == sym) result = that;
626                // no need to scan within module declaration
627            }
628            public void visitPackageDef(JCPackageDecl that) {
629                if (that.packge == sym) result = that;
630                else super.visitPackageDef(that);
631            }
632            public void visitClassDef(JCClassDecl that) {
633                if (that.sym == sym) result = that;
634                else super.visitClassDef(that);
635            }
636            public void visitMethodDef(JCMethodDecl that) {
637                if (that.sym == sym) result = that;
638                else super.visitMethodDef(that);
639            }
640            public void visitVarDef(JCVariableDecl that) {
641                if (that.sym == sym) result = that;
642                else super.visitVarDef(that);
643            }
644            public void visitTypeParameter(JCTypeParameter that) {
645                if (that.type != null && that.type.tsym == sym) result = that;
646                else super.visitTypeParameter(that);
647            }
648        }
649        DeclScanner s = new DeclScanner();
650        tree.accept(s);
651        return s.result;
652    }
653
654    public static Env<AttrContext> scopeFor(JCTree node, JCCompilationUnit unit) {
655        return scopeFor(pathFor(node, unit));
656    }
657
658    public static Env<AttrContext> scopeFor(List<JCTree> path) {
659        // TODO: not implemented yet
660        throw new UnsupportedOperationException("not implemented yet");
661    }
662
663    public static List<JCTree> pathFor(final JCTree node, final JCCompilationUnit unit) {
664        class Result extends Error {
665            static final long serialVersionUID = -5942088234594905625L;
666            List<JCTree> path;
667            Result(List<JCTree> path) {
668                this.path = path;
669            }
670        }
671        class PathFinder extends TreeScanner {
672            List<JCTree> path = List.nil();
673            public void scan(JCTree tree) {
674                if (tree != null) {
675                    path = path.prepend(tree);
676                    if (tree == node)
677                        throw new Result(path);
678                    super.scan(tree);
679                    path = path.tail;
680                }
681            }
682        }
683        try {
684            new PathFinder().scan(unit);
685        } catch (Result result) {
686            return result.path;
687        }
688        return List.nil();
689    }
690
691    /** Return the statement referenced by a label.
692     *  If the label refers to a loop or switch, return that switch
693     *  otherwise return the labelled statement itself
694     */
695    public static JCTree referencedStatement(JCLabeledStatement tree) {
696        JCTree t = tree;
697        do t = ((JCLabeledStatement) t).body;
698        while (t.hasTag(LABELLED));
699        switch (t.getTag()) {
700        case DOLOOP: case WHILELOOP: case FORLOOP: case FOREACHLOOP: case SWITCH:
701            return t;
702        default:
703            return tree;
704        }
705    }
706
707    /** Skip parens and return the enclosed expression
708     */
709    public static JCExpression skipParens(JCExpression tree) {
710        while (tree.hasTag(PARENS)) {
711            tree = ((JCParens) tree).expr;
712        }
713        return tree;
714    }
715
716    /** Skip parens and return the enclosed expression
717     */
718    public static JCTree skipParens(JCTree tree) {
719        if (tree.hasTag(PARENS))
720            return skipParens((JCParens)tree);
721        else
722            return tree;
723    }
724
725    /** Return the types of a list of trees.
726     */
727    public static List<Type> types(List<? extends JCTree> trees) {
728        ListBuffer<Type> ts = new ListBuffer<>();
729        for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
730            ts.append(l.head.type);
731        return ts.toList();
732    }
733
734    /** If this tree is an identifier or a field or a parameterized type,
735     *  return its name, otherwise return null.
736     */
737    public static Name name(JCTree tree) {
738        switch (tree.getTag()) {
739        case IDENT:
740            return ((JCIdent) tree).name;
741        case SELECT:
742            return ((JCFieldAccess) tree).name;
743        case TYPEAPPLY:
744            return name(((JCTypeApply) tree).clazz);
745        default:
746            return null;
747        }
748    }
749
750    /** If this tree is a qualified identifier, its return fully qualified name,
751     *  otherwise return null.
752     */
753    public static Name fullName(JCTree tree) {
754        tree = skipParens(tree);
755        switch (tree.getTag()) {
756        case IDENT:
757            return ((JCIdent) tree).name;
758        case SELECT:
759            Name sname = fullName(((JCFieldAccess) tree).selected);
760            return sname == null ? null : sname.append('.', name(tree));
761        default:
762            return null;
763        }
764    }
765
766    public static Symbol symbolFor(JCTree node) {
767        Symbol sym = symbolForImpl(node);
768
769        return sym != null ? sym.baseSymbol() : null;
770    }
771
772    private static Symbol symbolForImpl(JCTree node) {
773        node = skipParens(node);
774        switch (node.getTag()) {
775        case TOPLEVEL:
776            JCCompilationUnit cut = (JCCompilationUnit) node;
777            JCModuleDecl moduleDecl = cut.getModuleDecl();
778            if (isModuleInfo(cut) && moduleDecl != null)
779                return symbolFor(moduleDecl);
780            return cut.packge;
781        case MODULEDEF:
782            return ((JCModuleDecl) node).sym;
783        case PACKAGEDEF:
784            return ((JCPackageDecl) node).packge;
785        case CLASSDEF:
786            return ((JCClassDecl) node).sym;
787        case METHODDEF:
788            return ((JCMethodDecl) node).sym;
789        case VARDEF:
790            return ((JCVariableDecl) node).sym;
791        case IDENT:
792            return ((JCIdent) node).sym;
793        case SELECT:
794            return ((JCFieldAccess) node).sym;
795        case REFERENCE:
796            return ((JCMemberReference) node).sym;
797        case NEWCLASS:
798            return ((JCNewClass) node).constructor;
799        case APPLY:
800            return symbolFor(((JCMethodInvocation) node).meth);
801        case TYPEAPPLY:
802            return symbolFor(((JCTypeApply) node).clazz);
803        case ANNOTATION:
804        case TYPE_ANNOTATION:
805        case TYPEPARAMETER:
806            if (node.type != null)
807                return node.type.tsym;
808            return null;
809        default:
810            return null;
811        }
812    }
813
814    public static boolean isDeclaration(JCTree node) {
815        node = skipParens(node);
816        switch (node.getTag()) {
817        case PACKAGEDEF:
818        case CLASSDEF:
819        case METHODDEF:
820        case VARDEF:
821            return true;
822        default:
823            return false;
824        }
825    }
826
827    /** If this tree is an identifier or a field, return its symbol,
828     *  otherwise return null.
829     */
830    public static Symbol symbol(JCTree tree) {
831        tree = skipParens(tree);
832        switch (tree.getTag()) {
833        case IDENT:
834            return ((JCIdent) tree).sym;
835        case SELECT:
836            return ((JCFieldAccess) tree).sym;
837        case TYPEAPPLY:
838            return symbol(((JCTypeApply) tree).clazz);
839        case ANNOTATED_TYPE:
840            return symbol(((JCAnnotatedType) tree).underlyingType);
841        case REFERENCE:
842            return ((JCMemberReference) tree).sym;
843        default:
844            return null;
845        }
846    }
847
848    /** Return true if this is a nonstatic selection. */
849    public static boolean nonstaticSelect(JCTree tree) {
850        tree = skipParens(tree);
851        if (!tree.hasTag(SELECT)) return false;
852        JCFieldAccess s = (JCFieldAccess) tree;
853        Symbol e = symbol(s.selected);
854        return e == null || (e.kind != PCK && e.kind != TYP);
855    }
856
857    /** If this tree is an identifier or a field, set its symbol, otherwise skip.
858     */
859    public static void setSymbol(JCTree tree, Symbol sym) {
860        tree = skipParens(tree);
861        switch (tree.getTag()) {
862        case IDENT:
863            ((JCIdent) tree).sym = sym; break;
864        case SELECT:
865            ((JCFieldAccess) tree).sym = sym; break;
866        default:
867        }
868    }
869
870    /** If this tree is a declaration or a block, return its flags field,
871     *  otherwise return 0.
872     */
873    public static long flags(JCTree tree) {
874        switch (tree.getTag()) {
875        case VARDEF:
876            return ((JCVariableDecl) tree).mods.flags;
877        case METHODDEF:
878            return ((JCMethodDecl) tree).mods.flags;
879        case CLASSDEF:
880            return ((JCClassDecl) tree).mods.flags;
881        case BLOCK:
882            return ((JCBlock) tree).flags;
883        default:
884            return 0;
885        }
886    }
887
888    /** Return first (smallest) flag in `flags':
889     *  pre: flags != 0
890     */
891    public static long firstFlag(long flags) {
892        long flag = 1;
893        while ((flag & flags & ExtendedStandardFlags) == 0)
894            flag = flag << 1;
895        return flag;
896    }
897
898    /** Return flags as a string, separated by " ".
899     */
900    public static String flagNames(long flags) {
901        return Flags.toString(flags & ExtendedStandardFlags).trim();
902    }
903
904    /** Operator precedences values.
905     */
906    public static final int
907        notExpression = -1,   // not an expression
908        noPrec = 0,           // no enclosing expression
909        assignPrec = 1,
910        assignopPrec = 2,
911        condPrec = 3,
912        orPrec = 4,
913        andPrec = 5,
914        bitorPrec = 6,
915        bitxorPrec = 7,
916        bitandPrec = 8,
917        eqPrec = 9,
918        ordPrec = 10,
919        shiftPrec = 11,
920        addPrec = 12,
921        mulPrec = 13,
922        prefixPrec = 14,
923        postfixPrec = 15,
924        precCount = 16;
925
926
927    /** Map operators to their precedence levels.
928     */
929    public static int opPrec(JCTree.Tag op) {
930        switch(op) {
931        case POS:
932        case NEG:
933        case NOT:
934        case COMPL:
935        case PREINC:
936        case PREDEC: return prefixPrec;
937        case POSTINC:
938        case POSTDEC:
939        case NULLCHK: return postfixPrec;
940        case ASSIGN: return assignPrec;
941        case BITOR_ASG:
942        case BITXOR_ASG:
943        case BITAND_ASG:
944        case SL_ASG:
945        case SR_ASG:
946        case USR_ASG:
947        case PLUS_ASG:
948        case MINUS_ASG:
949        case MUL_ASG:
950        case DIV_ASG:
951        case MOD_ASG: return assignopPrec;
952        case OR: return orPrec;
953        case AND: return andPrec;
954        case EQ:
955        case NE: return eqPrec;
956        case LT:
957        case GT:
958        case LE:
959        case GE: return ordPrec;
960        case BITOR: return bitorPrec;
961        case BITXOR: return bitxorPrec;
962        case BITAND: return bitandPrec;
963        case SL:
964        case SR:
965        case USR: return shiftPrec;
966        case PLUS:
967        case MINUS: return addPrec;
968        case MUL:
969        case DIV:
970        case MOD: return mulPrec;
971        case TYPETEST: return ordPrec;
972        default: throw new AssertionError();
973        }
974    }
975
976    static Tree.Kind tagToKind(JCTree.Tag tag) {
977        switch (tag) {
978        // Postfix expressions
979        case POSTINC:           // _ ++
980            return Tree.Kind.POSTFIX_INCREMENT;
981        case POSTDEC:           // _ --
982            return Tree.Kind.POSTFIX_DECREMENT;
983
984        // Unary operators
985        case PREINC:            // ++ _
986            return Tree.Kind.PREFIX_INCREMENT;
987        case PREDEC:            // -- _
988            return Tree.Kind.PREFIX_DECREMENT;
989        case POS:               // +
990            return Tree.Kind.UNARY_PLUS;
991        case NEG:               // -
992            return Tree.Kind.UNARY_MINUS;
993        case COMPL:             // ~
994            return Tree.Kind.BITWISE_COMPLEMENT;
995        case NOT:               // !
996            return Tree.Kind.LOGICAL_COMPLEMENT;
997
998        // Binary operators
999
1000        // Multiplicative operators
1001        case MUL:               // *
1002            return Tree.Kind.MULTIPLY;
1003        case DIV:               // /
1004            return Tree.Kind.DIVIDE;
1005        case MOD:               // %
1006            return Tree.Kind.REMAINDER;
1007
1008        // Additive operators
1009        case PLUS:              // +
1010            return Tree.Kind.PLUS;
1011        case MINUS:             // -
1012            return Tree.Kind.MINUS;
1013
1014        // Shift operators
1015        case SL:                // <<
1016            return Tree.Kind.LEFT_SHIFT;
1017        case SR:                // >>
1018            return Tree.Kind.RIGHT_SHIFT;
1019        case USR:               // >>>
1020            return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
1021
1022        // Relational operators
1023        case LT:                // <
1024            return Tree.Kind.LESS_THAN;
1025        case GT:                // >
1026            return Tree.Kind.GREATER_THAN;
1027        case LE:                // <=
1028            return Tree.Kind.LESS_THAN_EQUAL;
1029        case GE:                // >=
1030            return Tree.Kind.GREATER_THAN_EQUAL;
1031
1032        // Equality operators
1033        case EQ:                // ==
1034            return Tree.Kind.EQUAL_TO;
1035        case NE:                // !=
1036            return Tree.Kind.NOT_EQUAL_TO;
1037
1038        // Bitwise and logical operators
1039        case BITAND:            // &
1040            return Tree.Kind.AND;
1041        case BITXOR:            // ^
1042            return Tree.Kind.XOR;
1043        case BITOR:             // |
1044            return Tree.Kind.OR;
1045
1046        // Conditional operators
1047        case AND:               // &&
1048            return Tree.Kind.CONDITIONAL_AND;
1049        case OR:                // ||
1050            return Tree.Kind.CONDITIONAL_OR;
1051
1052        // Assignment operators
1053        case MUL_ASG:           // *=
1054            return Tree.Kind.MULTIPLY_ASSIGNMENT;
1055        case DIV_ASG:           // /=
1056            return Tree.Kind.DIVIDE_ASSIGNMENT;
1057        case MOD_ASG:           // %=
1058            return Tree.Kind.REMAINDER_ASSIGNMENT;
1059        case PLUS_ASG:          // +=
1060            return Tree.Kind.PLUS_ASSIGNMENT;
1061        case MINUS_ASG:         // -=
1062            return Tree.Kind.MINUS_ASSIGNMENT;
1063        case SL_ASG:            // <<=
1064            return Tree.Kind.LEFT_SHIFT_ASSIGNMENT;
1065        case SR_ASG:            // >>=
1066            return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT;
1067        case USR_ASG:           // >>>=
1068            return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
1069        case BITAND_ASG:        // &=
1070            return Tree.Kind.AND_ASSIGNMENT;
1071        case BITXOR_ASG:        // ^=
1072            return Tree.Kind.XOR_ASSIGNMENT;
1073        case BITOR_ASG:         // |=
1074            return Tree.Kind.OR_ASSIGNMENT;
1075
1076        // Null check (implementation detail), for example, __.getClass()
1077        case NULLCHK:
1078            return Tree.Kind.OTHER;
1079
1080        case ANNOTATION:
1081            return Tree.Kind.ANNOTATION;
1082        case TYPE_ANNOTATION:
1083            return Tree.Kind.TYPE_ANNOTATION;
1084
1085        case EXPORTS:
1086            return Tree.Kind.EXPORTS;
1087        case OPENS:
1088            return Tree.Kind.OPENS;
1089
1090        default:
1091            return null;
1092        }
1093    }
1094
1095    /**
1096     * Returns the underlying type of the tree if it is an annotated type,
1097     * or the tree itself otherwise.
1098     */
1099    public static JCExpression typeIn(JCExpression tree) {
1100        switch (tree.getTag()) {
1101        case ANNOTATED_TYPE:
1102            return ((JCAnnotatedType)tree).underlyingType;
1103        case IDENT: /* simple names */
1104        case TYPEIDENT: /* primitive name */
1105        case SELECT: /* qualified name */
1106        case TYPEARRAY: /* array types */
1107        case WILDCARD: /* wild cards */
1108        case TYPEPARAMETER: /* type parameters */
1109        case TYPEAPPLY: /* parameterized types */
1110        case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */
1111            return tree;
1112        default:
1113            throw new AssertionError("Unexpected type tree: " + tree);
1114        }
1115    }
1116
1117    /* Return the inner-most type of a type tree.
1118     * For an array that contains an annotated type, return that annotated type.
1119     * TODO: currently only used by Pretty. Describe behavior better.
1120     */
1121    public static JCTree innermostType(JCTree type) {
1122        JCTree lastAnnotatedType = null;
1123        JCTree cur = type;
1124        loop: while (true) {
1125            switch (cur.getTag()) {
1126            case TYPEARRAY:
1127                lastAnnotatedType = null;
1128                cur = ((JCArrayTypeTree)cur).elemtype;
1129                break;
1130            case WILDCARD:
1131                lastAnnotatedType = null;
1132                cur = ((JCWildcard)cur).inner;
1133                break;
1134            case ANNOTATED_TYPE:
1135                lastAnnotatedType = cur;
1136                cur = ((JCAnnotatedType)cur).underlyingType;
1137                break;
1138            default:
1139                break loop;
1140            }
1141        }
1142        if (lastAnnotatedType!=null) {
1143            return lastAnnotatedType;
1144        } else {
1145            return cur;
1146        }
1147    }
1148
1149    private static class TypeAnnotationFinder extends TreeScanner {
1150        public boolean foundTypeAnno = false;
1151
1152        @Override
1153        public void scan(JCTree tree) {
1154            if (foundTypeAnno || tree == null)
1155                return;
1156            super.scan(tree);
1157        }
1158
1159        public void visitAnnotation(JCAnnotation tree) {
1160            foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION);
1161        }
1162    }
1163
1164    public static boolean containsTypeAnnotation(JCTree e) {
1165        TypeAnnotationFinder finder = new TypeAnnotationFinder();
1166        finder.scan(e);
1167        return finder.foundTypeAnno;
1168    }
1169
1170    public static boolean isModuleInfo(JCCompilationUnit tree) {
1171        return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE)
1172                && tree.getModuleDecl() != null;
1173    }
1174
1175    public static JCModuleDecl getModule(JCCompilationUnit t) {
1176        if (t.defs.nonEmpty()) {
1177            JCTree def = t.defs.head;
1178            if (def.hasTag(MODULEDEF))
1179                return (JCModuleDecl) def;
1180        }
1181        return null;
1182    }
1183
1184    public static boolean isPackageInfo(JCCompilationUnit tree) {
1185        return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
1186    }
1187}
1188