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