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