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