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