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