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