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