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