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