1 /* 2 * Copyright (c) 1999, 2025, 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.code.Symbol.RecordComponent; 34 import com.sun.tools.javac.comp.AttrContext; 35 import com.sun.tools.javac.comp.Env; 36 import com.sun.tools.javac.tree.JCTree.*; 37 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 38 import com.sun.tools.javac.util.*; 39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 40 41 import static com.sun.tools.javac.code.Flags.*; 42 import static com.sun.tools.javac.code.Kinds.Kind.*; 43 import com.sun.tools.javac.code.Symbol.VarSymbol; 44 import static com.sun.tools.javac.code.TypeTag.BOOLEAN; 45 import static com.sun.tools.javac.code.TypeTag.BOT; 46 import static com.sun.tools.javac.tree.JCTree.Tag.*; 47 import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK; 48 import static com.sun.tools.javac.tree.JCTree.Tag.SYNCHRONIZED; 49 50 import javax.lang.model.element.ElementKind; 51 import javax.tools.JavaFileObject; 52 53 import java.util.function.Function; 54 import java.util.function.Predicate; 55 import java.util.function.ToIntFunction; 56 57 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT; 58 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.RIGHT; 59 60 /** Utility class containing inspector methods for trees. 61 * 62 * <p><b>This is NOT part of any supported API. 63 * If you write code that depends on this, you do so at your own risk. 64 * This code and its internal interfaces are subject to change or 65 * deletion without notice.</b> 66 */ 67 public class TreeInfo { 68 69 public static List<JCExpression> args(JCTree t) { 70 switch (t.getTag()) { 71 case APPLY: 72 return ((JCMethodInvocation)t).args; 73 case NEWCLASS: 74 return ((JCNewClass)t).args; 75 default: 76 return null; 77 } 78 } 79 80 /** Is tree a constructor declaration? 81 */ 82 public static boolean isConstructor(JCTree tree) { 83 if (tree.hasTag(METHODDEF)) { 84 Name name = ((JCMethodDecl) tree).name; 85 return name == name.table.names.init; 86 } else { 87 return false; 88 } 89 } 90 91 public static boolean isCanonicalConstructor(JCTree tree) { 92 // the record flag is only set to the canonical constructor 93 return isConstructor(tree) && (((JCMethodDecl)tree).sym.flags_field & RECORD) != 0; 94 } 95 96 public static boolean isCompactConstructor(JCTree tree) { 97 // the record flag is only set to the canonical constructor 98 return isCanonicalConstructor(tree) && (((JCMethodDecl)tree).sym.flags_field & COMPACT_RECORD_CONSTRUCTOR) != 0; 99 } 100 101 public static boolean isReceiverParam(JCTree tree) { 102 if (tree.hasTag(VARDEF)) { 103 return ((JCVariableDecl)tree).nameexpr != null; 104 } else { 105 return false; 106 } 107 } 108 109 /** Is there a constructor declaration in the given list of trees? 110 */ 111 public static boolean hasConstructors(List<JCTree> trees) { 112 for (List<JCTree> l = trees; l.nonEmpty(); l = l.tail) 113 if (isConstructor(l.head)) return true; 114 return false; 115 } 116 117 public static boolean isMultiCatch(JCCatch catchClause) { 118 return catchClause.param.vartype.hasTag(TYPEUNION); 119 } 120 121 /** Is statement an initializer for a synthetic field? 122 */ 123 public static boolean isSyntheticInit(JCTree stat) { 124 if (stat.hasTag(EXEC)) { 125 JCExpressionStatement exec = (JCExpressionStatement)stat; 126 if (exec.expr.hasTag(ASSIGN)) { 127 JCAssign assign = (JCAssign)exec.expr; 128 if (assign.lhs.hasTag(SELECT)) { 129 JCFieldAccess select = (JCFieldAccess)assign.lhs; 130 if (select.sym != null && 131 (select.sym.flags() & SYNTHETIC) != 0) { 132 Name selected = name(select.selected); 133 if (selected != null && selected == selected.table.names._this) 134 return true; 135 } 136 } 137 } 138 } 139 return false; 140 } 141 142 /** If the expression is a method call, return the method name, null 143 * otherwise. */ 144 public static Name calledMethodName(JCTree tree) { 145 if (tree.hasTag(EXEC)) { 146 JCExpressionStatement exec = (JCExpressionStatement)tree; 147 if (exec.expr.hasTag(APPLY)) { 148 Name mname = TreeInfo.name(((JCMethodInvocation) exec.expr).meth); 149 return mname; 150 } 151 } 152 return null; 153 } 154 155 /** Is this tree a 'this' identifier? 156 */ 157 public static boolean isThisQualifier(JCTree tree) { 158 switch (tree.getTag()) { 159 case PARENS: 160 return isThisQualifier(skipParens(tree)); 161 case IDENT: { 162 JCIdent id = (JCIdent)tree; 163 return id.name == id.name.table.names._this; 164 } 165 default: 166 return false; 167 } 168 } 169 170 /** Is this tree an identifier, possibly qualified by 'this'? 171 */ 172 public static boolean isIdentOrThisDotIdent(JCTree tree) { 173 switch (tree.getTag()) { 174 case PARENS: 175 return isIdentOrThisDotIdent(skipParens(tree)); 176 case IDENT: 177 return true; 178 case SELECT: 179 return isThisQualifier(((JCFieldAccess)tree).selected); 180 default: 181 return false; 182 } 183 } 184 185 /** Check if the given tree is an explicit reference to the 'this' instance of the 186 * class currently being compiled. This is true if tree is: 187 * - An unqualified 'this' identifier 188 * - A 'super' identifier qualified by a class name whose type is 'currentClass' or a supertype 189 * - A 'this' identifier qualified by a class name whose type is 'currentClass' or a supertype 190 * but also NOT an enclosing outer class of 'currentClass'. 191 */ 192 public static boolean isExplicitThisReference(Types types, Type.ClassType currentClass, JCTree tree) { 193 switch (tree.getTag()) { 194 case PARENS: 195 return isExplicitThisReference(types, currentClass, skipParens(tree)); 196 case IDENT: { 197 JCIdent ident = (JCIdent)tree; 198 Names names = ident.name.table.names; 199 return ident.name == names._this || ident.name == names._super; 200 } 201 case SELECT: { 202 JCFieldAccess select = (JCFieldAccess)tree; 203 Type selectedType = types.erasure(select.selected.type); 204 if (!selectedType.hasTag(TypeTag.CLASS)) 205 return false; 206 Symbol.ClassSymbol currentClassSym = (Symbol.ClassSymbol)((Type.ClassType)types.erasure(currentClass)).tsym; 207 Symbol.ClassSymbol selectedClassSym = (Symbol.ClassSymbol)((Type.ClassType)selectedType).tsym; 208 Names names = select.name.table.names; 209 return currentClassSym.isSubClass(selectedClassSym, types) && 210 (select.name == names._super || 211 (select.name == names._this && 212 (currentClassSym == selectedClassSym || 213 !currentClassSym.isEnclosedBy(selectedClassSym)))); 214 } 215 default: 216 return false; 217 } 218 } 219 220 /** Is this a call to super? 221 */ 222 public static boolean isSuperCall(JCTree tree) { 223 Name name = calledMethodName(tree); 224 if (name != null) { 225 Names names = name.table.names; 226 return name==names._super; 227 } else { 228 return false; 229 } 230 } 231 232 public static List<JCVariableDecl> recordFields(JCClassDecl tree) { 233 return tree.defs.stream() 234 .filter(t -> t.hasTag(VARDEF)) 235 .map(t -> (JCVariableDecl)t) 236 .filter(vd -> (vd.getModifiers().flags & (Flags.RECORD)) == RECORD) 237 .collect(List.collector()); 238 } 239 240 public static List<Type> recordFieldTypes(JCClassDecl tree) { 241 return recordFields(tree).stream() 242 .map(vd -> vd.type) 243 .collect(List.collector()); 244 } 245 246 /** Is the given method a constructor containing a super() or this() call? 247 */ 248 public static boolean hasAnyConstructorCall(JCMethodDecl tree) { 249 return hasConstructorCall(tree, null); 250 } 251 252 /** Is the given method a constructor containing a super() and/or this() call? 253 * The "target" is either names._this, names._super, or null for either/both. 254 */ 255 public static boolean hasConstructorCall(JCMethodDecl tree, Name target) { 256 JCMethodInvocation app = findConstructorCall(tree); 257 return app != null && (target == null || target == name(app.meth)); 258 } 259 260 /** Find the first super() or init() call in the given constructor. 261 */ 262 public static JCMethodInvocation findConstructorCall(JCMethodDecl md) { 263 if (!TreeInfo.isConstructor(md) || md.body == null) 264 return null; 265 return new ConstructorCallFinder(md.name.table.names).find(md).head; 266 } 267 268 /** Finds all calls to this() and/or super() in a given constructor. 269 * We can't assume they will be "top level" statements, because 270 * some synthetic calls to super() are added inside { } blocks. 271 * So we must recurse through the method's entire syntax tree. 272 */ 273 private static class ConstructorCallFinder extends TreeScanner { 274 275 final ListBuffer<JCMethodInvocation> calls = new ListBuffer<>(); 276 final Names names; 277 278 ConstructorCallFinder(Names names) { 279 this.names = names; 280 } 281 282 List<JCMethodInvocation> find(JCMethodDecl meth) { 283 scan(meth); 284 return calls.toList(); 285 } 286 287 @Override 288 public void visitApply(JCMethodInvocation invoke) { 289 Name name = TreeInfo.name(invoke.meth); 290 if ((name == names._this || name == names._super)) 291 calls.append(invoke); 292 super.visitApply(invoke); 293 } 294 295 @Override 296 public void visitClassDef(JCClassDecl tree) { 297 // don't descend any further 298 } 299 300 @Override 301 public void visitLambda(JCLambda tree) { 302 // don't descend any further 303 } 304 } 305 306 /** 307 * Is the given method invocation an invocation of this(...) or super(...)? 308 */ 309 public static boolean isConstructorCall(JCMethodInvocation invoke) { 310 Name name = TreeInfo.name(invoke.meth); 311 Names names = name.table.names; 312 313 return (name == names._this || name == names._super); 314 } 315 316 /** Finds super() invocations and translates them using the given mapping. 317 */ 318 public static void mapSuperCalls(JCBlock block, Function<? super JCExpressionStatement, ? extends JCStatement> mapper) { 319 block.stats = block.stats.map(new TreeInfo.SuperCallTranslator(mapper)::translate); 320 } 321 322 /** Finds all super() invocations and translates them somehow. 323 */ 324 private static class SuperCallTranslator extends TreeTranslator { 325 326 final Function<? super JCExpressionStatement, ? extends JCStatement> translator; 327 328 /** Constructor. 329 * 330 * @param translator translates super() invocations, returning replacement statement or null for no change 331 */ 332 SuperCallTranslator(Function<? super JCExpressionStatement, ? extends JCStatement> translator) { 333 this.translator = translator; 334 } 335 336 // Because it returns void, anywhere super() can legally appear must be a location where a JCStatement 337 // could also appear, so it's OK that we are replacing a JCExpressionStatement with a JCStatement here. 338 @Override 339 public void visitExec(JCExpressionStatement stat) { 340 if (!TreeInfo.isSuperCall(stat) || (result = this.translator.apply(stat)) == null) 341 super.visitExec(stat); 342 } 343 344 @Override 345 public void visitClassDef(JCClassDecl tree) { 346 // don't descend any further 347 result = tree; 348 } 349 350 @Override 351 public void visitLambda(JCLambda tree) { 352 // don't descend any further 353 result = tree; 354 } 355 } 356 357 /** Return true if a tree represents a diamond new expr. */ 358 public static boolean isDiamond(JCTree tree) { 359 switch(tree.getTag()) { 360 case TYPEAPPLY: return ((JCTypeApply)tree).getTypeArguments().isEmpty(); 361 case NEWCLASS: return isDiamond(((JCNewClass)tree).clazz); 362 case ANNOTATED_TYPE: return isDiamond(((JCAnnotatedType)tree).underlyingType); 363 default: return false; 364 } 365 } 366 367 public static boolean isEnumInit(JCTree tree) { 368 switch (tree.getTag()) { 369 case VARDEF: 370 return (((JCVariableDecl)tree).mods.flags & ENUM) != 0; 371 default: 372 return false; 373 } 374 } 375 376 /** set 'polyKind' on given tree */ 377 public static void setPolyKind(JCTree tree, PolyKind pkind) { 378 switch (tree.getTag()) { 379 case APPLY: 380 ((JCMethodInvocation)tree).polyKind = pkind; 381 break; 382 case NEWCLASS: 383 ((JCNewClass)tree).polyKind = pkind; 384 break; 385 case REFERENCE: 386 ((JCMemberReference)tree).refPolyKind = pkind; 387 break; 388 default: 389 throw new AssertionError("Unexpected tree: " + tree); 390 } 391 } 392 393 /** set 'varargsElement' on given tree */ 394 public static void setVarargsElement(JCTree tree, Type varargsElement) { 395 switch (tree.getTag()) { 396 case APPLY: 397 ((JCMethodInvocation)tree).varargsElement = varargsElement; 398 break; 399 case NEWCLASS: 400 ((JCNewClass)tree).varargsElement = varargsElement; 401 break; 402 case REFERENCE: 403 ((JCMemberReference)tree).varargsElement = varargsElement; 404 break; 405 default: 406 throw new AssertionError("Unexpected tree: " + tree); 407 } 408 } 409 410 /** Return true if the tree corresponds to an expression statement */ 411 public static boolean isExpressionStatement(JCExpression tree) { 412 switch(tree.getTag()) { 413 case PREINC: case PREDEC: 414 case POSTINC: case POSTDEC: 415 case ASSIGN: 416 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: 417 case SL_ASG: case SR_ASG: case USR_ASG: 418 case PLUS_ASG: case MINUS_ASG: 419 case MUL_ASG: case DIV_ASG: case MOD_ASG: 420 case APPLY: case NEWCLASS: 421 case ERRONEOUS: 422 return true; 423 default: 424 return false; 425 } 426 } 427 428 /** Return true if the tree corresponds to a statement */ 429 public static boolean isStatement(JCTree tree) { 430 return (tree instanceof JCStatement) && 431 !tree.hasTag(CLASSDEF) && 432 !tree.hasTag(Tag.BLOCK) && 433 !tree.hasTag(METHODDEF); 434 } 435 436 /** 437 * Return true if the AST corresponds to a static select of the kind A.B 438 */ 439 public static boolean isStaticSelector(JCTree base, Names names) { 440 if (base == null) 441 return false; 442 switch (base.getTag()) { 443 case IDENT: 444 JCIdent id = (JCIdent)base; 445 return id.name != names._this && 446 id.name != names._super && 447 isStaticSym(base); 448 case SELECT: 449 return isStaticSym(base) && 450 isStaticSelector(((JCFieldAccess)base).selected, names); 451 case TYPEAPPLY: 452 case TYPEARRAY: 453 return true; 454 case ANNOTATED_TYPE: 455 return isStaticSelector(((JCAnnotatedType)base).underlyingType, names); 456 default: 457 return false; 458 } 459 } 460 //where 461 private static boolean isStaticSym(JCTree tree) { 462 Symbol sym = symbol(tree); 463 return (sym.kind == TYP || sym.kind == PCK); 464 } 465 466 /** Return true if a tree represents the null literal. */ 467 public static boolean isNull(JCTree tree) { 468 if (!tree.hasTag(LITERAL)) 469 return false; 470 JCLiteral lit = (JCLiteral) tree; 471 return (lit.typetag == BOT); 472 } 473 474 /** Return true iff this tree is a child of some annotation. */ 475 public static boolean isInAnnotation(Env<?> env, JCTree tree) { 476 TreePath tp = TreePath.getPath(env.toplevel, tree); 477 if (tp != null) { 478 for (Tree t : tp) { 479 if (t.getKind() == Tree.Kind.ANNOTATION) 480 return true; 481 } 482 } 483 return false; 484 } 485 486 public static String getCommentText(Env<?> env, JCTree tree) { 487 DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL)) 488 ? ((JCCompilationUnit) tree).docComments 489 : env.toplevel.docComments; 490 return (docComments == null) ? null : docComments.getCommentText(tree); 491 } 492 493 /** The position of the first statement in a block, or the position of 494 * the block itself if it is empty. 495 */ 496 public static int firstStatPos(JCTree tree) { 497 if (tree.hasTag(BLOCK) && ((JCBlock) tree).stats.nonEmpty()) 498 return ((JCBlock) tree).stats.head.pos; 499 else 500 return tree.pos; 501 } 502 503 /** The closing brace position of given tree, if it is a block with 504 * defined bracePos. 505 */ 506 public static int endPos(JCTree tree) { 507 if (tree.hasTag(BLOCK) && ((JCBlock) tree).bracePos != Position.NOPOS) 508 return ((JCBlock) tree).bracePos; 509 else if (tree.hasTag(SYNCHRONIZED)) 510 return endPos(((JCSynchronized) tree).body); 511 else if (tree.hasTag(TRY)) { 512 JCTry t = (JCTry) tree; 513 return endPos((t.finalizer != null) ? t.finalizer 514 : (t.catchers.nonEmpty() ? t.catchers.last().body : t.body)); 515 } else if (tree.hasTag(SWITCH) && 516 ((JCSwitch) tree).bracePos != Position.NOPOS) { 517 return ((JCSwitch) tree).bracePos; 518 } else if (tree.hasTag(SWITCH_EXPRESSION) && 519 ((JCSwitchExpression) tree).bracePos != Position.NOPOS) { 520 return ((JCSwitchExpression) tree).bracePos; 521 } else 522 return tree.pos; 523 } 524 525 526 /** Get the start position for a tree node. The start position is 527 * defined to be the position of the first character of the first 528 * token of the node's source text. 529 * @param tree The tree node 530 */ 531 public static int getStartPos(JCTree tree) { 532 if (tree == null) 533 return Position.NOPOS; 534 535 switch(tree.getTag()) { 536 case MODULEDEF: { 537 JCModuleDecl md = (JCModuleDecl)tree; 538 return md.mods.annotations.isEmpty() ? md.pos : 539 md.mods.annotations.head.pos; 540 } 541 case PACKAGEDEF: { 542 JCPackageDecl pd = (JCPackageDecl)tree; 543 return pd.annotations.isEmpty() ? pd.pos : 544 pd.annotations.head.pos; 545 } 546 case APPLY: 547 return getStartPos(((JCMethodInvocation) tree).meth); 548 case ASSIGN: 549 return getStartPos(((JCAssign) tree).lhs); 550 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: 551 case SL_ASG: case SR_ASG: case USR_ASG: 552 case PLUS_ASG: case MINUS_ASG: case MUL_ASG: 553 case DIV_ASG: case MOD_ASG: 554 case OR: case AND: case BITOR: 555 case BITXOR: case BITAND: case EQ: 556 case NE: case LT: case GT: 557 case LE: case GE: case SL: 558 case SR: case USR: case PLUS: 559 case MINUS: case MUL: case DIV: 560 case MOD: 561 case POSTINC: 562 case POSTDEC: 563 return getStartPos(((JCOperatorExpression) tree).getOperand(LEFT)); 564 case CLASSDEF: { 565 JCClassDecl node = (JCClassDecl)tree; 566 if (node.mods.pos != Position.NOPOS) 567 return node.mods.pos; 568 break; 569 } 570 case CONDEXPR: 571 return getStartPos(((JCConditional) tree).cond); 572 case EXEC: 573 return getStartPos(((JCExpressionStatement) tree).expr); 574 case INDEXED: 575 return getStartPos(((JCArrayAccess) tree).indexed); 576 case METHODDEF: { 577 JCMethodDecl node = (JCMethodDecl)tree; 578 if (node.mods.pos != Position.NOPOS) 579 return node.mods.pos; 580 if (node.typarams.nonEmpty()) // List.nil() used for no typarams 581 return getStartPos(node.typarams.head); 582 return node.restype == null ? node.pos : getStartPos(node.restype); 583 } 584 case SELECT: 585 return getStartPos(((JCFieldAccess) tree).selected); 586 case TYPEAPPLY: 587 return getStartPos(((JCTypeApply) tree).clazz); 588 case TYPEARRAY: 589 return getStartPos(((JCArrayTypeTree) tree).elemtype); 590 case TYPETEST: 591 return getStartPos(((JCInstanceOf) tree).expr); 592 case ANNOTATED_TYPE: { 593 JCAnnotatedType node = (JCAnnotatedType) tree; 594 if (node.annotations.nonEmpty()) { 595 if (node.underlyingType.hasTag(TYPEARRAY) || 596 node.underlyingType.hasTag(SELECT)) { 597 return getStartPos(node.underlyingType); 598 } else { 599 return getStartPos(node.annotations.head); 600 } 601 } else { 602 return getStartPos(node.underlyingType); 603 } 604 } 605 case NEWCLASS: { 606 JCNewClass node = (JCNewClass)tree; 607 if (node.encl != null) 608 return getStartPos(node.encl); 609 break; 610 } 611 case VARDEF: { 612 JCVariableDecl node = (JCVariableDecl)tree; 613 if (node.startPos != Position.NOPOS) { 614 return node.startPos; 615 } else if (node.mods.pos != Position.NOPOS) { 616 return node.mods.pos; 617 } else if (node.vartype == null || node.vartype.pos == Position.NOPOS) { 618 //if there's no type (partially typed lambda parameter) 619 //simply return node position 620 return node.pos; 621 } else { 622 return getStartPos(node.vartype); 623 } 624 } 625 case BINDINGPATTERN: { 626 JCBindingPattern node = (JCBindingPattern)tree; 627 return getStartPos(node.var); 628 } 629 case ERRONEOUS: { 630 JCErroneous node = (JCErroneous)tree; 631 if (node.errs != null && node.errs.nonEmpty()) { 632 int pos = getStartPos(node.errs.head); 633 if (pos != Position.NOPOS) { 634 return pos; 635 } 636 } 637 break; 638 } 639 } 640 return tree.pos; 641 } 642 643 /** The end position of given tree, given a table of end positions generated by the parser 644 */ 645 public static int getEndPos(JCTree tree, EndPosTable endPosTable) { 646 if (tree == null) 647 return Position.NOPOS; 648 649 int mapPos = endPosTable.getEndPos(tree); 650 if (mapPos != Position.NOPOS) 651 return mapPos; 652 653 switch(tree.getTag()) { 654 case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: 655 case SL_ASG: case SR_ASG: case USR_ASG: 656 case PLUS_ASG: case MINUS_ASG: case MUL_ASG: 657 case DIV_ASG: case MOD_ASG: 658 case OR: case AND: case BITOR: 659 case BITXOR: case BITAND: case EQ: 660 case NE: case LT: case GT: 661 case LE: case GE: case SL: 662 case SR: case USR: case PLUS: 663 case MINUS: case MUL: case DIV: 664 case MOD: 665 case POS: 666 case NEG: 667 case NOT: 668 case COMPL: 669 case PREINC: 670 case PREDEC: 671 return getEndPos(((JCOperatorExpression) tree).getOperand(RIGHT), endPosTable); 672 case CASE: 673 return getEndPos(((JCCase) tree).stats.last(), endPosTable); 674 case CATCH: 675 return getEndPos(((JCCatch) tree).body, endPosTable); 676 case CONDEXPR: 677 return getEndPos(((JCConditional) tree).falsepart, endPosTable); 678 case FORLOOP: 679 return getEndPos(((JCForLoop) tree).body, endPosTable); 680 case FOREACHLOOP: 681 return getEndPos(((JCEnhancedForLoop) tree).body, endPosTable); 682 case IF: { 683 JCIf node = (JCIf)tree; 684 if (node.elsepart == null) { 685 return getEndPos(node.thenpart, endPosTable); 686 } else { 687 return getEndPos(node.elsepart, endPosTable); 688 } 689 } 690 case LABELLED: 691 return getEndPos(((JCLabeledStatement) tree).body, endPosTable); 692 case MODIFIERS: 693 return getEndPos(((JCModifiers) tree).annotations.last(), endPosTable); 694 case SYNCHRONIZED: 695 return getEndPos(((JCSynchronized) tree).body, endPosTable); 696 case TOPLEVEL: 697 return getEndPos(((JCCompilationUnit) tree).defs.last(), endPosTable); 698 case TRY: { 699 JCTry node = (JCTry)tree; 700 if (node.finalizer != null) { 701 return getEndPos(node.finalizer, endPosTable); 702 } else if (!node.catchers.isEmpty()) { 703 return getEndPos(node.catchers.last(), endPosTable); 704 } else { 705 return getEndPos(node.body, endPosTable); 706 } 707 } 708 case WILDCARD: 709 return getEndPos(((JCWildcard) tree).inner, endPosTable); 710 case TYPECAST: 711 return getEndPos(((JCTypeCast) tree).expr, endPosTable); 712 case TYPETEST: 713 return getEndPos(((JCInstanceOf) tree).pattern, endPosTable); 714 case WHILELOOP: 715 return getEndPos(((JCWhileLoop) tree).body, endPosTable); 716 case ANNOTATED_TYPE: 717 return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable); 718 case ERRONEOUS: { 719 JCErroneous node = (JCErroneous)tree; 720 if (node.errs != null && node.errs.nonEmpty()) 721 return getEndPos(node.errs.last(), endPosTable); 722 } 723 } 724 return Position.NOPOS; 725 } 726 727 728 /** A DiagnosticPosition with the preferred position set to the 729 * closing brace position of given tree, if it is a block with 730 * defined closing brace position. 731 */ 732 public static DiagnosticPosition diagEndPos(final JCTree tree) { 733 final int endPos = TreeInfo.endPos(tree); 734 return new DiagnosticPosition() { 735 public JCTree getTree() { return tree; } 736 public int getStartPosition() { return TreeInfo.getStartPos(tree); } 737 public int getPreferredPosition() { return endPos; } 738 public int getEndPosition(EndPosTable endPosTable) { 739 return TreeInfo.getEndPos(tree, endPosTable); 740 } 741 }; 742 } 743 744 public enum PosKind { 745 START_POS(TreeInfo::getStartPos), 746 FIRST_STAT_POS(TreeInfo::firstStatPos), 747 END_POS(TreeInfo::endPos); 748 749 final ToIntFunction<JCTree> posFunc; 750 751 PosKind(ToIntFunction<JCTree> posFunc) { 752 this.posFunc = posFunc; 753 } 754 755 int toPos(JCTree tree) { 756 return posFunc.applyAsInt(tree); 757 } 758 } 759 760 /** The position of the finalizer of given try/synchronized statement. 761 */ 762 public static int finalizerPos(JCTree tree, PosKind posKind) { 763 if (tree.hasTag(TRY)) { 764 JCTry t = (JCTry) tree; 765 Assert.checkNonNull(t.finalizer); 766 return posKind.toPos(t.finalizer); 767 } else if (tree.hasTag(SYNCHRONIZED)) { 768 return endPos(((JCSynchronized) tree).body); 769 } else { 770 throw new AssertionError(); 771 } 772 } 773 774 /** Find the position for reporting an error about a symbol, where 775 * that symbol is defined somewhere in the given tree. */ 776 public static int positionFor(final Symbol sym, final JCTree tree) { 777 JCTree decl = declarationFor(sym, tree); 778 return ((decl != null) ? decl : tree).pos; 779 } 780 781 /** Find the position for reporting an error about a symbol, where 782 * that symbol is defined somewhere in the given tree. */ 783 public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) { 784 return diagnosticPositionFor(sym, tree, false); 785 } 786 787 public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree, boolean returnNullIfNotFound) { 788 return diagnosticPositionFor(sym, tree, returnNullIfNotFound, null); 789 } 790 791 public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree, boolean returnNullIfNotFound, 792 Predicate<? super JCTree> filter) { 793 class DiagScanner extends DeclScanner { 794 DiagScanner(Symbol sym, Predicate<? super JCTree> filter) { 795 super(sym, filter); 796 } 797 798 public void visitIdent(JCIdent that) { 799 if (!checkMatch(that, that.sym)) 800 super.visitIdent(that); 801 } 802 public void visitSelect(JCFieldAccess that) { 803 if (!checkMatch(that, that.sym)) 804 super.visitSelect(that); 805 } 806 } 807 DiagScanner s = new DiagScanner(sym, filter); 808 tree.accept(s); 809 JCTree decl = s.result; 810 if (decl == null && returnNullIfNotFound) { return null; } 811 return ((decl != null) ? decl : tree).pos(); 812 } 813 814 public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final List<? extends JCTree> trees) { 815 return trees.stream().map(t -> TreeInfo.diagnosticPositionFor(sym, t)).filter(t -> t != null).findFirst().get(); 816 } 817 818 private static class DeclScanner extends TreeScanner { 819 final Symbol sym; 820 final Predicate<? super JCTree> filter; 821 822 DeclScanner(final Symbol sym) { 823 this(sym, null); 824 } 825 DeclScanner(final Symbol sym, Predicate<? super JCTree> filter) { 826 this.sym = sym; 827 this.filter = filter; 828 } 829 830 JCTree result = null; 831 public void scan(JCTree tree) { 832 if (tree!=null && result==null) 833 tree.accept(this); 834 } 835 public void visitTopLevel(JCCompilationUnit that) { 836 if (!checkMatch(that, that.packge)) 837 super.visitTopLevel(that); 838 } 839 public void visitModuleDef(JCModuleDecl that) { 840 checkMatch(that, that.sym); 841 // no need to scan within module declaration 842 } 843 public void visitPackageDef(JCPackageDecl that) { 844 if (!checkMatch(that, that.packge)) 845 super.visitPackageDef(that); 846 } 847 public void visitClassDef(JCClassDecl that) { 848 if (!checkMatch(that, that.sym)) 849 super.visitClassDef(that); 850 } 851 public void visitMethodDef(JCMethodDecl that) { 852 if (!checkMatch(that, that.sym)) 853 super.visitMethodDef(that); 854 } 855 public void visitVarDef(JCVariableDecl that) { 856 if (!checkMatch(that, that.sym)) 857 super.visitVarDef(that); 858 } 859 public void visitTypeParameter(JCTypeParameter that) { 860 if (that.type == null || !checkMatch(that, that.type.tsym)) 861 super.visitTypeParameter(that); 862 } 863 864 protected boolean checkMatch(JCTree that, Symbol thatSym) { 865 if (thatSym == this.sym && (filter == null || filter.test(that))) { 866 result = that; 867 return true; 868 } 869 if (this.sym.getKind() == ElementKind.RECORD_COMPONENT) { 870 if (thatSym != null && thatSym.getKind() == ElementKind.FIELD && (thatSym.flags_field & RECORD) != 0) { 871 RecordComponent rc = thatSym.enclClass().getRecordComponent((VarSymbol)thatSym); 872 return checkMatch(rc.declarationFor(), rc); 873 } 874 } 875 return false; 876 } 877 } 878 879 /** Find the declaration for a symbol, where 880 * that symbol is defined somewhere in the given tree. */ 881 public static JCTree declarationFor(final Symbol sym, final JCTree tree) { 882 DeclScanner s = new DeclScanner(sym); 883 tree.accept(s); 884 return s.result; 885 } 886 887 /** Return the statement referenced by a label. 888 * If the label refers to a loop or switch, return that switch 889 * otherwise return the labelled statement itself 890 */ 891 public static JCTree referencedStatement(JCLabeledStatement tree) { 892 JCTree t = tree; 893 do t = ((JCLabeledStatement) t).body; 894 while (t.hasTag(LABELLED)); 895 switch (t.getTag()) { 896 case DOLOOP: case WHILELOOP: case FORLOOP: case FOREACHLOOP: case SWITCH: 897 return t; 898 default: 899 return tree; 900 } 901 } 902 903 /** Skip parens and return the enclosed expression 904 */ 905 public static JCExpression skipParens(JCExpression tree) { 906 while (tree.hasTag(PARENS)) { 907 tree = ((JCParens) tree).expr; 908 } 909 return tree; 910 } 911 912 /** Skip parens and return the enclosed expression 913 */ 914 public static JCTree skipParens(JCTree tree) { 915 if (tree.hasTag(PARENS)) 916 return skipParens((JCParens)tree); 917 else 918 return tree; 919 } 920 921 /** Return the types of a list of trees. 922 */ 923 public static List<Type> types(List<? extends JCTree> trees) { 924 ListBuffer<Type> ts = new ListBuffer<>(); 925 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 926 ts.append(l.head.type); 927 return ts.toList(); 928 } 929 930 /** If this tree is an identifier or a field or a parameterized type, 931 * return its name, otherwise return null. 932 */ 933 public static Name name(JCTree tree) { 934 switch (tree.getTag()) { 935 case IDENT: 936 return ((JCIdent) tree).name; 937 case SELECT: 938 return ((JCFieldAccess) tree).name; 939 case TYPEAPPLY: 940 return name(((JCTypeApply) tree).clazz); 941 default: 942 return null; 943 } 944 } 945 946 /** If this tree is a qualified identifier, its return fully qualified name, 947 * otherwise return null. 948 */ 949 public static Name fullName(JCTree tree) { 950 tree = skipParens(tree); 951 switch (tree.getTag()) { 952 case IDENT: 953 return ((JCIdent) tree).name; 954 case SELECT: 955 Name sname = fullName(((JCFieldAccess) tree).selected); 956 return sname == null ? null : sname.append('.', name(tree)); 957 default: 958 return null; 959 } 960 } 961 962 public static Symbol symbolFor(JCTree node) { 963 Symbol sym = symbolForImpl(node); 964 965 return sym != null ? sym.baseSymbol() : null; 966 } 967 968 private static Symbol symbolForImpl(JCTree node) { 969 node = skipParens(node); 970 switch (node.getTag()) { 971 case TOPLEVEL: 972 JCCompilationUnit cut = (JCCompilationUnit) node; 973 JCModuleDecl moduleDecl = cut.getModuleDecl(); 974 if (isModuleInfo(cut) && moduleDecl != null) 975 return symbolFor(moduleDecl); 976 return cut.packge; 977 case MODULEDEF: 978 return ((JCModuleDecl) node).sym; 979 case PACKAGEDEF: 980 return ((JCPackageDecl) node).packge; 981 case CLASSDEF: 982 return ((JCClassDecl) node).sym; 983 case METHODDEF: 984 return ((JCMethodDecl) node).sym; 985 case VARDEF: 986 return ((JCVariableDecl) node).sym; 987 case IDENT: 988 return ((JCIdent) node).sym; 989 case SELECT: 990 return ((JCFieldAccess) node).sym; 991 case REFERENCE: 992 return ((JCMemberReference) node).sym; 993 case NEWCLASS: 994 return ((JCNewClass) node).constructor; 995 case APPLY: 996 return symbolFor(((JCMethodInvocation) node).meth); 997 case TYPEAPPLY: 998 return symbolFor(((JCTypeApply) node).clazz); 999 case ANNOTATION: 1000 case TYPE_ANNOTATION: 1001 case TYPEPARAMETER: 1002 if (node.type != null) 1003 return node.type.tsym; 1004 return null; 1005 default: 1006 return null; 1007 } 1008 } 1009 1010 public static boolean isDeclaration(JCTree node) { 1011 node = skipParens(node); 1012 switch (node.getTag()) { 1013 case PACKAGEDEF: 1014 case CLASSDEF: 1015 case METHODDEF: 1016 case VARDEF: 1017 return true; 1018 default: 1019 return false; 1020 } 1021 } 1022 1023 /** If this tree is an identifier or a field, return its symbol, 1024 * otherwise return null. 1025 */ 1026 public static Symbol symbol(JCTree tree) { 1027 tree = skipParens(tree); 1028 switch (tree.getTag()) { 1029 case IDENT: 1030 return ((JCIdent) tree).sym; 1031 case SELECT: 1032 return ((JCFieldAccess) tree).sym; 1033 case TYPEAPPLY: 1034 return symbol(((JCTypeApply) tree).clazz); 1035 case ANNOTATED_TYPE: 1036 return symbol(((JCAnnotatedType) tree).underlyingType); 1037 case REFERENCE: 1038 return ((JCMemberReference) tree).sym; 1039 case CLASSDEF: 1040 return ((JCClassDecl) tree).sym; 1041 default: 1042 return null; 1043 } 1044 } 1045 1046 /** If this tree has a modifiers field, return it otherwise return null 1047 */ 1048 public static JCModifiers getModifiers(JCTree tree) { 1049 tree = skipParens(tree); 1050 switch (tree.getTag()) { 1051 case VARDEF: 1052 return ((JCVariableDecl) tree).mods; 1053 case METHODDEF: 1054 return ((JCMethodDecl) tree).mods; 1055 case CLASSDEF: 1056 return ((JCClassDecl) tree).mods; 1057 case MODULEDEF: 1058 return ((JCModuleDecl) tree).mods; 1059 default: 1060 return null; 1061 } 1062 } 1063 1064 /** Return true if this is a nonstatic selection. */ 1065 public static boolean nonstaticSelect(JCTree tree) { 1066 tree = skipParens(tree); 1067 if (!tree.hasTag(SELECT)) return false; 1068 JCFieldAccess s = (JCFieldAccess) tree; 1069 Symbol e = symbol(s.selected); 1070 return e == null || (e.kind != PCK && e.kind != TYP); 1071 } 1072 1073 /** If this tree is an identifier or a field, set its symbol, otherwise skip. 1074 */ 1075 public static void setSymbol(JCTree tree, Symbol sym) { 1076 tree = skipParens(tree); 1077 switch (tree.getTag()) { 1078 case IDENT: 1079 ((JCIdent) tree).sym = sym; break; 1080 case SELECT: 1081 ((JCFieldAccess) tree).sym = sym; break; 1082 default: 1083 } 1084 } 1085 1086 /** If this tree is a declaration or a block, return its flags field, 1087 * otherwise return 0. 1088 */ 1089 public static long flags(JCTree tree) { 1090 switch (tree.getTag()) { 1091 case VARDEF: 1092 return ((JCVariableDecl) tree).mods.flags; 1093 case METHODDEF: 1094 return ((JCMethodDecl) tree).mods.flags; 1095 case CLASSDEF: 1096 return ((JCClassDecl) tree).mods.flags; 1097 case BLOCK: 1098 return ((JCBlock) tree).flags; 1099 default: 1100 return 0; 1101 } 1102 } 1103 1104 /** Return first (smallest) flag in `flags': 1105 * pre: flags != 0 1106 */ 1107 public static long firstFlag(long flags) { 1108 long flag = 1; 1109 while ((flag & flags) == 0) 1110 flag = flag << 1; 1111 return flag; 1112 } 1113 1114 /** Return flags as a string, separated by " ". 1115 */ 1116 public static String flagNames(long flags) { 1117 return Flags.toString(flags & ExtendedStandardFlags).trim(); 1118 } 1119 1120 /** Operator precedences values. 1121 */ 1122 public static final int 1123 notExpression = -1, // not an expression 1124 noPrec = 0, // no enclosing expression 1125 assignPrec = 1, 1126 assignopPrec = 2, 1127 condPrec = 3, 1128 orPrec = 4, 1129 andPrec = 5, 1130 bitorPrec = 6, 1131 bitxorPrec = 7, 1132 bitandPrec = 8, 1133 eqPrec = 9, 1134 ordPrec = 10, 1135 shiftPrec = 11, 1136 addPrec = 12, 1137 mulPrec = 13, 1138 prefixPrec = 14, 1139 postfixPrec = 15, 1140 precCount = 16; 1141 1142 1143 /** Map operators to their precedence levels. 1144 */ 1145 public static int opPrec(JCTree.Tag op) { 1146 switch(op) { 1147 case POS: 1148 case NEG: 1149 case NOT: 1150 case COMPL: 1151 case PREINC: 1152 case PREDEC: return prefixPrec; 1153 case POSTINC: 1154 case POSTDEC: 1155 case NULLCHK: return postfixPrec; 1156 case ASSIGN: return assignPrec; 1157 case BITOR_ASG: 1158 case BITXOR_ASG: 1159 case BITAND_ASG: 1160 case SL_ASG: 1161 case SR_ASG: 1162 case USR_ASG: 1163 case PLUS_ASG: 1164 case MINUS_ASG: 1165 case MUL_ASG: 1166 case DIV_ASG: 1167 case MOD_ASG: return assignopPrec; 1168 case OR: return orPrec; 1169 case AND: return andPrec; 1170 case EQ: 1171 case NE: return eqPrec; 1172 case LT: 1173 case GT: 1174 case LE: 1175 case GE: return ordPrec; 1176 case BITOR: return bitorPrec; 1177 case BITXOR: return bitxorPrec; 1178 case BITAND: return bitandPrec; 1179 case SL: 1180 case SR: 1181 case USR: return shiftPrec; 1182 case PLUS: 1183 case MINUS: return addPrec; 1184 case MUL: 1185 case DIV: 1186 case MOD: return mulPrec; 1187 case TYPETEST: return ordPrec; 1188 default: throw new AssertionError(); 1189 } 1190 } 1191 1192 static Tree.Kind tagToKind(JCTree.Tag tag) { 1193 switch (tag) { 1194 // Postfix expressions 1195 case POSTINC: // _ ++ 1196 return Tree.Kind.POSTFIX_INCREMENT; 1197 case POSTDEC: // _ -- 1198 return Tree.Kind.POSTFIX_DECREMENT; 1199 1200 // Unary operators 1201 case PREINC: // ++ _ 1202 return Tree.Kind.PREFIX_INCREMENT; 1203 case PREDEC: // -- _ 1204 return Tree.Kind.PREFIX_DECREMENT; 1205 case POS: // + 1206 return Tree.Kind.UNARY_PLUS; 1207 case NEG: // - 1208 return Tree.Kind.UNARY_MINUS; 1209 case COMPL: // ~ 1210 return Tree.Kind.BITWISE_COMPLEMENT; 1211 case NOT: // ! 1212 return Tree.Kind.LOGICAL_COMPLEMENT; 1213 1214 // Binary operators 1215 1216 // Multiplicative operators 1217 case MUL: // * 1218 return Tree.Kind.MULTIPLY; 1219 case DIV: // / 1220 return Tree.Kind.DIVIDE; 1221 case MOD: // % 1222 return Tree.Kind.REMAINDER; 1223 1224 // Additive operators 1225 case PLUS: // + 1226 return Tree.Kind.PLUS; 1227 case MINUS: // - 1228 return Tree.Kind.MINUS; 1229 1230 // Shift operators 1231 case SL: // << 1232 return Tree.Kind.LEFT_SHIFT; 1233 case SR: // >> 1234 return Tree.Kind.RIGHT_SHIFT; 1235 case USR: // >>> 1236 return Tree.Kind.UNSIGNED_RIGHT_SHIFT; 1237 1238 // Relational operators 1239 case LT: // < 1240 return Tree.Kind.LESS_THAN; 1241 case GT: // > 1242 return Tree.Kind.GREATER_THAN; 1243 case LE: // <= 1244 return Tree.Kind.LESS_THAN_EQUAL; 1245 case GE: // >= 1246 return Tree.Kind.GREATER_THAN_EQUAL; 1247 1248 // Equality operators 1249 case EQ: // == 1250 return Tree.Kind.EQUAL_TO; 1251 case NE: // != 1252 return Tree.Kind.NOT_EQUAL_TO; 1253 1254 // Bitwise and logical operators 1255 case BITAND: // & 1256 return Tree.Kind.AND; 1257 case BITXOR: // ^ 1258 return Tree.Kind.XOR; 1259 case BITOR: // | 1260 return Tree.Kind.OR; 1261 1262 // Conditional operators 1263 case AND: // && 1264 return Tree.Kind.CONDITIONAL_AND; 1265 case OR: // || 1266 return Tree.Kind.CONDITIONAL_OR; 1267 1268 // Assignment operators 1269 case MUL_ASG: // *= 1270 return Tree.Kind.MULTIPLY_ASSIGNMENT; 1271 case DIV_ASG: // /= 1272 return Tree.Kind.DIVIDE_ASSIGNMENT; 1273 case MOD_ASG: // %= 1274 return Tree.Kind.REMAINDER_ASSIGNMENT; 1275 case PLUS_ASG: // += 1276 return Tree.Kind.PLUS_ASSIGNMENT; 1277 case MINUS_ASG: // -= 1278 return Tree.Kind.MINUS_ASSIGNMENT; 1279 case SL_ASG: // <<= 1280 return Tree.Kind.LEFT_SHIFT_ASSIGNMENT; 1281 case SR_ASG: // >>= 1282 return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT; 1283 case USR_ASG: // >>>= 1284 return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT; 1285 case BITAND_ASG: // &= 1286 return Tree.Kind.AND_ASSIGNMENT; 1287 case BITXOR_ASG: // ^= 1288 return Tree.Kind.XOR_ASSIGNMENT; 1289 case BITOR_ASG: // |= 1290 return Tree.Kind.OR_ASSIGNMENT; 1291 1292 // Null check (implementation detail), for example, __.getClass() 1293 case NULLCHK: 1294 return Tree.Kind.OTHER; 1295 1296 case ANNOTATION: 1297 return Tree.Kind.ANNOTATION; 1298 case TYPE_ANNOTATION: 1299 return Tree.Kind.TYPE_ANNOTATION; 1300 1301 case EXPORTS: 1302 return Tree.Kind.EXPORTS; 1303 case OPENS: 1304 return Tree.Kind.OPENS; 1305 1306 default: 1307 return null; 1308 } 1309 } 1310 1311 /** 1312 * Returns the underlying type of the tree if it is an annotated type, 1313 * or the tree itself otherwise. 1314 */ 1315 public static JCExpression typeIn(JCExpression tree) { 1316 switch (tree.getTag()) { 1317 case ANNOTATED_TYPE: 1318 return ((JCAnnotatedType)tree).underlyingType; 1319 case IDENT: /* simple names */ 1320 case TYPEIDENT: /* primitive name */ 1321 case SELECT: /* qualified name */ 1322 case TYPEARRAY: /* array types */ 1323 case WILDCARD: /* wild cards */ 1324 case TYPEPARAMETER: /* type parameters */ 1325 case TYPEAPPLY: /* parameterized types */ 1326 case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */ 1327 return tree; 1328 default: 1329 throw new AssertionError("Unexpected type tree: " + tree); 1330 } 1331 } 1332 1333 /* Return the inner-most type of a type tree. 1334 * For an array that contains an annotated type, return that annotated type. 1335 * TODO: currently only used by Pretty. Describe behavior better. 1336 */ 1337 public static JCTree innermostType(JCTree type, boolean skipAnnos) { 1338 JCTree lastAnnotatedType = null; 1339 JCTree cur = type; 1340 loop: while (true) { 1341 switch (cur.getTag()) { 1342 case TYPEARRAY: 1343 lastAnnotatedType = null; 1344 cur = ((JCArrayTypeTree)cur).elemtype; 1345 break; 1346 case WILDCARD: 1347 lastAnnotatedType = null; 1348 cur = ((JCWildcard)cur).inner; 1349 break; 1350 case ANNOTATED_TYPE: 1351 lastAnnotatedType = cur; 1352 cur = ((JCAnnotatedType)cur).underlyingType; 1353 break; 1354 default: 1355 break loop; 1356 } 1357 } 1358 if (!skipAnnos && lastAnnotatedType!=null) { 1359 return lastAnnotatedType; 1360 } else { 1361 return cur; 1362 } 1363 } 1364 1365 private static class TypeAnnotationFinder extends TreeScanner { 1366 public boolean foundTypeAnno = false; 1367 1368 @Override 1369 public void scan(JCTree tree) { 1370 if (foundTypeAnno || tree == null) 1371 return; 1372 super.scan(tree); 1373 } 1374 1375 public void visitAnnotation(JCAnnotation tree) { 1376 foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION); 1377 } 1378 } 1379 1380 public static boolean containsTypeAnnotation(JCTree e) { 1381 TypeAnnotationFinder finder = new TypeAnnotationFinder(); 1382 finder.scan(e); 1383 return finder.foundTypeAnno; 1384 } 1385 1386 public static boolean isModuleInfo(JCCompilationUnit tree) { 1387 return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE) 1388 && tree.getModuleDecl() != null; 1389 } 1390 1391 public static boolean isPackageInfo(JCCompilationUnit tree) { 1392 return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); 1393 } 1394 1395 public static boolean isErrorEnumSwitch(JCExpression selector, List<JCCase> cases) { 1396 return selector.type.tsym.kind == Kinds.Kind.ERR && 1397 cases.stream().flatMap(c -> c.labels.stream()) 1398 .filter(l -> l.hasTag(CONSTANTCASELABEL)) 1399 .map(l -> ((JCConstantCaseLabel) l).expr) 1400 .allMatch(p -> p.hasTag(IDENT)); 1401 } 1402 1403 public static Type primaryPatternType(JCTree pat) { 1404 return switch (pat.getTag()) { 1405 case BINDINGPATTERN -> pat.type; 1406 case RECORDPATTERN -> ((JCRecordPattern) pat).type; 1407 case ANYPATTERN -> ((JCAnyPattern) pat).type; 1408 default -> throw new AssertionError(); 1409 }; 1410 } 1411 1412 public static JCTree primaryPatternTypeTree(JCTree pat) { 1413 return switch (pat.getTag()) { 1414 case BINDINGPATTERN -> ((JCBindingPattern) pat).var.vartype; 1415 case RECORDPATTERN -> ((JCRecordPattern) pat).deconstructor; 1416 default -> throw new AssertionError(); 1417 }; 1418 } 1419 1420 public static boolean expectedExhaustive(JCSwitch tree) { 1421 return tree.patternSwitch || 1422 tree.cases.stream() 1423 .flatMap(c -> c.labels.stream()) 1424 .anyMatch(l -> TreeInfo.isNullCaseLabel(l)); 1425 } 1426 1427 public static boolean unguardedCase(JCCase cse) { 1428 JCExpression guard = cse.guard; 1429 if (guard == null) { 1430 return true; 1431 } 1432 return isBooleanWithValue(guard, 1); 1433 } 1434 1435 public static boolean isBooleanWithValue(JCExpression guard, int value) { 1436 var constValue = guard.type.constValue(); 1437 return constValue != null && 1438 guard.type.hasTag(BOOLEAN) && 1439 ((int) constValue) == value; 1440 } 1441 1442 public static boolean isNullCaseLabel(JCCaseLabel label) { 1443 return label.hasTag(CONSTANTCASELABEL) && 1444 TreeInfo.isNull(((JCConstantCaseLabel) label).expr); 1445 } 1446 }