TreeInfo.java revision 3792:d516975e8110
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 MODULEDEF: { 382 JCModuleDecl md = (JCModuleDecl)tree; 383 return md.mods.annotations.isEmpty() ? md.pos : 384 md.mods.annotations.head.pos; 385 } 386 case PACKAGEDEF: { 387 JCPackageDecl pd = (JCPackageDecl)tree; 388 return pd.annotations.isEmpty() ? pd.pos : 389 pd.annotations.head.pos; 390 } 391 case APPLY: 392 return getStartPos(((JCMethodInvocation) tree).meth); 393 case ASSIGN: 394 return getStartPos(((JCAssign) tree).lhs); 395 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: 396 case SL_ASG: case SR_ASG: case USR_ASG: 397 case PLUS_ASG: case MINUS_ASG: case MUL_ASG: 398 case DIV_ASG: case MOD_ASG: 399 case OR: case AND: case BITOR: 400 case BITXOR: case BITAND: case EQ: 401 case NE: case LT: case GT: 402 case LE: case GE: case SL: 403 case SR: case USR: case PLUS: 404 case MINUS: case MUL: case DIV: 405 case MOD: 406 case POSTINC: 407 case POSTDEC: 408 return getStartPos(((JCOperatorExpression) tree).getOperand(LEFT)); 409 case CLASSDEF: { 410 JCClassDecl node = (JCClassDecl)tree; 411 if (node.mods.pos != Position.NOPOS) 412 return node.mods.pos; 413 break; 414 } 415 case CONDEXPR: 416 return getStartPos(((JCConditional) tree).cond); 417 case EXEC: 418 return getStartPos(((JCExpressionStatement) tree).expr); 419 case INDEXED: 420 return getStartPos(((JCArrayAccess) tree).indexed); 421 case METHODDEF: { 422 JCMethodDecl node = (JCMethodDecl)tree; 423 if (node.mods.pos != Position.NOPOS) 424 return node.mods.pos; 425 if (node.typarams.nonEmpty()) // List.nil() used for no typarams 426 return getStartPos(node.typarams.head); 427 return node.restype == null ? node.pos : getStartPos(node.restype); 428 } 429 case SELECT: 430 return getStartPos(((JCFieldAccess) tree).selected); 431 case TYPEAPPLY: 432 return getStartPos(((JCTypeApply) tree).clazz); 433 case TYPEARRAY: 434 return getStartPos(((JCArrayTypeTree) tree).elemtype); 435 case TYPETEST: 436 return getStartPos(((JCInstanceOf) tree).expr); 437 case ANNOTATED_TYPE: { 438 JCAnnotatedType node = (JCAnnotatedType) tree; 439 if (node.annotations.nonEmpty()) { 440 if (node.underlyingType.hasTag(TYPEARRAY) || 441 node.underlyingType.hasTag(SELECT)) { 442 return getStartPos(node.underlyingType); 443 } else { 444 return getStartPos(node.annotations.head); 445 } 446 } else { 447 return getStartPos(node.underlyingType); 448 } 449 } 450 case NEWCLASS: { 451 JCNewClass node = (JCNewClass)tree; 452 if (node.encl != null) 453 return getStartPos(node.encl); 454 break; 455 } 456 case VARDEF: { 457 JCVariableDecl node = (JCVariableDecl)tree; 458 if (node.mods.pos != Position.NOPOS) { 459 return node.mods.pos; 460 } else if (node.vartype == null) { 461 //if there's no type (partially typed lambda parameter) 462 //simply return node position 463 return node.pos; 464 } else { 465 return getStartPos(node.vartype); 466 } 467 } 468 case ERRONEOUS: { 469 JCErroneous node = (JCErroneous)tree; 470 if (node.errs != null && node.errs.nonEmpty()) 471 return getStartPos(node.errs.head); 472 } 473 } 474 return tree.pos; 475 } 476 477 /** The end position of given tree, given a table of end positions generated by the parser 478 */ 479 public static int getEndPos(JCTree tree, EndPosTable endPosTable) { 480 if (tree == null) 481 return Position.NOPOS; 482 483 if (endPosTable == null) { 484 // fall back on limited info in the tree 485 return endPos(tree); 486 } 487 488 int mapPos = endPosTable.getEndPos(tree); 489 if (mapPos != Position.NOPOS) 490 return mapPos; 491 492 switch(tree.getTag()) { 493 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: 494 case SL_ASG: case SR_ASG: case USR_ASG: 495 case PLUS_ASG: case MINUS_ASG: case MUL_ASG: 496 case DIV_ASG: case MOD_ASG: 497 case OR: case AND: case BITOR: 498 case BITXOR: case BITAND: case EQ: 499 case NE: case LT: case GT: 500 case LE: case GE: case SL: 501 case SR: case USR: case PLUS: 502 case MINUS: case MUL: case DIV: 503 case MOD: 504 case POS: 505 case NEG: 506 case NOT: 507 case COMPL: 508 case PREINC: 509 case PREDEC: 510 return getEndPos(((JCOperatorExpression) tree).getOperand(RIGHT), endPosTable); 511 case CASE: 512 return getEndPos(((JCCase) tree).stats.last(), endPosTable); 513 case CATCH: 514 return getEndPos(((JCCatch) tree).body, endPosTable); 515 case CONDEXPR: 516 return getEndPos(((JCConditional) tree).falsepart, endPosTable); 517 case FORLOOP: 518 return getEndPos(((JCForLoop) tree).body, endPosTable); 519 case FOREACHLOOP: 520 return getEndPos(((JCEnhancedForLoop) tree).body, endPosTable); 521 case IF: { 522 JCIf node = (JCIf)tree; 523 if (node.elsepart == null) { 524 return getEndPos(node.thenpart, endPosTable); 525 } else { 526 return getEndPos(node.elsepart, endPosTable); 527 } 528 } 529 case LABELLED: 530 return getEndPos(((JCLabeledStatement) tree).body, endPosTable); 531 case MODIFIERS: 532 return getEndPos(((JCModifiers) tree).annotations.last(), endPosTable); 533 case SYNCHRONIZED: 534 return getEndPos(((JCSynchronized) tree).body, endPosTable); 535 case TOPLEVEL: 536 return getEndPos(((JCCompilationUnit) tree).defs.last(), endPosTable); 537 case TRY: { 538 JCTry node = (JCTry)tree; 539 if (node.finalizer != null) { 540 return getEndPos(node.finalizer, endPosTable); 541 } else if (!node.catchers.isEmpty()) { 542 return getEndPos(node.catchers.last(), endPosTable); 543 } else { 544 return getEndPos(node.body, endPosTable); 545 } 546 } 547 case WILDCARD: 548 return getEndPos(((JCWildcard) tree).inner, endPosTable); 549 case TYPECAST: 550 return getEndPos(((JCTypeCast) tree).expr, endPosTable); 551 case TYPETEST: 552 return getEndPos(((JCInstanceOf) tree).clazz, endPosTable); 553 case WHILELOOP: 554 return getEndPos(((JCWhileLoop) tree).body, endPosTable); 555 case ANNOTATED_TYPE: 556 return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable); 557 case ERRONEOUS: { 558 JCErroneous node = (JCErroneous)tree; 559 if (node.errs != null && node.errs.nonEmpty()) 560 return getEndPos(node.errs.last(), endPosTable); 561 } 562 } 563 return Position.NOPOS; 564 } 565 566 567 /** A DiagnosticPosition with the preferred position set to the 568 * end position of given tree, if it is a block with 569 * defined endpos. 570 */ 571 public static DiagnosticPosition diagEndPos(final JCTree tree) { 572 final int endPos = TreeInfo.endPos(tree); 573 return new DiagnosticPosition() { 574 public JCTree getTree() { return tree; } 575 public int getStartPosition() { return TreeInfo.getStartPos(tree); } 576 public int getPreferredPosition() { return endPos; } 577 public int getEndPosition(EndPosTable endPosTable) { 578 return TreeInfo.getEndPos(tree, endPosTable); 579 } 580 }; 581 } 582 583 /** The position of the finalizer of given try/synchronized statement. 584 */ 585 public static int finalizerPos(JCTree tree) { 586 if (tree.hasTag(TRY)) { 587 JCTry t = (JCTry) tree; 588 Assert.checkNonNull(t.finalizer); 589 return firstStatPos(t.finalizer); 590 } else if (tree.hasTag(SYNCHRONIZED)) { 591 return endPos(((JCSynchronized) tree).body); 592 } else { 593 throw new AssertionError(); 594 } 595 } 596 597 /** Find the position for reporting an error about a symbol, where 598 * that symbol is defined somewhere in the given tree. */ 599 public static int positionFor(final Symbol sym, final JCTree tree) { 600 JCTree decl = declarationFor(sym, tree); 601 return ((decl != null) ? decl : tree).pos; 602 } 603 604 /** Find the position for reporting an error about a symbol, where 605 * that symbol is defined somewhere in the given tree. */ 606 public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) { 607 JCTree decl = declarationFor(sym, tree); 608 return ((decl != null) ? decl : tree).pos(); 609 } 610 611 /** Find the declaration for a symbol, where 612 * that symbol is defined somewhere in the given tree. */ 613 public static JCTree declarationFor(final Symbol sym, final JCTree tree) { 614 class DeclScanner extends TreeScanner { 615 JCTree result = null; 616 public void scan(JCTree tree) { 617 if (tree!=null && result==null) 618 tree.accept(this); 619 } 620 public void visitTopLevel(JCCompilationUnit that) { 621 if (that.packge == sym) result = that; 622 else super.visitTopLevel(that); 623 } 624 public void visitModuleDef(JCModuleDecl that) { 625 if (that.sym == sym) result = that; 626 // no need to scan within module declaration 627 } 628 public void visitPackageDef(JCPackageDecl that) { 629 if (that.packge == sym) result = that; 630 else super.visitPackageDef(that); 631 } 632 public void visitClassDef(JCClassDecl that) { 633 if (that.sym == sym) result = that; 634 else super.visitClassDef(that); 635 } 636 public void visitMethodDef(JCMethodDecl that) { 637 if (that.sym == sym) result = that; 638 else super.visitMethodDef(that); 639 } 640 public void visitVarDef(JCVariableDecl that) { 641 if (that.sym == sym) result = that; 642 else super.visitVarDef(that); 643 } 644 public void visitTypeParameter(JCTypeParameter that) { 645 if (that.type != null && that.type.tsym == sym) result = that; 646 else super.visitTypeParameter(that); 647 } 648 } 649 DeclScanner s = new DeclScanner(); 650 tree.accept(s); 651 return s.result; 652 } 653 654 public static Env<AttrContext> scopeFor(JCTree node, JCCompilationUnit unit) { 655 return scopeFor(pathFor(node, unit)); 656 } 657 658 public static Env<AttrContext> scopeFor(List<JCTree> path) { 659 // TODO: not implemented yet 660 throw new UnsupportedOperationException("not implemented yet"); 661 } 662 663 public static List<JCTree> pathFor(final JCTree node, final JCCompilationUnit unit) { 664 class Result extends Error { 665 static final long serialVersionUID = -5942088234594905625L; 666 List<JCTree> path; 667 Result(List<JCTree> path) { 668 this.path = path; 669 } 670 } 671 class PathFinder extends TreeScanner { 672 List<JCTree> path = List.nil(); 673 public void scan(JCTree tree) { 674 if (tree != null) { 675 path = path.prepend(tree); 676 if (tree == node) 677 throw new Result(path); 678 super.scan(tree); 679 path = path.tail; 680 } 681 } 682 } 683 try { 684 new PathFinder().scan(unit); 685 } catch (Result result) { 686 return result.path; 687 } 688 return List.nil(); 689 } 690 691 /** Return the statement referenced by a label. 692 * If the label refers to a loop or switch, return that switch 693 * otherwise return the labelled statement itself 694 */ 695 public static JCTree referencedStatement(JCLabeledStatement tree) { 696 JCTree t = tree; 697 do t = ((JCLabeledStatement) t).body; 698 while (t.hasTag(LABELLED)); 699 switch (t.getTag()) { 700 case DOLOOP: case WHILELOOP: case FORLOOP: case FOREACHLOOP: case SWITCH: 701 return t; 702 default: 703 return tree; 704 } 705 } 706 707 /** Skip parens and return the enclosed expression 708 */ 709 public static JCExpression skipParens(JCExpression tree) { 710 while (tree.hasTag(PARENS)) { 711 tree = ((JCParens) tree).expr; 712 } 713 return tree; 714 } 715 716 /** Skip parens and return the enclosed expression 717 */ 718 public static JCTree skipParens(JCTree tree) { 719 if (tree.hasTag(PARENS)) 720 return skipParens((JCParens)tree); 721 else 722 return tree; 723 } 724 725 /** Return the types of a list of trees. 726 */ 727 public static List<Type> types(List<? extends JCTree> trees) { 728 ListBuffer<Type> ts = new ListBuffer<>(); 729 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 730 ts.append(l.head.type); 731 return ts.toList(); 732 } 733 734 /** If this tree is an identifier or a field or a parameterized type, 735 * return its name, otherwise return null. 736 */ 737 public static Name name(JCTree tree) { 738 switch (tree.getTag()) { 739 case IDENT: 740 return ((JCIdent) tree).name; 741 case SELECT: 742 return ((JCFieldAccess) tree).name; 743 case TYPEAPPLY: 744 return name(((JCTypeApply) tree).clazz); 745 default: 746 return null; 747 } 748 } 749 750 /** If this tree is a qualified identifier, its return fully qualified name, 751 * otherwise return null. 752 */ 753 public static Name fullName(JCTree tree) { 754 tree = skipParens(tree); 755 switch (tree.getTag()) { 756 case IDENT: 757 return ((JCIdent) tree).name; 758 case SELECT: 759 Name sname = fullName(((JCFieldAccess) tree).selected); 760 return sname == null ? null : sname.append('.', name(tree)); 761 default: 762 return null; 763 } 764 } 765 766 public static Symbol symbolFor(JCTree node) { 767 Symbol sym = symbolForImpl(node); 768 769 return sym != null ? sym.baseSymbol() : null; 770 } 771 772 private static Symbol symbolForImpl(JCTree node) { 773 node = skipParens(node); 774 switch (node.getTag()) { 775 case TOPLEVEL: 776 JCCompilationUnit cut = (JCCompilationUnit) node; 777 JCModuleDecl moduleDecl = cut.getModuleDecl(); 778 if (isModuleInfo(cut) && moduleDecl != null) 779 return symbolFor(moduleDecl); 780 return cut.packge; 781 case MODULEDEF: 782 return ((JCModuleDecl) node).sym; 783 case PACKAGEDEF: 784 return ((JCPackageDecl) node).packge; 785 case CLASSDEF: 786 return ((JCClassDecl) node).sym; 787 case METHODDEF: 788 return ((JCMethodDecl) node).sym; 789 case VARDEF: 790 return ((JCVariableDecl) node).sym; 791 case IDENT: 792 return ((JCIdent) node).sym; 793 case SELECT: 794 return ((JCFieldAccess) node).sym; 795 case REFERENCE: 796 return ((JCMemberReference) node).sym; 797 case NEWCLASS: 798 return ((JCNewClass) node).constructor; 799 case APPLY: 800 return symbolFor(((JCMethodInvocation) node).meth); 801 case TYPEAPPLY: 802 return symbolFor(((JCTypeApply) node).clazz); 803 case ANNOTATION: 804 case TYPE_ANNOTATION: 805 case TYPEPARAMETER: 806 if (node.type != null) 807 return node.type.tsym; 808 return null; 809 default: 810 return null; 811 } 812 } 813 814 public static boolean isDeclaration(JCTree node) { 815 node = skipParens(node); 816 switch (node.getTag()) { 817 case PACKAGEDEF: 818 case CLASSDEF: 819 case METHODDEF: 820 case VARDEF: 821 return true; 822 default: 823 return false; 824 } 825 } 826 827 /** If this tree is an identifier or a field, return its symbol, 828 * otherwise return null. 829 */ 830 public static Symbol symbol(JCTree tree) { 831 tree = skipParens(tree); 832 switch (tree.getTag()) { 833 case IDENT: 834 return ((JCIdent) tree).sym; 835 case SELECT: 836 return ((JCFieldAccess) tree).sym; 837 case TYPEAPPLY: 838 return symbol(((JCTypeApply) tree).clazz); 839 case ANNOTATED_TYPE: 840 return symbol(((JCAnnotatedType) tree).underlyingType); 841 case REFERENCE: 842 return ((JCMemberReference) tree).sym; 843 default: 844 return null; 845 } 846 } 847 848 /** Return true if this is a nonstatic selection. */ 849 public static boolean nonstaticSelect(JCTree tree) { 850 tree = skipParens(tree); 851 if (!tree.hasTag(SELECT)) return false; 852 JCFieldAccess s = (JCFieldAccess) tree; 853 Symbol e = symbol(s.selected); 854 return e == null || (e.kind != PCK && e.kind != TYP); 855 } 856 857 /** If this tree is an identifier or a field, set its symbol, otherwise skip. 858 */ 859 public static void setSymbol(JCTree tree, Symbol sym) { 860 tree = skipParens(tree); 861 switch (tree.getTag()) { 862 case IDENT: 863 ((JCIdent) tree).sym = sym; break; 864 case SELECT: 865 ((JCFieldAccess) tree).sym = sym; break; 866 default: 867 } 868 } 869 870 /** If this tree is a declaration or a block, return its flags field, 871 * otherwise return 0. 872 */ 873 public static long flags(JCTree tree) { 874 switch (tree.getTag()) { 875 case VARDEF: 876 return ((JCVariableDecl) tree).mods.flags; 877 case METHODDEF: 878 return ((JCMethodDecl) tree).mods.flags; 879 case CLASSDEF: 880 return ((JCClassDecl) tree).mods.flags; 881 case BLOCK: 882 return ((JCBlock) tree).flags; 883 default: 884 return 0; 885 } 886 } 887 888 /** Return first (smallest) flag in `flags': 889 * pre: flags != 0 890 */ 891 public static long firstFlag(long flags) { 892 long flag = 1; 893 while ((flag & flags & ExtendedStandardFlags) == 0) 894 flag = flag << 1; 895 return flag; 896 } 897 898 /** Return flags as a string, separated by " ". 899 */ 900 public static String flagNames(long flags) { 901 return Flags.toString(flags & ExtendedStandardFlags).trim(); 902 } 903 904 /** Operator precedences values. 905 */ 906 public static final int 907 notExpression = -1, // not an expression 908 noPrec = 0, // no enclosing expression 909 assignPrec = 1, 910 assignopPrec = 2, 911 condPrec = 3, 912 orPrec = 4, 913 andPrec = 5, 914 bitorPrec = 6, 915 bitxorPrec = 7, 916 bitandPrec = 8, 917 eqPrec = 9, 918 ordPrec = 10, 919 shiftPrec = 11, 920 addPrec = 12, 921 mulPrec = 13, 922 prefixPrec = 14, 923 postfixPrec = 15, 924 precCount = 16; 925 926 927 /** Map operators to their precedence levels. 928 */ 929 public static int opPrec(JCTree.Tag op) { 930 switch(op) { 931 case POS: 932 case NEG: 933 case NOT: 934 case COMPL: 935 case PREINC: 936 case PREDEC: return prefixPrec; 937 case POSTINC: 938 case POSTDEC: 939 case NULLCHK: return postfixPrec; 940 case ASSIGN: return assignPrec; 941 case BITOR_ASG: 942 case BITXOR_ASG: 943 case BITAND_ASG: 944 case SL_ASG: 945 case SR_ASG: 946 case USR_ASG: 947 case PLUS_ASG: 948 case MINUS_ASG: 949 case MUL_ASG: 950 case DIV_ASG: 951 case MOD_ASG: return assignopPrec; 952 case OR: return orPrec; 953 case AND: return andPrec; 954 case EQ: 955 case NE: return eqPrec; 956 case LT: 957 case GT: 958 case LE: 959 case GE: return ordPrec; 960 case BITOR: return bitorPrec; 961 case BITXOR: return bitxorPrec; 962 case BITAND: return bitandPrec; 963 case SL: 964 case SR: 965 case USR: return shiftPrec; 966 case PLUS: 967 case MINUS: return addPrec; 968 case MUL: 969 case DIV: 970 case MOD: return mulPrec; 971 case TYPETEST: return ordPrec; 972 default: throw new AssertionError(); 973 } 974 } 975 976 static Tree.Kind tagToKind(JCTree.Tag tag) { 977 switch (tag) { 978 // Postfix expressions 979 case POSTINC: // _ ++ 980 return Tree.Kind.POSTFIX_INCREMENT; 981 case POSTDEC: // _ -- 982 return Tree.Kind.POSTFIX_DECREMENT; 983 984 // Unary operators 985 case PREINC: // ++ _ 986 return Tree.Kind.PREFIX_INCREMENT; 987 case PREDEC: // -- _ 988 return Tree.Kind.PREFIX_DECREMENT; 989 case POS: // + 990 return Tree.Kind.UNARY_PLUS; 991 case NEG: // - 992 return Tree.Kind.UNARY_MINUS; 993 case COMPL: // ~ 994 return Tree.Kind.BITWISE_COMPLEMENT; 995 case NOT: // ! 996 return Tree.Kind.LOGICAL_COMPLEMENT; 997 998 // Binary operators 999 1000 // Multiplicative operators 1001 case MUL: // * 1002 return Tree.Kind.MULTIPLY; 1003 case DIV: // / 1004 return Tree.Kind.DIVIDE; 1005 case MOD: // % 1006 return Tree.Kind.REMAINDER; 1007 1008 // Additive operators 1009 case PLUS: // + 1010 return Tree.Kind.PLUS; 1011 case MINUS: // - 1012 return Tree.Kind.MINUS; 1013 1014 // Shift operators 1015 case SL: // << 1016 return Tree.Kind.LEFT_SHIFT; 1017 case SR: // >> 1018 return Tree.Kind.RIGHT_SHIFT; 1019 case USR: // >>> 1020 return Tree.Kind.UNSIGNED_RIGHT_SHIFT; 1021 1022 // Relational operators 1023 case LT: // < 1024 return Tree.Kind.LESS_THAN; 1025 case GT: // > 1026 return Tree.Kind.GREATER_THAN; 1027 case LE: // <= 1028 return Tree.Kind.LESS_THAN_EQUAL; 1029 case GE: // >= 1030 return Tree.Kind.GREATER_THAN_EQUAL; 1031 1032 // Equality operators 1033 case EQ: // == 1034 return Tree.Kind.EQUAL_TO; 1035 case NE: // != 1036 return Tree.Kind.NOT_EQUAL_TO; 1037 1038 // Bitwise and logical operators 1039 case BITAND: // & 1040 return Tree.Kind.AND; 1041 case BITXOR: // ^ 1042 return Tree.Kind.XOR; 1043 case BITOR: // | 1044 return Tree.Kind.OR; 1045 1046 // Conditional operators 1047 case AND: // && 1048 return Tree.Kind.CONDITIONAL_AND; 1049 case OR: // || 1050 return Tree.Kind.CONDITIONAL_OR; 1051 1052 // Assignment operators 1053 case MUL_ASG: // *= 1054 return Tree.Kind.MULTIPLY_ASSIGNMENT; 1055 case DIV_ASG: // /= 1056 return Tree.Kind.DIVIDE_ASSIGNMENT; 1057 case MOD_ASG: // %= 1058 return Tree.Kind.REMAINDER_ASSIGNMENT; 1059 case PLUS_ASG: // += 1060 return Tree.Kind.PLUS_ASSIGNMENT; 1061 case MINUS_ASG: // -= 1062 return Tree.Kind.MINUS_ASSIGNMENT; 1063 case SL_ASG: // <<= 1064 return Tree.Kind.LEFT_SHIFT_ASSIGNMENT; 1065 case SR_ASG: // >>= 1066 return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT; 1067 case USR_ASG: // >>>= 1068 return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT; 1069 case BITAND_ASG: // &= 1070 return Tree.Kind.AND_ASSIGNMENT; 1071 case BITXOR_ASG: // ^= 1072 return Tree.Kind.XOR_ASSIGNMENT; 1073 case BITOR_ASG: // |= 1074 return Tree.Kind.OR_ASSIGNMENT; 1075 1076 // Null check (implementation detail), for example, __.getClass() 1077 case NULLCHK: 1078 return Tree.Kind.OTHER; 1079 1080 case ANNOTATION: 1081 return Tree.Kind.ANNOTATION; 1082 case TYPE_ANNOTATION: 1083 return Tree.Kind.TYPE_ANNOTATION; 1084 1085 case EXPORTS: 1086 return Tree.Kind.EXPORTS; 1087 case OPENS: 1088 return Tree.Kind.OPENS; 1089 1090 default: 1091 return null; 1092 } 1093 } 1094 1095 /** 1096 * Returns the underlying type of the tree if it is an annotated type, 1097 * or the tree itself otherwise. 1098 */ 1099 public static JCExpression typeIn(JCExpression tree) { 1100 switch (tree.getTag()) { 1101 case ANNOTATED_TYPE: 1102 return ((JCAnnotatedType)tree).underlyingType; 1103 case IDENT: /* simple names */ 1104 case TYPEIDENT: /* primitive name */ 1105 case SELECT: /* qualified name */ 1106 case TYPEARRAY: /* array types */ 1107 case WILDCARD: /* wild cards */ 1108 case TYPEPARAMETER: /* type parameters */ 1109 case TYPEAPPLY: /* parameterized types */ 1110 case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */ 1111 return tree; 1112 default: 1113 throw new AssertionError("Unexpected type tree: " + tree); 1114 } 1115 } 1116 1117 /* Return the inner-most type of a type tree. 1118 * For an array that contains an annotated type, return that annotated type. 1119 * TODO: currently only used by Pretty. Describe behavior better. 1120 */ 1121 public static JCTree innermostType(JCTree type) { 1122 JCTree lastAnnotatedType = null; 1123 JCTree cur = type; 1124 loop: while (true) { 1125 switch (cur.getTag()) { 1126 case TYPEARRAY: 1127 lastAnnotatedType = null; 1128 cur = ((JCArrayTypeTree)cur).elemtype; 1129 break; 1130 case WILDCARD: 1131 lastAnnotatedType = null; 1132 cur = ((JCWildcard)cur).inner; 1133 break; 1134 case ANNOTATED_TYPE: 1135 lastAnnotatedType = cur; 1136 cur = ((JCAnnotatedType)cur).underlyingType; 1137 break; 1138 default: 1139 break loop; 1140 } 1141 } 1142 if (lastAnnotatedType!=null) { 1143 return lastAnnotatedType; 1144 } else { 1145 return cur; 1146 } 1147 } 1148 1149 private static class TypeAnnotationFinder extends TreeScanner { 1150 public boolean foundTypeAnno = false; 1151 1152 @Override 1153 public void scan(JCTree tree) { 1154 if (foundTypeAnno || tree == null) 1155 return; 1156 super.scan(tree); 1157 } 1158 1159 public void visitAnnotation(JCAnnotation tree) { 1160 foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION); 1161 } 1162 } 1163 1164 public static boolean containsTypeAnnotation(JCTree e) { 1165 TypeAnnotationFinder finder = new TypeAnnotationFinder(); 1166 finder.scan(e); 1167 return finder.foundTypeAnno; 1168 } 1169 1170 public static boolean isModuleInfo(JCCompilationUnit tree) { 1171 return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE) 1172 && tree.getModuleDecl() != null; 1173 } 1174 1175 public static JCModuleDecl getModule(JCCompilationUnit t) { 1176 if (t.defs.nonEmpty()) { 1177 JCTree def = t.defs.head; 1178 if (def.hasTag(MODULEDEF)) 1179 return (JCModuleDecl) def; 1180 } 1181 return null; 1182 } 1183 1184 public static boolean isPackageInfo(JCCompilationUnit tree) { 1185 return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); 1186 } 1187} 1188