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