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