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