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 
  63     public static List<JCExpression> args(JCTree t) {
  64         switch (t.getTag()) {
  65             case APPLY:
  66                 return ((JCMethodInvocation)t).args;
  67             case NEWCLASS:
  68                 return ((JCNewClass)t).args;
  69             default:
  70                 return null;
  71         }
  72     }
  73 
  74     /** Is tree a constructor declaration?
  75      */
  76     public static boolean isConstructor(JCTree tree) {
  77         if (tree.hasTag(METHODDEF)) {
  78             Name name = ((JCMethodDecl) tree).name;
  79             return name == name.table.names.init;
  80         } else {
  81             return false;
  82         }
  83     }
  84 
  85     public static boolean isReceiverParam(JCTree tree) {
  86         if (tree.hasTag(VARDEF)) {
  87             return ((JCVariableDecl)tree).nameexpr != null;
  88         } else {
  89             return false;
  90         }
  91     }
  92 
  93     /** Is there a constructor declaration in the given list of trees?
  94      */
  95     public static boolean hasConstructors(List<JCTree> trees) {
  96         for (List<JCTree> l = trees; l.nonEmpty(); l = l.tail)
  97             if (isConstructor(l.head)) return true;
  98         return false;
  99     }
 100 
 101     public static boolean isMultiCatch(JCCatch catchClause) {
 102         return catchClause.param.vartype.hasTag(TYPEUNION);
 103     }
 104 
 105     /** Is statement an initializer for a synthetic field?
 106      */
 107     public static boolean isSyntheticInit(JCTree stat) {
 108         if (stat.hasTag(EXEC)) {
 109             JCExpressionStatement exec = (JCExpressionStatement)stat;
 110             if (exec.expr.hasTag(ASSIGN)) {
 111                 JCAssign assign = (JCAssign)exec.expr;
 112                 if (assign.lhs.hasTag(SELECT)) {
 113                     JCFieldAccess select = (JCFieldAccess)assign.lhs;
 114                     if (select.sym != null &&
 115                         (select.sym.flags() & SYNTHETIC) != 0) {
 116                         Name selected = name(select.selected);
 117                         if (selected != null && selected == selected.table.names._this)
 118                             return true;
 119                     }
 120                 }
 121             }
 122         }
 123         return false;
 124     }
 125 
 126     /** If the expression is a method call, return the method name, null
 127      *  otherwise. */
 128     public static Name calledMethodName(JCTree tree) {
 129         if (tree.hasTag(EXEC)) {
 130             JCExpressionStatement exec = (JCExpressionStatement)tree;
 131             if (exec.expr.hasTag(APPLY)) {
 132                 Name mname = TreeInfo.name(((JCMethodInvocation) exec.expr).meth);
 133                 return mname;
 134             }
 135         }
 136         return null;
 137     }
 138 
 139     /** Is this a call to this or super?
 140      */
 141     public static boolean isSelfCall(JCTree tree) {
 142         Name name = calledMethodName(tree);
 143         if (name != null) {
 144             Names names = name.table.names;
 145             return name==names._this || name==names._super;
 146         } else {
 147             return false;
 148         }
 149     }
 150 
 151     /** Is this tree a 'this' identifier?
 152      */
 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      */
 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      */
 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      */
 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. */
 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. */
 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 
 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 */
 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 */
 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 */
 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 */
 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      */
 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
 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. */
 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. */
 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 
 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 
 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      */
 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      */
 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      */
 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      */
 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      */
 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 }