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