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
 387             return tree.pos;
 388     }
 389 
 390 
 391     /** Get the start position for a tree node.  The start position is
 392      * defined to be the position of the first character of the first
 393      * token of the node's source text.
 394      * @param tree  The tree node
 395      */
 396     public static int getStartPos(JCTree tree) {
 397         if (tree == null)
 398             return Position.NOPOS;
 399 
 400         switch(tree.getTag()) {
 401             case MODULEDEF: {
 402                 JCModuleDecl md = (JCModuleDecl)tree;
 403                 return md.mods.annotations.isEmpty() ? md.pos :
 404                        md.mods.annotations.head.pos;
 405             }
 406             case PACKAGEDEF: {
 407                 JCPackageDecl pd = (JCPackageDecl)tree;
 408                 return pd.annotations.isEmpty() ? pd.pos :
 409                        pd.annotations.head.pos;
 410             }
 411             case APPLY:
 412                 return getStartPos(((JCMethodInvocation) tree).meth);
 413             case ASSIGN:
 414                 return getStartPos(((JCAssign) tree).lhs);
 415             case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
 416             case SL_ASG: case SR_ASG: case USR_ASG:
 417             case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
 418             case DIV_ASG: case MOD_ASG:
 419             case OR: case AND: case BITOR:
 420             case BITXOR: case BITAND: case EQ:
 421             case NE: case LT: case GT:
 422             case LE: case GE: case SL:
 423             case SR: case USR: case PLUS:
 424             case MINUS: case MUL: case DIV:
 425             case MOD:
 426             case POSTINC:
 427             case POSTDEC:
 428                 return getStartPos(((JCOperatorExpression) tree).getOperand(LEFT));
 429             case CLASSDEF: {
 430                 JCClassDecl node = (JCClassDecl)tree;
 431                 if (node.mods.pos != Position.NOPOS)
 432                     return node.mods.pos;
 433                 break;
 434             }
 435             case CONDEXPR:
 436                 return getStartPos(((JCConditional) tree).cond);
 437             case EXEC:
 438                 return getStartPos(((JCExpressionStatement) tree).expr);
 439             case INDEXED:
 440                 return getStartPos(((JCArrayAccess) tree).indexed);
 441             case METHODDEF: {
 442                 JCMethodDecl node = (JCMethodDecl)tree;
 443                 if (node.mods.pos != Position.NOPOS)
 444                     return node.mods.pos;
 445                 if (node.typarams.nonEmpty()) // List.nil() used for no typarams
 446                     return getStartPos(node.typarams.head);
 447                 return node.restype == null ? node.pos : getStartPos(node.restype);
 448             }
 449             case SELECT:
 450                 return getStartPos(((JCFieldAccess) tree).selected);
 451             case TYPEAPPLY:
 452                 return getStartPos(((JCTypeApply) tree).clazz);
 453             case TYPEARRAY:
 454                 return getStartPos(((JCArrayTypeTree) tree).elemtype);
 455             case TYPETEST:
 456                 return getStartPos(((JCInstanceOf) tree).expr);
 457             case ANNOTATED_TYPE: {
 458                 JCAnnotatedType node = (JCAnnotatedType) tree;
 459                 if (node.annotations.nonEmpty()) {
 460                     if (node.underlyingType.hasTag(TYPEARRAY) ||
 461                             node.underlyingType.hasTag(SELECT)) {
 462                         return getStartPos(node.underlyingType);
 463                     } else {
 464                         return getStartPos(node.annotations.head);
 465                     }
 466                 } else {
 467                     return getStartPos(node.underlyingType);
 468                 }
 469             }
 470             case NEWCLASS: {
 471                 JCNewClass node = (JCNewClass)tree;
 472                 if (node.encl != null)
 473                     return getStartPos(node.encl);
 474                 break;
 475             }
 476             case VARDEF: {
 477                 JCVariableDecl node = (JCVariableDecl)tree;
 478                 if (node.startPos != Position.NOPOS) {
 479                     return node.startPos;
 480                 } else if (node.mods.pos != Position.NOPOS) {
 481                     return node.mods.pos;
 482                 } else if (node.vartype == null || node.vartype.pos == Position.NOPOS) {
 483                     //if there's no type (partially typed lambda parameter)
 484                     //simply return node position
 485                     return node.pos;
 486                 } else {
 487                     return getStartPos(node.vartype);
 488                 }
 489             }
 490             case ERRONEOUS: {
 491                 JCErroneous node = (JCErroneous)tree;
 492                 if (node.errs != null && node.errs.nonEmpty())
 493                     return getStartPos(node.errs.head);
 494             }
 495         }
 496         return tree.pos;
 497     }
 498 
 499     /** The end position of given tree, given  a table of end positions generated by the parser
 500      */
 501     public static int getEndPos(JCTree tree, EndPosTable endPosTable) {
 502         if (tree == null)
 503             return Position.NOPOS;
 504 
 505         if (endPosTable == null) {
 506             // fall back on limited info in the tree
 507             return endPos(tree);
 508         }
 509 
 510         int mapPos = endPosTable.getEndPos(tree);
 511         if (mapPos != Position.NOPOS)
 512             return mapPos;
 513 
 514         switch(tree.getTag()) {
 515             case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
 516             case SL_ASG: case SR_ASG: case USR_ASG:
 517             case PLUS_ASG: case MINUS_ASG: case MUL_ASG:
 518             case DIV_ASG: case MOD_ASG:
 519             case OR: case AND: case BITOR:
 520             case BITXOR: case BITAND: case EQ:
 521             case NE: case LT: case GT:
 522             case LE: case GE: case SL:
 523             case SR: case USR: case PLUS:
 524             case MINUS: case MUL: case DIV:
 525             case MOD:
 526             case POS:
 527             case NEG:
 528             case NOT:
 529             case COMPL:
 530             case PREINC:
 531             case PREDEC:
 532                 return getEndPos(((JCOperatorExpression) tree).getOperand(RIGHT), endPosTable);
 533             case CASE:
 534                 return getEndPos(((JCCase) tree).stats.last(), endPosTable);
 535             case CATCH:
 536                 return getEndPos(((JCCatch) tree).body, endPosTable);
 537             case CONDEXPR:
 538                 return getEndPos(((JCConditional) tree).falsepart, endPosTable);
 539             case FORLOOP:
 540                 return getEndPos(((JCForLoop) tree).body, endPosTable);
 541             case FOREACHLOOP:
 542                 return getEndPos(((JCEnhancedForLoop) tree).body, endPosTable);
 543             case IF: {
 544                 JCIf node = (JCIf)tree;
 545                 if (node.elsepart == null) {
 546                     return getEndPos(node.thenpart, endPosTable);
 547                 } else {
 548                     return getEndPos(node.elsepart, endPosTable);
 549                 }
 550             }
 551             case LABELLED:
 552                 return getEndPos(((JCLabeledStatement) tree).body, endPosTable);
 553             case MODIFIERS:
 554                 return getEndPos(((JCModifiers) tree).annotations.last(), endPosTable);
 555             case SYNCHRONIZED:
 556                 return getEndPos(((JCSynchronized) tree).body, endPosTable);
 557             case TOPLEVEL:
 558                 return getEndPos(((JCCompilationUnit) tree).defs.last(), endPosTable);
 559             case TRY: {
 560                 JCTry node = (JCTry)tree;
 561                 if (node.finalizer != null) {
 562                     return getEndPos(node.finalizer, endPosTable);
 563                 } else if (!node.catchers.isEmpty()) {
 564                     return getEndPos(node.catchers.last(), endPosTable);
 565                 } else {
 566                     return getEndPos(node.body, endPosTable);
 567                 }
 568             }
 569             case WILDCARD:
 570                 return getEndPos(((JCWildcard) tree).inner, endPosTable);
 571             case TYPECAST:
 572                 return getEndPos(((JCTypeCast) tree).expr, endPosTable);
 573             case TYPETEST:
 574                 return getEndPos(((JCInstanceOf) tree).clazz, endPosTable);
 575             case WHILELOOP:
 576                 return getEndPos(((JCWhileLoop) tree).body, endPosTable);
 577             case ANNOTATED_TYPE:
 578                 return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable);
 579             case ERRONEOUS: {
 580                 JCErroneous node = (JCErroneous)tree;
 581                 if (node.errs != null && node.errs.nonEmpty())
 582                     return getEndPos(node.errs.last(), endPosTable);
 583             }
 584         }
 585         return Position.NOPOS;
 586     }
 587 
 588 
 589     /** A DiagnosticPosition with the preferred position set to the
 590      *  end position of given tree, if it is a block with
 591      *  defined endpos.
 592      */
 593     public static DiagnosticPosition diagEndPos(final JCTree tree) {
 594         final int endPos = TreeInfo.endPos(tree);
 595         return new DiagnosticPosition() {
 596             public JCTree getTree() { return tree; }
 597             public int getStartPosition() { return TreeInfo.getStartPos(tree); }
 598             public int getPreferredPosition() { return endPos; }
 599             public int getEndPosition(EndPosTable endPosTable) {
 600                 return TreeInfo.getEndPos(tree, endPosTable);
 601             }
 602         };
 603     }
 604 
 605     public enum PosKind {
 606         START_POS(TreeInfo::getStartPos),
 607         FIRST_STAT_POS(TreeInfo::firstStatPos),
 608         END_POS(TreeInfo::endPos);
 609 
 610         final ToIntFunction<JCTree> posFunc;
 611 
 612         PosKind(ToIntFunction<JCTree> posFunc) {
 613             this.posFunc = posFunc;
 614         }
 615 
 616         int toPos(JCTree tree) {
 617             return posFunc.applyAsInt(tree);
 618         }
 619     }
 620 
 621     /** The position of the finalizer of given try/synchronized statement.
 622      */
 623     public static int finalizerPos(JCTree tree, PosKind posKind) {
 624         if (tree.hasTag(TRY)) {
 625             JCTry t = (JCTry) tree;
 626             Assert.checkNonNull(t.finalizer);
 627             return posKind.toPos(t.finalizer);
 628         } else if (tree.hasTag(SYNCHRONIZED)) {
 629             return endPos(((JCSynchronized) tree).body);
 630         } else {
 631             throw new AssertionError();
 632         }
 633     }
 634 
 635     /** Find the position for reporting an error about a symbol, where
 636      *  that symbol is defined somewhere in the given tree. */
 637     public static int positionFor(final Symbol sym, final JCTree tree) {
 638         JCTree decl = declarationFor(sym, tree);
 639         return ((decl != null) ? decl : tree).pos;
 640     }
 641 
 642     /** Find the position for reporting an error about a symbol, where
 643      *  that symbol is defined somewhere in the given tree. */
 644     public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) {
 645         JCTree decl = declarationFor(sym, tree);
 646         return ((decl != null) ? decl : tree).pos();
 647     }
 648 
 649     /** Find the declaration for a symbol, where
 650      *  that symbol is defined somewhere in the given tree. */
 651     public static JCTree declarationFor(final Symbol sym, final JCTree tree) {
 652         class DeclScanner extends TreeScanner {
 653             JCTree result = null;
 654             public void scan(JCTree tree) {
 655                 if (tree!=null && result==null)
 656                     tree.accept(this);
 657             }
 658             public void visitTopLevel(JCCompilationUnit that) {
 659                 if (that.packge == sym) result = that;
 660                 else super.visitTopLevel(that);
 661             }
 662             public void visitModuleDef(JCModuleDecl that) {
 663                 if (that.sym == sym) result = that;
 664                 // no need to scan within module declaration
 665             }
 666             public void visitPackageDef(JCPackageDecl that) {
 667                 if (that.packge == sym) result = that;
 668                 else super.visitPackageDef(that);
 669             }
 670             public void visitClassDef(JCClassDecl that) {
 671                 if (that.sym == sym) result = that;
 672                 else super.visitClassDef(that);
 673             }
 674             public void visitMethodDef(JCMethodDecl that) {
 675                 if (that.sym == sym) result = that;
 676                 else super.visitMethodDef(that);
 677             }
 678             public void visitVarDef(JCVariableDecl that) {
 679                 if (that.sym == sym) result = that;
 680                 else super.visitVarDef(that);
 681             }
 682             public void visitTypeParameter(JCTypeParameter that) {
 683                 if (that.type != null && that.type.tsym == sym) result = that;
 684                 else super.visitTypeParameter(that);
 685             }
 686         }
 687         DeclScanner s = new DeclScanner();
 688         tree.accept(s);
 689         return s.result;
 690     }
 691 
 692     public static Env<AttrContext> scopeFor(JCTree node, JCCompilationUnit unit) {
 693         return scopeFor(pathFor(node, unit));
 694     }
 695 
 696     public static Env<AttrContext> scopeFor(List<JCTree> path) {
 697         // TODO: not implemented yet
 698         throw new UnsupportedOperationException("not implemented yet");
 699     }
 700 
 701     public static List<JCTree> pathFor(final JCTree node, final JCCompilationUnit unit) {
 702         class Result extends Error {
 703             static final long serialVersionUID = -5942088234594905625L;
 704             List<JCTree> path;
 705             Result(List<JCTree> path) {
 706                 this.path = path;
 707             }
 708         }
 709         class PathFinder extends TreeScanner {
 710             List<JCTree> path = List.nil();
 711             public void scan(JCTree tree) {
 712                 if (tree != null) {
 713                     path = path.prepend(tree);
 714                     if (tree == node)
 715                         throw new Result(path);
 716                     super.scan(tree);
 717                     path = path.tail;
 718                 }
 719             }
 720         }
 721         try {
 722             new PathFinder().scan(unit);
 723         } catch (Result result) {
 724             return result.path;
 725         }
 726         return List.nil();
 727     }
 728 
 729     /** Return the statement referenced by a label.
 730      *  If the label refers to a loop or switch, return that switch
 731      *  otherwise return the labelled statement itself
 732      */
 733     public static JCTree referencedStatement(JCLabeledStatement tree) {
 734         JCTree t = tree;
 735         do t = ((JCLabeledStatement) t).body;
 736         while (t.hasTag(LABELLED));
 737         switch (t.getTag()) {
 738         case DOLOOP: case WHILELOOP: case FORLOOP: case FOREACHLOOP: case SWITCH:
 739             return t;
 740         default:
 741             return tree;
 742         }
 743     }
 744 
 745     /** Skip parens and return the enclosed expression
 746      */
 747     public static JCExpression skipParens(JCExpression tree) {
 748         while (tree.hasTag(PARENS)) {
 749             tree = ((JCParens) tree).expr;
 750         }
 751         return tree;
 752     }
 753 
 754     /** Skip parens and return the enclosed expression
 755      */
 756     public static JCTree skipParens(JCTree tree) {
 757         if (tree.hasTag(PARENS))
 758             return skipParens((JCParens)tree);
 759         else
 760             return tree;
 761     }
 762 
 763     /** Return the types of a list of trees.
 764      */
 765     public static List<Type> types(List<? extends JCTree> trees) {
 766         ListBuffer<Type> ts = new ListBuffer<>();
 767         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
 768             ts.append(l.head.type);
 769         return ts.toList();
 770     }
 771 
 772     /** If this tree is an identifier or a field or a parameterized type,
 773      *  return its name, otherwise return null.
 774      */
 775     public static Name name(JCTree tree) {
 776         switch (tree.getTag()) {
 777         case IDENT:
 778             return ((JCIdent) tree).name;
 779         case SELECT:
 780             return ((JCFieldAccess) tree).name;
 781         case TYPEAPPLY:
 782             return name(((JCTypeApply) tree).clazz);
 783         default:
 784             return null;
 785         }
 786     }
 787 
 788     /** If this tree is a qualified identifier, its return fully qualified name,
 789      *  otherwise return null.
 790      */
 791     public static Name fullName(JCTree tree) {
 792         tree = skipParens(tree);
 793         switch (tree.getTag()) {
 794         case IDENT:
 795             return ((JCIdent) tree).name;
 796         case SELECT:
 797             Name sname = fullName(((JCFieldAccess) tree).selected);
 798             return sname == null ? null : sname.append('.', name(tree));
 799         default:
 800             return null;
 801         }
 802     }
 803 
 804     public static Symbol symbolFor(JCTree node) {
 805         Symbol sym = symbolForImpl(node);
 806 
 807         return sym != null ? sym.baseSymbol() : null;
 808     }
 809 
 810     private static Symbol symbolForImpl(JCTree node) {
 811         node = skipParens(node);
 812         switch (node.getTag()) {
 813         case TOPLEVEL:
 814             JCCompilationUnit cut = (JCCompilationUnit) node;
 815             JCModuleDecl moduleDecl = cut.getModuleDecl();
 816             if (isModuleInfo(cut) && moduleDecl != null)
 817                 return symbolFor(moduleDecl);
 818             return cut.packge;
 819         case MODULEDEF:
 820             return ((JCModuleDecl) node).sym;
 821         case PACKAGEDEF:
 822             return ((JCPackageDecl) node).packge;
 823         case CLASSDEF:
 824             return ((JCClassDecl) node).sym;
 825         case METHODDEF:
 826             return ((JCMethodDecl) node).sym;
 827         case VARDEF:
 828             return ((JCVariableDecl) node).sym;
 829         case IDENT:
 830             return ((JCIdent) node).sym;
 831         case SELECT:
 832             return ((JCFieldAccess) node).sym;
 833         case REFERENCE:
 834             return ((JCMemberReference) node).sym;
 835         case NEWCLASS:
 836             return ((JCNewClass) node).constructor;
 837         case APPLY:
 838             return symbolFor(((JCMethodInvocation) node).meth);
 839         case TYPEAPPLY:
 840             return symbolFor(((JCTypeApply) node).clazz);
 841         case ANNOTATION:
 842         case TYPE_ANNOTATION:
 843         case TYPEPARAMETER:
 844             if (node.type != null)
 845                 return node.type.tsym;
 846             return null;
 847         default:
 848             return null;
 849         }
 850     }
 851 
 852     public static boolean isDeclaration(JCTree node) {
 853         node = skipParens(node);
 854         switch (node.getTag()) {
 855         case PACKAGEDEF:
 856         case CLASSDEF:
 857         case METHODDEF:
 858         case VARDEF:
 859             return true;
 860         default:
 861             return false;
 862         }
 863     }
 864 
 865     /** If this tree is an identifier or a field, return its symbol,
 866      *  otherwise return null.
 867      */
 868     public static Symbol symbol(JCTree tree) {
 869         tree = skipParens(tree);
 870         switch (tree.getTag()) {
 871         case IDENT:
 872             return ((JCIdent) tree).sym;
 873         case SELECT:
 874             return ((JCFieldAccess) tree).sym;
 875         case TYPEAPPLY:
 876             return symbol(((JCTypeApply) tree).clazz);
 877         case ANNOTATED_TYPE:
 878             return symbol(((JCAnnotatedType) tree).underlyingType);
 879         case REFERENCE:
 880             return ((JCMemberReference) tree).sym;
 881         default:
 882             return null;
 883         }
 884     }
 885 
 886     /** Return true if this is a nonstatic selection. */
 887     public static boolean nonstaticSelect(JCTree tree) {
 888         tree = skipParens(tree);
 889         if (!tree.hasTag(SELECT)) return false;
 890         JCFieldAccess s = (JCFieldAccess) tree;
 891         Symbol e = symbol(s.selected);
 892         return e == null || (e.kind != PCK && e.kind != TYP);
 893     }
 894 
 895     /** If this tree is an identifier or a field, set its symbol, otherwise skip.
 896      */
 897     public static void setSymbol(JCTree tree, Symbol sym) {
 898         tree = skipParens(tree);
 899         switch (tree.getTag()) {
 900         case IDENT:
 901             ((JCIdent) tree).sym = sym; break;
 902         case SELECT:
 903             ((JCFieldAccess) tree).sym = sym; break;
 904         default:
 905         }
 906     }
 907 
 908     /** If this tree is a declaration or a block, return its flags field,
 909      *  otherwise return 0.
 910      */
 911     public static long flags(JCTree tree) {
 912         switch (tree.getTag()) {
 913         case VARDEF:
 914             return ((JCVariableDecl) tree).mods.flags;
 915         case METHODDEF:
 916             return ((JCMethodDecl) tree).mods.flags;
 917         case CLASSDEF:
 918             return ((JCClassDecl) tree).mods.flags;
 919         case BLOCK:
 920             return ((JCBlock) tree).flags;
 921         default:
 922             return 0;
 923         }
 924     }
 925 
 926     /** Return first (smallest) flag in `flags':
 927      *  pre: flags != 0
 928      */
 929     public static long firstFlag(long flags) {
 930         long flag = 1;
 931         while ((flag & flags & ExtendedStandardFlags) == 0)
 932             flag = flag << 1;
 933         return flag;
 934     }
 935 
 936     /** Return flags as a string, separated by " ".
 937      */
 938     public static String flagNames(long flags) {
 939         return Flags.toString(flags & ExtendedStandardFlags).trim();
 940     }
 941 
 942     /** Operator precedences values.
 943      */
 944     public static final int
 945         notExpression = -1,   // not an expression
 946         noPrec = 0,           // no enclosing expression
 947         assignPrec = 1,
 948         assignopPrec = 2,
 949         condPrec = 3,
 950         orPrec = 4,
 951         andPrec = 5,
 952         bitorPrec = 6,
 953         bitxorPrec = 7,
 954         bitandPrec = 8,
 955         eqPrec = 9,
 956         ordPrec = 10,
 957         shiftPrec = 11,
 958         addPrec = 12,
 959         mulPrec = 13,
 960         prefixPrec = 14,
 961         postfixPrec = 15,
 962         precCount = 16;
 963 
 964 
 965     /** Map operators to their precedence levels.
 966      */
 967     public static int opPrec(JCTree.Tag op) {
 968         switch(op) {
 969         case POS:
 970         case NEG:
 971         case NOT:
 972         case COMPL:
 973         case PREINC:
 974         case PREDEC: return prefixPrec;
 975         case POSTINC:
 976         case POSTDEC:
 977         case NULLCHK: return postfixPrec;
 978         case ASSIGN: return assignPrec;
 979         case BITOR_ASG:
 980         case BITXOR_ASG:
 981         case BITAND_ASG:
 982         case SL_ASG:
 983         case SR_ASG:
 984         case USR_ASG:
 985         case PLUS_ASG:
 986         case MINUS_ASG:
 987         case MUL_ASG:
 988         case DIV_ASG:
 989         case MOD_ASG: return assignopPrec;
 990         case OR: return orPrec;
 991         case AND: return andPrec;
 992         case EQ:
 993         case NE: return eqPrec;
 994         case LT:
 995         case GT:
 996         case LE:
 997         case GE: return ordPrec;
 998         case BITOR: return bitorPrec;
 999         case BITXOR: return bitxorPrec;
1000         case BITAND: return bitandPrec;
1001         case SL:
1002         case SR:
1003         case USR: return shiftPrec;
1004         case PLUS:
1005         case MINUS: return addPrec;
1006         case MUL:
1007         case DIV:
1008         case MOD: return mulPrec;
1009         case TYPETEST: return ordPrec;
1010         default: throw new AssertionError();
1011         }
1012     }
1013 
1014     static Tree.Kind tagToKind(JCTree.Tag tag) {
1015         switch (tag) {
1016         // Postfix expressions
1017         case POSTINC:           // _ ++
1018             return Tree.Kind.POSTFIX_INCREMENT;
1019         case POSTDEC:           // _ --
1020             return Tree.Kind.POSTFIX_DECREMENT;
1021 
1022         // Unary operators
1023         case PREINC:            // ++ _
1024             return Tree.Kind.PREFIX_INCREMENT;
1025         case PREDEC:            // -- _
1026             return Tree.Kind.PREFIX_DECREMENT;
1027         case POS:               // +
1028             return Tree.Kind.UNARY_PLUS;
1029         case NEG:               // -
1030             return Tree.Kind.UNARY_MINUS;
1031         case COMPL:             // ~
1032             return Tree.Kind.BITWISE_COMPLEMENT;
1033         case NOT:               // !
1034             return Tree.Kind.LOGICAL_COMPLEMENT;
1035 
1036         // Binary operators
1037 
1038         // Multiplicative operators
1039         case MUL:               // *
1040             return Tree.Kind.MULTIPLY;
1041         case DIV:               // /
1042             return Tree.Kind.DIVIDE;
1043         case MOD:               // %
1044             return Tree.Kind.REMAINDER;
1045 
1046         // Additive operators
1047         case PLUS:              // +
1048             return Tree.Kind.PLUS;
1049         case MINUS:             // -
1050             return Tree.Kind.MINUS;
1051 
1052         // Shift operators
1053         case SL:                // <<
1054             return Tree.Kind.LEFT_SHIFT;
1055         case SR:                // >>
1056             return Tree.Kind.RIGHT_SHIFT;
1057         case USR:               // >>>
1058             return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
1059 
1060         // Relational operators
1061         case LT:                // <
1062             return Tree.Kind.LESS_THAN;
1063         case GT:                // >
1064             return Tree.Kind.GREATER_THAN;
1065         case LE:                // <=
1066             return Tree.Kind.LESS_THAN_EQUAL;
1067         case GE:                // >=
1068             return Tree.Kind.GREATER_THAN_EQUAL;
1069 
1070         // Equality operators
1071         case EQ:                // ==
1072             return Tree.Kind.EQUAL_TO;
1073         case NE:                // !=
1074             return Tree.Kind.NOT_EQUAL_TO;
1075 
1076         // Bitwise and logical operators
1077         case BITAND:            // &
1078             return Tree.Kind.AND;
1079         case BITXOR:            // ^
1080             return Tree.Kind.XOR;
1081         case BITOR:             // |
1082             return Tree.Kind.OR;
1083 
1084         // Conditional operators
1085         case AND:               // &&
1086             return Tree.Kind.CONDITIONAL_AND;
1087         case OR:                // ||
1088             return Tree.Kind.CONDITIONAL_OR;
1089 
1090         // Assignment operators
1091         case MUL_ASG:           // *=
1092             return Tree.Kind.MULTIPLY_ASSIGNMENT;
1093         case DIV_ASG:           // /=
1094             return Tree.Kind.DIVIDE_ASSIGNMENT;
1095         case MOD_ASG:           // %=
1096             return Tree.Kind.REMAINDER_ASSIGNMENT;
1097         case PLUS_ASG:          // +=
1098             return Tree.Kind.PLUS_ASSIGNMENT;
1099         case MINUS_ASG:         // -=
1100             return Tree.Kind.MINUS_ASSIGNMENT;
1101         case SL_ASG:            // <<=
1102             return Tree.Kind.LEFT_SHIFT_ASSIGNMENT;
1103         case SR_ASG:            // >>=
1104             return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT;
1105         case USR_ASG:           // >>>=
1106             return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
1107         case BITAND_ASG:        // &=
1108             return Tree.Kind.AND_ASSIGNMENT;
1109         case BITXOR_ASG:        // ^=
1110             return Tree.Kind.XOR_ASSIGNMENT;
1111         case BITOR_ASG:         // |=
1112             return Tree.Kind.OR_ASSIGNMENT;
1113 
1114         // Null check (implementation detail), for example, __.getClass()
1115         case NULLCHK:
1116             return Tree.Kind.OTHER;
1117 
1118         case ANNOTATION:
1119             return Tree.Kind.ANNOTATION;
1120         case TYPE_ANNOTATION:
1121             return Tree.Kind.TYPE_ANNOTATION;
1122 
1123         case EXPORTS:
1124             return Tree.Kind.EXPORTS;
1125         case OPENS:
1126             return Tree.Kind.OPENS;
1127 
1128         default:
1129             return null;
1130         }
1131     }
1132 
1133     /**
1134      * Returns the underlying type of the tree if it is an annotated type,
1135      * or the tree itself otherwise.
1136      */
1137     public static JCExpression typeIn(JCExpression tree) {
1138         switch (tree.getTag()) {
1139         case ANNOTATED_TYPE:
1140             return ((JCAnnotatedType)tree).underlyingType;
1141         case IDENT: /* simple names */
1142         case TYPEIDENT: /* primitive name */
1143         case SELECT: /* qualified name */
1144         case TYPEARRAY: /* array types */
1145         case WILDCARD: /* wild cards */
1146         case TYPEPARAMETER: /* type parameters */
1147         case TYPEAPPLY: /* parameterized types */
1148         case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */
1149             return tree;
1150         default:
1151             throw new AssertionError("Unexpected type tree: " + tree);
1152         }
1153     }
1154 
1155     /* Return the inner-most type of a type tree.
1156      * For an array that contains an annotated type, return that annotated type.
1157      * TODO: currently only used by Pretty. Describe behavior better.
1158      */
1159     public static JCTree innermostType(JCTree type, boolean skipAnnos) {
1160         JCTree lastAnnotatedType = null;
1161         JCTree cur = type;
1162         loop: while (true) {
1163             switch (cur.getTag()) {
1164             case TYPEARRAY:
1165                 lastAnnotatedType = null;
1166                 cur = ((JCArrayTypeTree)cur).elemtype;
1167                 break;
1168             case WILDCARD:
1169                 lastAnnotatedType = null;
1170                 cur = ((JCWildcard)cur).inner;
1171                 break;
1172             case ANNOTATED_TYPE:
1173                 lastAnnotatedType = cur;
1174                 cur = ((JCAnnotatedType)cur).underlyingType;
1175                 break;
1176             default:
1177                 break loop;
1178             }
1179         }
1180         if (!skipAnnos && lastAnnotatedType!=null) {
1181             return lastAnnotatedType;
1182         } else {
1183             return cur;
1184         }
1185     }
1186 
1187     private static class TypeAnnotationFinder extends TreeScanner {
1188         public boolean foundTypeAnno = false;
1189 
1190         @Override
1191         public void scan(JCTree tree) {
1192             if (foundTypeAnno || tree == null)
1193                 return;
1194             super.scan(tree);
1195         }
1196 
1197         public void visitAnnotation(JCAnnotation tree) {
1198             foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION);
1199         }
1200     }
1201 
1202     public static boolean containsTypeAnnotation(JCTree e) {
1203         TypeAnnotationFinder finder = new TypeAnnotationFinder();
1204         finder.scan(e);
1205         return finder.foundTypeAnno;
1206     }
1207 
1208     public static boolean isModuleInfo(JCCompilationUnit tree) {
1209         return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE)
1210                 && tree.getModuleDecl() != null;
1211     }
1212 
1213     public static JCModuleDecl getModule(JCCompilationUnit t) {
1214         if (t.defs.nonEmpty()) {
1215             JCTree def = t.defs.head;
1216             if (def.hasTag(MODULEDEF))
1217                 return (JCModuleDecl) def;
1218         }
1219         return null;
1220     }
1221 
1222     public static boolean isPackageInfo(JCCompilationUnit tree) {
1223         return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
1224     }
1225 }