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