1 /******************************************************************************* 2 * Copyright (c) 2000, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 package org.eclipse.jdt.core.dom; 16 17 import java.util.AbstractList; 18 import java.util.ArrayList; 19 import java.util.Collections; 20 import java.util.HashMap; 21 import java.util.Iterator; 22 import java.util.List; 23 import java.util.Map; 24 25 import org.eclipse.jdt.internal.core.dom.NaiveASTFlattener; 26 27 /** 28 * Abstract superclass of all Abstract Syntax Tree (AST) node types. 29 * <p> 30 * An AST node represents a Java source code construct, such 31 * as a name, type, expression, statement, or declaration. 32 * </p> 33 * <p> 34 * Each AST node belongs to a unique AST instance, called the owning AST. 35 * The children of an AST node always have the same owner as their parent node. 36 * If a node from one AST is to be added to a different AST, the subtree must 37 * be cloned first to ensure that the added nodes have the correct owning AST. 38 * </p> 39 * <p> 40 * When an AST node is part of an AST, it has a unique parent node. 41 * Clients can navigate upwards, from child to parent, as well as downwards, 42 * from parent to child. Newly created nodes are unparented. When an 43 * unparented node is set as a child of a node (using a 44 * <code>set<i>CHILD</i></code> method), its parent link is set automatically 45 * and the parent link of the former child is set to <code>null</code>. 46 * For nodes with properties that include a list of children (for example, 47 * <code>Block</code> whose <code>statements</code> property is a list 48 * of statements), adding or removing an element to/for the list property 49 * automatically updates the parent links. These lists support the 50 * <code>List.set</code> method; however, the constraint that the same 51 * node cannot appear more than once means that this method cannot be used 52 * to swap elements without first removing the node. 53 * </p> 54 * <p> 55 * ASTs must not contain cycles. All operations that could create a cycle 56 * detect this possibility and fail. 57 * </p> 58 * <p> 59 * ASTs do not contain "holes" (missing subtrees). If a node is required to 60 * have a certain property, a syntactically plausible initial value is 61 * always supplied. 62 * </p> 63 * <p> 64 * The hierarchy of AST node types has some convenient groupings marked 65 * by abstract superclasses: 66 * <ul> 67 * <li>expressions - <code>Expression</code></li> 68 * <li>names - <code>Name</code> (a sub-kind of expression)</li> 69 * <li>statements - <code>Statement</code></li> 70 * <li>types - <code>Type</code></li> 71 * <li>type body declarations - <code>BodyDeclaration</code></li> 72 * </ul> 73 * <p> 74 * Abstract syntax trees may be hand constructed by clients, using the 75 * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to 76 * create new nodes, and the various <code>set<i>CHILD</i></code> methods 77 * to connect them together. 78 * </p> 79 * <p> 80 * The class {@link ASTParser} parses a string 81 * containing a Java source code and returns an abstract syntax tree 82 * for it. The resulting nodes carry source ranges relating the node back to 83 * the original source characters. The source range covers the construct 84 * as a whole. 85 * </p> 86 * <p> 87 * Each AST node carries bit flags, which may convey additional information about 88 * the node. For instance, the parser uses a flag to indicate a syntax error. 89 * Newly created nodes have no flags set. 90 * </p> 91 * <p> 92 * Each AST node is capable of carrying an open-ended collection of 93 * client-defined properties. Newly created nodes have none. 94 * <code>getProperty</code> and <code>setProperty</code> are used to access 95 * these properties. 96 * </p> 97 * <p> 98 * AST nodes are thread-safe for readers provided there are no active writers. 99 * If one thread is modifying an AST, including creating new nodes or cloning 100 * existing ones, it is <b>not</b> safe for another thread to read, visit, 101 * write, create, or clone <em>any</em> of the nodes on the same AST. 102 * When synchronization is required, consider using the common AST 103 * object that owns the node; that is, use 104 * <code>synchronize (node.getAST()) {...}</code>. 105 * </p> 106 * <p> 107 * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code> 108 * for details. The <code>NodeFinder</code> class can be used to find a specific 109 * node inside a tree. 110 * </p> 111 * <p> 112 * Compilation units created by <code>ASTParser</code> from a 113 * source document can be serialized after arbitrary modifications 114 * with minimal loss of original formatting. See 115 * {@link CompilationUnit#recordModifications()} for details. 116 * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for 117 * an alternative way to describe and serialize changes to a 118 * read-only AST. 119 * </p> 120 * 121 * @see ASTParser 122 * @see ASTVisitor 123 * @see NodeFinder 124 * @since 2.0 125 * @noextend This class is not intended to be subclassed by clients. 126 */ 127 @SuppressWarnings({ "rawtypes", "unchecked" }) 128 public abstract class ASTNode { 129 /* 130 * ATTENTION: When doing anything to the ASTNode hierarchy, do not try to 131 * reinvent the wheel. 132 * 133 * Look out for precedents with 134 * - the same structural property type 135 * - for child node properties: the same optionality (can be null / lazy initialization blurbs and impl.) 136 * - the same declaring node type kind (abstract supertype or concrete type) 137 * - a similar history (added in JLSx API, below JLSx only, replaced by {@link #xx}) 138 * ..., and copy what was done there. Most of the code and 139 * Javadoc in this package should look like it was created by a code generator. 140 * 141 * In subclasses of ASTNode, order properties by order of occurrence in source. 142 * In general classes that list all AST node types, order alphabetically. 143 */ 144 145 /* 146 * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES 147 * 148 * There are several things that need to be changed when a 149 * new concrete AST node type (call it "FooBar") is added: 150 * 151 * 1. Create the FooBar AST node type class. 152 * The most effective way to do this is to copy a similar 153 * existing concrete node class to get a template that 154 * includes all the framework methods that must be implemented. 155 * 156 * 2. Add node type constant ASTNode.FOO_BAR. 157 * Node constants are numbered consecutively. Add the 158 * constant after the existing ones. 159 * 160 * 3. Add entry to ASTNode.nodeClassForType(int). 161 * 162 * 4. Add AST.newFooBar() factory method. 163 * 164 * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods. Same for DefaultASTVisitor. 165 * 166 * 6. Add ASTMatcher.match(FooBar,Object) method. 167 * 168 * 7. Ensure that SimpleName.isDeclaration() covers FooBar 169 * nodes if required. 170 * 171 * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate 172 * how these nodes should be serialized. 173 * 174 * 9. Update the AST test suites (ASTVisitorTest, etc.) 175 * 176 * The next steps are to update AST.parse* to start generating 177 * the new type of nodes, and ASTRewrite to serialize them back out. 178 */ 179 180 /* 181 * INSTRUCTIONS FOR ADDING A NEW PROPERTY TO AN AST NODE TYPE 182 * 183 * For concrete node types, use e.g. properties of SimpleName or ClassInstanceCreation 184 * as templates: 185 * 186 * 1. Copy/paste the field, property descriptor, and getter/setter. 187 * 188 * 2. Adjust everything to the new property name and type. In the field's 189 * Javadoc, properly document default value, initialization, and applicable 190 * API levels. 191 * 192 * 3. Add/remove @since tags as necessary. 193 * 194 * 4. Search for references to the members in the template, and add similar 195 * references in corresponding places for the new property. 196 * 197 * 198 * For abstract node types, use AbstractTypeDeclaration as a template: 199 * 200 * 1. Same steps as above, but take extra care to copy and adjust the 201 * *internal*() methods as well. 202 * 203 * 2. Search for references to the members in the template, and add similar 204 * references in corresponding places for the new property (e.g. property 205 * descriptor in each leaf type). 206 */ 207 208 /* 209 * INSTRUCTIONS FOR REPLACING/DEPRECATING A PROPERTY OF AN AST NODE 210 * 211 * To replace a simple property with a child list property, see e.g. how 212 * SingleVariableDeclaration replaced MODIFIERS_PROPERTY with 213 * MODIFIERS2_PROPERTY. 214 * 215 * 1. Reuse the old property id. 216 * 217 * 2. Deprecate all references to the old property, except for the old 218 * getter, which should compute the value from the new property in 219 * later API levels. 220 * 221 * To completely replace a property, see how ClassInstanceCreation replaced 222 * NAME_PROPERTY with TYPE_PROPERTY. 223 */ 224 225 /** 226 * Node type constant indicating a node of type 227 * <code>AnonymousClassDeclaration</code>. 228 * @see AnonymousClassDeclaration 229 */ 230 public static final int ANONYMOUS_CLASS_DECLARATION = 1; 231 232 /** 233 * Node type constant indicating a node of type 234 * <code>ArrayAccess</code>. 235 * @see ArrayAccess 236 */ 237 public static final int ARRAY_ACCESS = 2; 238 239 /** 240 * Node type constant indicating a node of type 241 * <code>ArrayCreation</code>. 242 * @see ArrayCreation 243 */ 244 public static final int ARRAY_CREATION = 3; 245 246 /** 247 * Node type constant indicating a node of type 248 * <code>ArrayInitializer</code>. 249 * @see ArrayInitializer 250 */ 251 public static final int ARRAY_INITIALIZER = 4; 252 253 /** 254 * Node type constant indicating a node of type 255 * <code>ArrayType</code>. 256 * @see ArrayType 257 */ 258 public static final int ARRAY_TYPE = 5; 259 260 /** 261 * Node type constant indicating a node of type 262 * <code>AssertStatement</code>. 263 * @see AssertStatement 264 */ 265 public static final int ASSERT_STATEMENT = 6; 266 267 /** 268 * Node type constant indicating a node of type 269 * <code>Assignment</code>. 270 * @see Assignment 271 */ 272 public static final int ASSIGNMENT = 7; 273 274 /** 275 * Node type constant indicating a node of type 276 * <code>Block</code>. 277 * @see Block 278 */ 279 public static final int BLOCK = 8; 280 281 /** 282 * Node type constant indicating a node of type 283 * <code>BooleanLiteral</code>. 284 * @see BooleanLiteral 285 */ 286 public static final int BOOLEAN_LITERAL = 9; 287 288 /** 289 * Node type constant indicating a node of type 290 * <code>BreakStatement</code>. 291 * @see BreakStatement 292 */ 293 public static final int BREAK_STATEMENT = 10; 294 295 /** 296 * Node type constant indicating a node of type 297 * <code>CastExpression</code>. 298 * @see CastExpression 299 */ 300 public static final int CAST_EXPRESSION = 11; 301 302 /** 303 * Node type constant indicating a node of type 304 * <code>CatchClause</code>. 305 * @see CatchClause 306 */ 307 public static final int CATCH_CLAUSE = 12; 308 309 /** 310 * Node type constant indicating a node of type 311 * <code>CharacterLiteral</code>. 312 * @see CharacterLiteral 313 */ 314 public static final int CHARACTER_LITERAL = 13; 315 316 /** 317 * Node type constant indicating a node of type 318 * <code>ClassInstanceCreation</code>. 319 * @see ClassInstanceCreation 320 */ 321 public static final int CLASS_INSTANCE_CREATION = 14; 322 323 /** 324 * Node type constant indicating a node of type 325 * <code>CompilationUnit</code>. 326 * @see CompilationUnit 327 */ 328 public static final int COMPILATION_UNIT = 15; 329 330 /** 331 * Node type constant indicating a node of type 332 * <code>ConditionalExpression</code>. 333 * @see ConditionalExpression 334 */ 335 public static final int CONDITIONAL_EXPRESSION = 16; 336 337 /** 338 * Node type constant indicating a node of type 339 * <code>ConstructorInvocation</code>. 340 * @see ConstructorInvocation 341 */ 342 public static final int CONSTRUCTOR_INVOCATION = 17; 343 344 /** 345 * Node type constant indicating a node of type 346 * <code>ContinueStatement</code>. 347 * @see ContinueStatement 348 */ 349 public static final int CONTINUE_STATEMENT = 18; 350 351 /** 352 * Node type constant indicating a node of type 353 * <code>DoStatement</code>. 354 * @see DoStatement 355 */ 356 public static final int DO_STATEMENT = 19; 357 358 /** 359 * Node type constant indicating a node of type 360 * <code>EmptyStatement</code>. 361 * @see EmptyStatement 362 */ 363 public static final int EMPTY_STATEMENT = 20; 364 365 /** 366 * Node type constant indicating a node of type 367 * <code>ExpressionStatement</code>. 368 * @see ExpressionStatement 369 */ 370 public static final int EXPRESSION_STATEMENT = 21; 371 372 /** 373 * Node type constant indicating a node of type 374 * <code>FieldAccess</code>. 375 * @see FieldAccess 376 */ 377 public static final int FIELD_ACCESS = 22; 378 379 /** 380 * Node type constant indicating a node of type 381 * <code>FieldDeclaration</code>. 382 * @see FieldDeclaration 383 */ 384 public static final int FIELD_DECLARATION = 23; 385 386 /** 387 * Node type constant indicating a node of type 388 * <code>ForStatement</code>. 389 * @see ForStatement 390 */ 391 public static final int FOR_STATEMENT = 24; 392 393 /** 394 * Node type constant indicating a node of type 395 * <code>IfStatement</code>. 396 * @see IfStatement 397 */ 398 public static final int IF_STATEMENT = 25; 399 400 /** 401 * Node type constant indicating a node of type 402 * <code>ImportDeclaration</code>. 403 * @see ImportDeclaration 404 */ 405 public static final int IMPORT_DECLARATION = 26; 406 407 /** 408 * Node type constant indicating a node of type 409 * <code>InfixExpression</code>. 410 * @see InfixExpression 411 */ 412 public static final int INFIX_EXPRESSION = 27; 413 414 /** 415 * Node type constant indicating a node of type 416 * <code>Initializer</code>. 417 * @see Initializer 418 */ 419 public static final int INITIALIZER = 28; 420 421 /** 422 * Node type constant indicating a node of type 423 * <code>Javadoc</code>. 424 * @see Javadoc 425 */ 426 public static final int JAVADOC = 29; 427 428 /** 429 * Node type constant indicating a node of type 430 * <code>LabeledStatement</code>. 431 * @see LabeledStatement 432 */ 433 public static final int LABELED_STATEMENT = 30; 434 435 /** 436 * Node type constant indicating a node of type 437 * <code>MethodDeclaration</code>. 438 * @see MethodDeclaration 439 */ 440 public static final int METHOD_DECLARATION = 31; 441 442 /** 443 * Node type constant indicating a node of type 444 * <code>MethodInvocation</code>. 445 * @see MethodInvocation 446 */ 447 public static final int METHOD_INVOCATION = 32; 448 449 /** 450 * Node type constant indicating a node of type 451 * <code>NullLiteral</code>. 452 * @see NullLiteral 453 */ 454 public static final int NULL_LITERAL = 33; 455 456 /** 457 * Node type constant indicating a node of type 458 * <code>NumberLiteral</code>. 459 * @see NumberLiteral 460 */ 461 public static final int NUMBER_LITERAL = 34; 462 463 /** 464 * Node type constant indicating a node of type 465 * <code>PackageDeclaration</code>. 466 * @see PackageDeclaration 467 */ 468 public static final int PACKAGE_DECLARATION = 35; 469 470 /** 471 * Node type constant indicating a node of type 472 * <code>ParenthesizedExpression</code>. 473 * @see ParenthesizedExpression 474 */ 475 public static final int PARENTHESIZED_EXPRESSION = 36; 476 477 /** 478 * Node type constant indicating a node of type 479 * <code>PostfixExpression</code>. 480 * @see PostfixExpression 481 */ 482 public static final int POSTFIX_EXPRESSION = 37; 483 484 /** 485 * Node type constant indicating a node of type 486 * <code>PrefixExpression</code>. 487 * @see PrefixExpression 488 */ 489 public static final int PREFIX_EXPRESSION = 38; 490 491 /** 492 * Node type constant indicating a node of type 493 * <code>PrimitiveType</code>. 494 * @see PrimitiveType 495 */ 496 public static final int PRIMITIVE_TYPE = 39; 497 498 /** 499 * Node type constant indicating a node of type 500 * <code>QualifiedName</code>. 501 * @see QualifiedName 502 */ 503 public static final int QUALIFIED_NAME = 40; 504 505 /** 506 * Node type constant indicating a node of type 507 * <code>ReturnStatement</code>. 508 * @see ReturnStatement 509 */ 510 public static final int RETURN_STATEMENT = 41; 511 512 /** 513 * Node type constant indicating a node of type 514 * <code>SimpleName</code>. 515 * @see SimpleName 516 */ 517 public static final int SIMPLE_NAME = 42; 518 519 /** 520 * Node type constant indicating a node of type 521 * <code>SimpleType</code>. 522 * @see SimpleType 523 */ 524 public static final int SIMPLE_TYPE = 43; 525 526 /** 527 * Node type constant indicating a node of type 528 * <code>SingleVariableDeclaration</code>. 529 * @see SingleVariableDeclaration 530 */ 531 public static final int SINGLE_VARIABLE_DECLARATION = 44; 532 533 /** 534 * Node type constant indicating a node of type 535 * <code>StringLiteral</code>. 536 * @see StringLiteral 537 */ 538 public static final int STRING_LITERAL = 45; 539 540 /** 541 * Node type constant indicating a node of type 542 * <code>SuperConstructorInvocation</code>. 543 * @see SuperConstructorInvocation 544 */ 545 public static final int SUPER_CONSTRUCTOR_INVOCATION = 46; 546 547 /** 548 * Node type constant indicating a node of type 549 * <code>SuperFieldAccess</code>. 550 * @see SuperFieldAccess 551 */ 552 public static final int SUPER_FIELD_ACCESS = 47; 553 554 /** 555 * Node type constant indicating a node of type 556 * <code>SuperMethodInvocation</code>. 557 * @see SuperMethodInvocation 558 */ 559 public static final int SUPER_METHOD_INVOCATION = 48; 560 561 /** 562 * Node type constant indicating a node of type 563 * <code>SwitchCase</code>. 564 * @see SwitchCase 565 */ 566 public static final int SWITCH_CASE = 49; 567 568 /** 569 * Node type constant indicating a node of type 570 * <code>SwitchStatement</code>. 571 * @see SwitchStatement 572 */ 573 public static final int SWITCH_STATEMENT = 50; 574 575 /** 576 * Node type constant indicating a node of type 577 * <code>SynchronizedStatement</code>. 578 * @see SynchronizedStatement 579 */ 580 public static final int SYNCHRONIZED_STATEMENT = 51; 581 582 /** 583 * Node type constant indicating a node of type 584 * <code>ThisExpression</code>. 585 * @see ThisExpression 586 */ 587 public static final int THIS_EXPRESSION = 52; 588 589 /** 590 * Node type constant indicating a node of type 591 * <code>ThrowStatement</code>. 592 * @see ThrowStatement 593 */ 594 public static final int THROW_STATEMENT = 53; 595 596 /** 597 * Node type constant indicating a node of type 598 * <code>TryStatement</code>. 599 * @see TryStatement 600 */ 601 public static final int TRY_STATEMENT = 54; 602 603 /** 604 * Node type constant indicating a node of type 605 * <code>TypeDeclaration</code>. 606 * @see TypeDeclaration 607 */ 608 public static final int TYPE_DECLARATION = 55; 609 610 /** 611 * Node type constant indicating a node of type 612 * <code>TypeDeclarationStatement</code>. 613 * @see TypeDeclarationStatement 614 */ 615 public static final int TYPE_DECLARATION_STATEMENT = 56; 616 617 /** 618 * Node type constant indicating a node of type 619 * <code>TypeLiteral</code>. 620 * @see TypeLiteral 621 */ 622 public static final int TYPE_LITERAL = 57; 623 624 /** 625 * Node type constant indicating a node of type 626 * <code>VariableDeclarationExpression</code>. 627 * @see VariableDeclarationExpression 628 */ 629 public static final int VARIABLE_DECLARATION_EXPRESSION = 58; 630 631 /** 632 * Node type constant indicating a node of type 633 * <code>VariableDeclarationFragment</code>. 634 * @see VariableDeclarationFragment 635 */ 636 public static final int VARIABLE_DECLARATION_FRAGMENT = 59; 637 638 /** 639 * Node type constant indicating a node of type 640 * <code>VariableDeclarationStatement</code>. 641 * @see VariableDeclarationStatement 642 */ 643 public static final int VARIABLE_DECLARATION_STATEMENT = 60; 644 645 /** 646 * Node type constant indicating a node of type 647 * <code>WhileStatement</code>. 648 * @see WhileStatement 649 */ 650 public static final int WHILE_STATEMENT = 61; 651 652 /** 653 * Node type constant indicating a node of type 654 * <code>InstanceofExpression</code>. 655 * @see InstanceofExpression 656 */ 657 public static final int INSTANCEOF_EXPRESSION = 62; 658 659 /** 660 * Node type constant indicating a node of type 661 * <code>LineComment</code>. 662 * @see LineComment 663 * @since 3.0 664 */ 665 public static final int LINE_COMMENT = 63; 666 667 /** 668 * Node type constant indicating a node of type 669 * <code>BlockComment</code>. 670 * @see BlockComment 671 * @since 3.0 672 */ 673 public static final int BLOCK_COMMENT = 64; 674 675 /** 676 * Node type constant indicating a node of type 677 * <code>TagElement</code>. 678 * @see TagElement 679 * @since 3.0 680 */ 681 public static final int TAG_ELEMENT = 65; 682 683 /** 684 * Node type constant indicating a node of type 685 * <code>TextElement</code>. 686 * @see TextElement 687 * @since 3.0 688 */ 689 public static final int TEXT_ELEMENT = 66; 690 691 /** 692 * Node type constant indicating a node of type 693 * <code>MemberRef</code>. 694 * @see MemberRef 695 * @since 3.0 696 */ 697 public static final int MEMBER_REF = 67; 698 699 /** 700 * Node type constant indicating a node of type 701 * <code>MethodRef</code>. 702 * @see MethodRef 703 * @since 3.0 704 */ 705 public static final int METHOD_REF = 68; 706 707 /** 708 * Node type constant indicating a node of type 709 * <code>MethodRefParameter</code>. 710 * @see MethodRefParameter 711 * @since 3.0 712 */ 713 public static final int METHOD_REF_PARAMETER = 69; 714 715 /** 716 * Node type constant indicating a node of type 717 * <code>EnhancedForStatement</code>. 718 * @see EnhancedForStatement 719 * @since 3.1 720 */ 721 public static final int ENHANCED_FOR_STATEMENT = 70; 722 723 /** 724 * Node type constant indicating a node of type 725 * <code>EnumDeclaration</code>. 726 * @see EnumDeclaration 727 * @since 3.1 728 */ 729 public static final int ENUM_DECLARATION = 71; 730 731 /** 732 * Node type constant indicating a node of type 733 * <code>EnumConstantDeclaration</code>. 734 * @see EnumConstantDeclaration 735 * @since 3.1 736 */ 737 public static final int ENUM_CONSTANT_DECLARATION = 72; 738 739 /** 740 * Node type constant indicating a node of type 741 * <code>TypeParameter</code>. 742 * @see TypeParameter 743 * @since 3.1 744 */ 745 public static final int TYPE_PARAMETER = 73; 746 747 /** 748 * Node type constant indicating a node of type 749 * <code>ParameterizedType</code>. 750 * @see ParameterizedType 751 * @since 3.1 752 */ 753 public static final int PARAMETERIZED_TYPE = 74; 754 755 /** 756 * Node type constant indicating a node of type 757 * <code>QualifiedType</code>. 758 * @see QualifiedType 759 * @since 3.1 760 */ 761 public static final int QUALIFIED_TYPE = 75; 762 763 /** 764 * Node type constant indicating a node of type 765 * <code>WildcardType</code>. 766 * @see WildcardType 767 * @since 3.1 768 */ 769 public static final int WILDCARD_TYPE = 76; 770 771 /** 772 * Node type constant indicating a node of type 773 * <code>NormalAnnotation</code>. 774 * @see NormalAnnotation 775 * @since 3.1 776 */ 777 public static final int NORMAL_ANNOTATION = 77; 778 779 /** 780 * Node type constant indicating a node of type 781 * <code>MarkerAnnotation</code>. 782 * @see MarkerAnnotation 783 * @since 3.1 784 */ 785 public static final int MARKER_ANNOTATION = 78; 786 787 /** 788 * Node type constant indicating a node of type 789 * <code>SingleMemberAnnotation</code>. 790 * @see SingleMemberAnnotation 791 * @since 3.1 792 */ 793 public static final int SINGLE_MEMBER_ANNOTATION = 79; 794 795 /** 796 * Node type constant indicating a node of type 797 * <code>MemberValuePair</code>. 798 * @see MemberValuePair 799 * @since 3.1 800 */ 801 public static final int MEMBER_VALUE_PAIR = 80; 802 803 /** 804 * Node type constant indicating a node of type 805 * <code>AnnotationTypeDeclaration</code>. 806 * @see AnnotationTypeDeclaration 807 * @since 3.1 808 */ 809 public static final int ANNOTATION_TYPE_DECLARATION = 81; 810 811 /** 812 * Node type constant indicating a node of type 813 * <code>AnnotationTypeMemberDeclaration</code>. 814 * @see AnnotationTypeMemberDeclaration 815 * @since 3.1 816 */ 817 public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82; 818 819 /** 820 * Node type constant indicating a node of type 821 * <code>Modifier</code>. 822 * @see Modifier 823 * @since 3.1 824 */ 825 public static final int MODIFIER = 83; 826 827 /** 828 * Node type constant indicating a node of type 829 * <code>UnionType</code>. 830 * @see UnionType 831 * @since 3.7.1 832 */ 833 public static final int UNION_TYPE = 84; 834 835 /** 836 * Node type constant indicating a node of type 837 * <code>Dimension</code>. 838 * 839 * @see Dimension 840 * @since 3.10 841 */ 842 public static final int DIMENSION = 85; 843 844 /** 845 * Node type constant indicating a node of type 846 * <code>LambdaExpression</code>. 847 * @see LambdaExpression 848 * @since 3.10 849 */ 850 public static final int LAMBDA_EXPRESSION = 86; 851 852 /** 853 * Node type constant indicating a node of type 854 * <code>IntersectionType</code>. 855 * 856 * @see IntersectionType 857 * @since 3.10 858 */ 859 public static final int INTERSECTION_TYPE = 87; 860 861 /** 862 * Node type constant indicating a node of type 863 * <code>NameQualifiedType</code>. 864 * @see NameQualifiedType 865 * @since 3.10 866 */ 867 public static final int NAME_QUALIFIED_TYPE = 88; 868 869 /** 870 * Node type constant indicating a node of type 871 * <code>CreationReference</code>. 872 * @see CreationReference 873 * @since 3.10 874 */ 875 public static final int CREATION_REFERENCE = 89; 876 877 /** 878 * Node type constant indicating a node of type 879 * <code>ExpressionMethodReference</code>. 880 * @see ExpressionMethodReference 881 * @since 3.10 882 */ 883 public static final int EXPRESSION_METHOD_REFERENCE = 90; 884 885 /** 886 * Node type constant indicating a node of type 887 * <code>SuperMethhodReference</code>. 888 * @see SuperMethodReference 889 * @since 3.10 890 */ 891 public static final int SUPER_METHOD_REFERENCE = 91; 892 893 /** 894 * Node type constant indicating a node of type 895 * <code>TypeMethodReference</code>. 896 * @see TypeMethodReference 897 * @since 3.10 898 */ 899 public static final int TYPE_METHOD_REFERENCE = 92; 900 901 /** 902 * Node type constant indicating a node of type 903 * <code>ModuleDeclaration</code>. 904 * @see ModuleDeclaration 905 * @since 3.14 906 */ 907 public static final int MODULE_DECLARATION = 93; 908 909 /** 910 * Node type constant indicating a node of type 911 * <code>RequiresDirective</code>. 912 * @see RequiresDirective 913 * @since 3.14 914 */ 915 public static final int REQUIRES_DIRECTIVE = 94; 916 917 /** 918 * Node type constant indicating a node of type 919 * <code>ExportsDirective</code>. 920 * @see ExportsDirective 921 * @since 3.14 922 */ 923 public static final int EXPORTS_DIRECTIVE = 95; 924 925 /** 926 * Node type constant indicating a node of type 927 * <code>OpensDirective</code>. 928 * @see OpensDirective 929 * @since 3.14 930 */ 931 public static final int OPENS_DIRECTIVE = 96; 932 933 /** 934 * Node type constant indicating a node of type 935 * <code>UsesDirective</code>. 936 * @see UsesDirective 937 * @since 3.14 938 */ 939 public static final int USES_DIRECTIVE = 97; 940 941 /** 942 * Node type constant indicating a node of type 943 * <code>ProvidesDirective</code>. 944 * @see ProvidesDirective 945 * @since 3.14 946 */ 947 public static final int PROVIDES_DIRECTIVE = 98; 948 949 /** 950 * Node type constant indicating a node of type 951 * <code>ModuleModifier</code>. 952 * @see ModuleModifier 953 * @since 3.14 954 */ 955 public static final int MODULE_MODIFIER = 99; 956 957 /** 958 * Node type constant indicating a node of type 959 * <code>SwitchExpression</code>. 960 * @see SwitchExpression 961 * @since 3.18 962 */ 963 public static final int SWITCH_EXPRESSION = 100; 964 965 /** 966 * Node type constant indicating a node of type 967 * <code>YieldStatement</code>. 968 * @see YieldStatement 969 * @since 3.20 970 */ 971 public static final int YIELD_STATEMENT = 101; 972 973 /** 974 * Node type constant indicating a node of type 975 * <code>TextBlock</code>. 976 * @see TextBlock 977 * @since 3.20 978 */ 979 public static final int TEXT_BLOCK = 102; 980 981 /** 982 * Node type constant indicating a node of type 983 * <code>RecordDeclaration</code>. 984 * @see RecordDeclaration 985 * @since 3.22 986 */ 987 public static final int RECORD_DECLARATION = 103; 988 989 990 /** 991 * Returns the node class for the corresponding node type. 992 * 993 * @param nodeType AST node type 994 * @return the corresponding <code>ASTNode</code> subclass 995 * @exception IllegalArgumentException if <code>nodeType</code> is 996 * not a legal AST node type 997 * @see #getNodeType() 998 * @since 3.0 999 */ nodeClassForType(int nodeType)1000 public static Class nodeClassForType(int nodeType) { 1001 switch (nodeType) { 1002 case ANNOTATION_TYPE_DECLARATION : 1003 return AnnotationTypeDeclaration.class; 1004 case ANNOTATION_TYPE_MEMBER_DECLARATION : 1005 return AnnotationTypeMemberDeclaration.class; 1006 case ANONYMOUS_CLASS_DECLARATION : 1007 return AnonymousClassDeclaration.class; 1008 case ARRAY_ACCESS : 1009 return ArrayAccess.class; 1010 case ARRAY_CREATION : 1011 return ArrayCreation.class; 1012 case ARRAY_INITIALIZER : 1013 return ArrayInitializer.class; 1014 case ARRAY_TYPE : 1015 return ArrayType.class; 1016 case ASSERT_STATEMENT : 1017 return AssertStatement.class; 1018 case ASSIGNMENT : 1019 return Assignment.class; 1020 case BLOCK : 1021 return Block.class; 1022 case BLOCK_COMMENT : 1023 return BlockComment.class; 1024 case BOOLEAN_LITERAL : 1025 return BooleanLiteral.class; 1026 case BREAK_STATEMENT : 1027 return BreakStatement.class; 1028 case CAST_EXPRESSION : 1029 return CastExpression.class; 1030 case CATCH_CLAUSE : 1031 return CatchClause.class; 1032 case CHARACTER_LITERAL : 1033 return CharacterLiteral.class; 1034 case CLASS_INSTANCE_CREATION : 1035 return ClassInstanceCreation.class; 1036 case COMPILATION_UNIT : 1037 return CompilationUnit.class; 1038 case CONDITIONAL_EXPRESSION : 1039 return ConditionalExpression.class; 1040 case CONSTRUCTOR_INVOCATION : 1041 return ConstructorInvocation.class; 1042 case CONTINUE_STATEMENT : 1043 return ContinueStatement.class; 1044 case CREATION_REFERENCE : 1045 return CreationReference.class; 1046 case DIMENSION: 1047 return Dimension.class; 1048 case DO_STATEMENT : 1049 return DoStatement.class; 1050 case EMPTY_STATEMENT : 1051 return EmptyStatement.class; 1052 case ENHANCED_FOR_STATEMENT : 1053 return EnhancedForStatement.class; 1054 case ENUM_CONSTANT_DECLARATION : 1055 return EnumConstantDeclaration.class; 1056 case ENUM_DECLARATION : 1057 return EnumDeclaration.class; 1058 case EXPORTS_DIRECTIVE : 1059 return ExportsDirective.class; 1060 case EXPRESSION_METHOD_REFERENCE : 1061 return ExpressionMethodReference.class; 1062 case EXPRESSION_STATEMENT : 1063 return ExpressionStatement.class; 1064 case FIELD_ACCESS : 1065 return FieldAccess.class; 1066 case FIELD_DECLARATION : 1067 return FieldDeclaration.class; 1068 case FOR_STATEMENT : 1069 return ForStatement.class; 1070 case IF_STATEMENT : 1071 return IfStatement.class; 1072 case IMPORT_DECLARATION : 1073 return ImportDeclaration.class; 1074 case INFIX_EXPRESSION : 1075 return InfixExpression.class; 1076 case INITIALIZER : 1077 return Initializer.class; 1078 case INSTANCEOF_EXPRESSION : 1079 return InstanceofExpression.class; 1080 case INTERSECTION_TYPE: 1081 return IntersectionType.class; 1082 case JAVADOC : 1083 return Javadoc.class; 1084 case LABELED_STATEMENT : 1085 return LabeledStatement.class; 1086 case LAMBDA_EXPRESSION : 1087 return LambdaExpression.class; 1088 case LINE_COMMENT : 1089 return LineComment.class; 1090 case MARKER_ANNOTATION : 1091 return MarkerAnnotation.class; 1092 case MEMBER_REF : 1093 return MemberRef.class; 1094 case MEMBER_VALUE_PAIR : 1095 return MemberValuePair.class; 1096 case METHOD_DECLARATION : 1097 return MethodDeclaration.class; 1098 case METHOD_INVOCATION : 1099 return MethodInvocation.class; 1100 case METHOD_REF : 1101 return MethodRef.class; 1102 case METHOD_REF_PARAMETER : 1103 return MethodRefParameter.class; 1104 case MODIFIER : 1105 return Modifier.class; 1106 case MODULE_DECLARATION : 1107 return ModuleDeclaration.class; 1108 case MODULE_MODIFIER : 1109 return ModuleModifier.class; 1110 case NAME_QUALIFIED_TYPE : 1111 return NameQualifiedType.class; 1112 case NORMAL_ANNOTATION : 1113 return NormalAnnotation.class; 1114 case NULL_LITERAL : 1115 return NullLiteral.class; 1116 case NUMBER_LITERAL : 1117 return NumberLiteral.class; 1118 case OPENS_DIRECTIVE : 1119 return OpensDirective.class; 1120 case PACKAGE_DECLARATION : 1121 return PackageDeclaration.class; 1122 case PARAMETERIZED_TYPE : 1123 return ParameterizedType.class; 1124 case PARENTHESIZED_EXPRESSION : 1125 return ParenthesizedExpression.class; 1126 case POSTFIX_EXPRESSION : 1127 return PostfixExpression.class; 1128 case PREFIX_EXPRESSION : 1129 return PrefixExpression.class; 1130 case PRIMITIVE_TYPE : 1131 return PrimitiveType.class; 1132 case PROVIDES_DIRECTIVE : 1133 return ProvidesDirective.class; 1134 case QUALIFIED_NAME : 1135 return QualifiedName.class; 1136 case QUALIFIED_TYPE : 1137 return QualifiedType.class; 1138 case RECORD_DECLARATION : 1139 return RecordDeclaration.class; 1140 case REQUIRES_DIRECTIVE : 1141 return RequiresDirective.class; 1142 case RETURN_STATEMENT : 1143 return ReturnStatement.class; 1144 case SIMPLE_NAME : 1145 return SimpleName.class; 1146 case SIMPLE_TYPE : 1147 return SimpleType.class; 1148 case SINGLE_MEMBER_ANNOTATION : 1149 return SingleMemberAnnotation.class; 1150 case SINGLE_VARIABLE_DECLARATION : 1151 return SingleVariableDeclaration.class; 1152 case STRING_LITERAL : 1153 return StringLiteral.class; 1154 case SUPER_CONSTRUCTOR_INVOCATION : 1155 return SuperConstructorInvocation.class; 1156 case SUPER_FIELD_ACCESS : 1157 return SuperFieldAccess.class; 1158 case SUPER_METHOD_INVOCATION : 1159 return SuperMethodInvocation.class; 1160 case SUPER_METHOD_REFERENCE : 1161 return SuperMethodReference.class; 1162 case SWITCH_CASE: 1163 return SwitchCase.class; 1164 case SWITCH_STATEMENT : 1165 return SwitchStatement.class; 1166 case SWITCH_EXPRESSION : 1167 return SwitchExpression.class; 1168 case SYNCHRONIZED_STATEMENT : 1169 return SynchronizedStatement.class; 1170 case TAG_ELEMENT : 1171 return TagElement.class; 1172 case TEXT_BLOCK : 1173 return TextBlock.class; 1174 case TEXT_ELEMENT : 1175 return TextElement.class; 1176 case THIS_EXPRESSION : 1177 return ThisExpression.class; 1178 case THROW_STATEMENT : 1179 return ThrowStatement.class; 1180 case TRY_STATEMENT : 1181 return TryStatement.class; 1182 case TYPE_DECLARATION : 1183 return TypeDeclaration.class; 1184 case TYPE_DECLARATION_STATEMENT : 1185 return TypeDeclarationStatement.class; 1186 case TYPE_METHOD_REFERENCE : 1187 return TypeMethodReference.class; 1188 case TYPE_LITERAL : 1189 return TypeLiteral.class; 1190 case TYPE_PARAMETER : 1191 return TypeParameter.class; 1192 case UNION_TYPE : 1193 return UnionType.class; 1194 case USES_DIRECTIVE : 1195 return UsesDirective.class; 1196 case VARIABLE_DECLARATION_EXPRESSION : 1197 return VariableDeclarationExpression.class; 1198 case VARIABLE_DECLARATION_FRAGMENT : 1199 return VariableDeclarationFragment.class; 1200 case VARIABLE_DECLARATION_STATEMENT : 1201 return VariableDeclarationStatement.class; 1202 case WHILE_STATEMENT : 1203 return WhileStatement.class; 1204 case WILDCARD_TYPE : 1205 return WildcardType.class; 1206 case YIELD_STATEMENT : 1207 return YieldStatement.class; 1208 } 1209 throw new IllegalArgumentException(); 1210 } 1211 1212 /** 1213 * Owning AST. 1214 * <p> 1215 * N.B. This is a private field, but declared as package-visible 1216 * for more efficient access from inner classes. 1217 * </p> 1218 */ 1219 final AST ast; 1220 1221 /** 1222 * Parent AST node, or <code>null</code> if this node is a root. 1223 * Initially <code>null</code>. 1224 */ 1225 private ASTNode parent = null; 1226 1227 /** 1228 * An unmodifiable empty map (used to implement <code>properties()</code>). 1229 */ 1230 private static final Map UNMODIFIABLE_EMPTY_MAP 1231 = Collections.unmodifiableMap(new HashMap(1)); 1232 1233 /** 1234 * Primary field used in representing node properties efficiently. 1235 * If <code>null</code>, this node has no properties. 1236 * If a {@link String}, this is the name of this node's sole property, 1237 * and <code>property2</code> contains its value. 1238 * If a {@link Map}, this is the table of property name-value 1239 * mappings; <code>property2</code>, if non-null is its unmodifiable 1240 * equivalent. 1241 * Initially <code>null</code>. 1242 * 1243 * @see #property2 1244 */ 1245 private Object property1 = null; 1246 1247 /** 1248 * Auxiliary field used in representing node properties efficiently. 1249 * 1250 * @see #property1 1251 */ 1252 private Object property2 = null; 1253 1254 /** 1255 * A character index into the original source string, 1256 * or <code>-1</code> if no source position information is available 1257 * for this node; <code>-1</code> by default. 1258 */ 1259 private int startPosition = -1; 1260 1261 /** 1262 * A character length, or <code>0</code> if no source position 1263 * information is recorded for this node; <code>0</code> by default. 1264 */ 1265 private int length = 0; 1266 1267 /** 1268 * Flag constant (bit mask, value 1) indicating that there is something 1269 * not quite right with this AST node. 1270 * <p> 1271 * The standard parser (<code>ASTParser</code>) sets this 1272 * flag on a node to indicate a syntax error detected in the vicinity. 1273 * </p> 1274 */ 1275 public static final int MALFORMED = 1; 1276 1277 /** 1278 * Flag constant (bit mask, value 2) indicating that this is a node 1279 * that was created by the parser (as opposed to one created by another 1280 * party). 1281 * <p> 1282 * The standard parser (<code>ASTParser</code>) sets this 1283 * flag on the nodes it creates. 1284 * </p> 1285 * @since 3.0 1286 */ 1287 public static final int ORIGINAL = 2; 1288 1289 /** 1290 * Flag constant (bit mask, value 4) indicating that this node 1291 * is unmodifiable. When a node is marked unmodifiable, the 1292 * following operations result in a runtime exception: 1293 * <ul> 1294 * <li>Change a simple property of this node.</li> 1295 * <li>Add or remove a child node from this node.</li> 1296 * <li>Parent (or reparent) this node.</li> 1297 * </ul> 1298 * <p> 1299 * The standard parser (<code>ASTParser</code>) does not set 1300 * this flag on the nodes it creates. However, clients may set 1301 * this flag on a node to prevent further modification of the 1302 * its structural properties. 1303 * </p> 1304 * @since 3.0 1305 */ 1306 public static final int PROTECT = 4; 1307 1308 /** 1309 * Flag constant (bit mask, value 8) indicating that this node 1310 * or a part of this node is recovered from source that contains 1311 * a syntax error detected in the vicinity. 1312 * <p> 1313 * The standard parser (<code>ASTParser</code>) sets this 1314 * flag on a node to indicate a recovered node. 1315 * </p> 1316 * @since 3.2 1317 */ 1318 public static final int RECOVERED = 8; 1319 1320 /** 1321 * int containing the node type in the top 16 bits and 1322 * flags in the bottom 16 bits; none set by default. 1323 * <p> 1324 * N.B. This is a private field, but declared as package-visible 1325 * for more efficient access from inner classes. 1326 * </p> 1327 * 1328 * @see #MALFORMED 1329 */ 1330 int typeAndFlags = 0; 1331 1332 /** 1333 * Property of parent in which this node is a child, or <code>null</code> 1334 * if this node is a root. Initially <code>null</code>. 1335 * 1336 * @see #getLocationInParent 1337 * @since 3.0 1338 */ 1339 private StructuralPropertyDescriptor location = null; 1340 1341 /** Internal convenience constant indicating that there is definite risk of cycles. 1342 * @see ChildPropertyDescriptor#cycleRisk() 1343 * @see ChildListPropertyDescriptor#cycleRisk() 1344 * @since 3.0 1345 */ 1346 static final boolean CYCLE_RISK = true; 1347 1348 /** Internal convenience constant indicating that there is no risk of cycles. 1349 * @see ChildPropertyDescriptor#cycleRisk() 1350 * @see ChildListPropertyDescriptor#cycleRisk() 1351 * @since 3.0 1352 */ 1353 static final boolean NO_CYCLE_RISK = false; 1354 1355 /** Internal convenience constant indicating that a structural property is mandatory. 1356 * @since 3.0 1357 */ 1358 static final boolean MANDATORY = true; 1359 1360 /** Internal convenience constant indicating that a structural property is optional. 1361 * @since 3.0 1362 */ 1363 static final boolean OPTIONAL = false; 1364 1365 /** 1366 * A specialized implementation of a list of ASTNodes. The 1367 * implementation is based on an ArrayList. 1368 */ 1369 class NodeList extends AbstractList { 1370 1371 /** 1372 * The underlying list in which the nodes of this list are 1373 * stored (element type: {@link ASTNode}). 1374 * <p> 1375 * Be stingy on storage - assume that list will be empty. 1376 * </p> 1377 * <p> 1378 * This field declared default visibility (rather than private) 1379 * so that accesses from <code>NodeList.Cursor</code> do not require 1380 * a synthetic accessor method. 1381 * </p> 1382 */ 1383 ArrayList store = new ArrayList(0); 1384 1385 /** 1386 * The property descriptor for this list. 1387 */ 1388 ChildListPropertyDescriptor propertyDescriptor; 1389 1390 /** 1391 * A cursor for iterating over the elements of the list. 1392 * Does not lose its position if the list is changed during 1393 * the iteration. 1394 */ 1395 class Cursor implements Iterator { 1396 /** 1397 * The position of the cursor between elements. If the value 1398 * is N, then the cursor sits between the element at positions 1399 * N-1 and N. Initially just before the first element of the 1400 * list. 1401 */ 1402 private int position = 0; 1403 1404 @Override hasNext()1405 public boolean hasNext() { 1406 return this.position < NodeList.this.store.size(); 1407 } 1408 1409 @Override next()1410 public Object next() { 1411 Object result = NodeList.this.store.get(this.position); 1412 this.position++; 1413 return result; 1414 } 1415 1416 @Override remove()1417 public void remove() { 1418 throw new UnsupportedOperationException(); 1419 } 1420 1421 /** 1422 * Adjusts this cursor to accommodate an add/remove at the given 1423 * index. 1424 * 1425 * @param index the position at which the element was added 1426 * or removed 1427 * @param delta +1 for add, and -1 for remove 1428 */ update(int index, int delta)1429 void update(int index, int delta) { 1430 if (this.position > index) { 1431 // the cursor has passed the added or removed element 1432 this.position += delta; 1433 } 1434 } 1435 } 1436 1437 /** 1438 * A list of currently active cursors (element type: 1439 * {@link Cursor}), or <code>null</code> if there are no 1440 * active cursors. 1441 * <p> 1442 * It is important for storage considerations to maintain the 1443 * null-means-empty invariant; otherwise, every NodeList instance 1444 * will waste a lot of space. A cursor is needed only for the duration 1445 * of a visit to the child nodes. Under normal circumstances, only a 1446 * single cursor is needed; multiple cursors are only required if there 1447 * are multiple visits going on at the same time. 1448 * </p> 1449 */ 1450 private List cursors = null; 1451 1452 /** 1453 * Creates a new empty list of nodes owned by this node. 1454 * This node will be the common parent of all nodes added to 1455 * this list. 1456 * 1457 * @param property the property descriptor 1458 * @since 3.0 1459 */ NodeList(ChildListPropertyDescriptor property)1460 NodeList(ChildListPropertyDescriptor property) { 1461 super(); 1462 this.propertyDescriptor = property; 1463 } 1464 1465 @Override size()1466 public int size() { 1467 return this.store.size(); 1468 } 1469 1470 @Override get(int index)1471 public Object get(int index) { 1472 return this.store.get(index); 1473 } 1474 1475 @Override set(int index, Object element)1476 public Object set(int index, Object element) { 1477 if (element == null) { 1478 throw new IllegalArgumentException(); 1479 } 1480 if ((ASTNode.this.typeAndFlags & PROTECT) != 0) { 1481 // this node is protected => cannot gain or lose children 1482 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 1483 } 1484 // delink old child from parent, and link new child to parent 1485 ASTNode newChild = (ASTNode) element; 1486 ASTNode oldChild = (ASTNode) this.store.get(index); 1487 if (oldChild == newChild) { 1488 return oldChild; 1489 } 1490 if ((oldChild.typeAndFlags & PROTECT) != 0) { 1491 // old child is protected => cannot be unparented 1492 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 1493 } 1494 ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType); 1495 ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor); 1496 1497 Object result = this.store.set(index, newChild); 1498 // n.b. setParent will call ast.modifying() 1499 oldChild.setParent(null, null); 1500 newChild.setParent(ASTNode.this, this.propertyDescriptor); 1501 ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor); 1502 return result; 1503 } 1504 1505 @Override add(int index, Object element)1506 public void add(int index, Object element) { 1507 if (element == null) { 1508 throw new IllegalArgumentException(); 1509 } 1510 if ((ASTNode.this.typeAndFlags & PROTECT) != 0) { 1511 // this node is protected => cannot gain or lose children 1512 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 1513 } 1514 // link new child to parent 1515 ASTNode newChild = (ASTNode) element; 1516 ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType); 1517 ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor); 1518 1519 1520 this.store.add(index, element); 1521 updateCursors(index, +1); 1522 // n.b. setParent will call ast.modifying() 1523 newChild.setParent(ASTNode.this, this.propertyDescriptor); 1524 ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor); 1525 } 1526 1527 @Override remove(int index)1528 public Object remove(int index) { 1529 if ((ASTNode.this.typeAndFlags & PROTECT) != 0) { 1530 // this node is protected => cannot gain or lose children 1531 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 1532 } 1533 // delink old child from parent 1534 ASTNode oldChild = (ASTNode) this.store.get(index); 1535 if ((oldChild.typeAndFlags & PROTECT) != 0) { 1536 // old child is protected => cannot be unparented 1537 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 1538 } 1539 1540 ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor); 1541 // n.b. setParent will call ast.modifying() 1542 oldChild.setParent(null, null); 1543 Object result = this.store.remove(index); 1544 updateCursors(index, -1); 1545 ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor); 1546 return result; 1547 1548 } 1549 1550 /** 1551 * Allocate a cursor to use for a visit. The client must call 1552 * <code>releaseCursor</code> when done. 1553 * <p> 1554 * This method is internally synchronized on this NodeList. 1555 * It is thread-safe to create a cursor. 1556 * </p> 1557 * 1558 * @return a new cursor positioned before the first element 1559 * of the list 1560 */ newCursor()1561 Cursor newCursor() { 1562 synchronized (this) { 1563 // serialize cursor management on this NodeList 1564 if (this.cursors == null) { 1565 // convert null to empty list 1566 this.cursors = new ArrayList(1); 1567 } 1568 Cursor result = new Cursor(); 1569 this.cursors.add(result); 1570 return result; 1571 } 1572 } 1573 1574 /** 1575 * Releases the given cursor at the end of a visit. 1576 * <p> 1577 * This method is internally synchronized on this NodeList. 1578 * It is thread-safe to release a cursor. 1579 * </p> 1580 * 1581 * @param cursor the cursor 1582 */ releaseCursor(Cursor cursor)1583 void releaseCursor(Cursor cursor) { 1584 synchronized (this) { 1585 // serialize cursor management on this NodeList 1586 this.cursors.remove(cursor); 1587 if (this.cursors.isEmpty()) { 1588 // important: convert empty list back to null 1589 // otherwise the node will hang on to needless junk 1590 this.cursors = null; 1591 } 1592 } 1593 } 1594 1595 /** 1596 * Adjusts all cursors to accommodate an add/remove at the given 1597 * index. 1598 * <p> 1599 * This method is only used when the list is being modified. 1600 * The AST is not thread-safe if any of the clients are modifying it. 1601 * </p> 1602 * 1603 * @param index the position at which the element was added 1604 * or removed 1605 * @param delta +1 for add, and -1 for remove 1606 */ updateCursors(int index, int delta)1607 private synchronized void updateCursors(int index, int delta) { 1608 if (this.cursors == null) { 1609 // there are no cursors to worry about 1610 return; 1611 } 1612 for (Iterator it = this.cursors.iterator(); it.hasNext(); ) { 1613 Cursor c = (Cursor) it.next(); 1614 c.update(index, delta); 1615 } 1616 } 1617 1618 /** 1619 * Returns an estimate of the memory footprint of this node list 1620 * instance in bytes. 1621 * <ul> 1622 * <li>1 object header for the NodeList instance</li> 1623 * <li>5 4-byte fields of the NodeList instance</li> 1624 * <li>0 for cursors since null unless walk in progress</li> 1625 * <li>1 object header for the ArrayList instance</li> 1626 * <li>2 4-byte fields of the ArrayList instance</li> 1627 * <li>1 object header for an Object[] instance</li> 1628 * <li>4 bytes in array for each element</li> 1629 * </ul> 1630 * 1631 * @return the size of this node list in bytes 1632 */ memSize()1633 int memSize() { 1634 int result = HEADERS + 5 * 4; 1635 result += HEADERS + 2 * 4; 1636 result += HEADERS + 4 * size(); 1637 return result; 1638 } 1639 1640 /** 1641 * Returns an estimate of the memory footprint in bytes of this node 1642 * list and all its subtrees. 1643 * 1644 * @return the size of this list of subtrees in bytes 1645 */ listSize()1646 int listSize() { 1647 int result = memSize(); 1648 for (Iterator it = iterator(); it.hasNext(); ) { 1649 ASTNode child = (ASTNode) it.next(); 1650 result += child.treeSize(); 1651 } 1652 return result; 1653 } 1654 } 1655 1656 /** 1657 * Creates a new AST node owned by the given AST. Once established, 1658 * the relationship between an AST node and its owning AST does not change 1659 * over the lifetime of the node. The new node has no parent node, 1660 * and no properties. 1661 * <p> 1662 * N.B. This constructor is package-private; all subclasses my be 1663 * declared in the same package; clients are unable to declare 1664 * additional subclasses. 1665 * </p> 1666 * 1667 * @param ast the AST that is to own this node 1668 */ ASTNode(AST ast)1669 ASTNode(AST ast) { 1670 if (ast == null) { 1671 throw new IllegalArgumentException(); 1672 } 1673 1674 this.ast = ast; 1675 setNodeType(getNodeType0()); 1676 setFlags(ast.getDefaultNodeFlag()); 1677 // setFlags calls modifying(); 1678 } 1679 1680 /** 1681 * Returns this node's AST. 1682 * <p> 1683 * Note that the relationship between an AST node and its owing AST does 1684 * not change over the lifetime of a node. 1685 * </p> 1686 * 1687 * @return the AST that owns this node 1688 */ getAST()1689 public final AST getAST() { 1690 return this.ast; 1691 } 1692 1693 /** 1694 * Returns this node's parent node, or <code>null</code> if this is the 1695 * root node. 1696 * <p> 1697 * Note that the relationship between an AST node and its parent node 1698 * may change over the lifetime of a node. 1699 * </p> 1700 * 1701 * @return the parent of this node, or <code>null</code> if none 1702 */ getParent()1703 public final ASTNode getParent() { 1704 return this.parent; 1705 } 1706 1707 /** 1708 * Returns the location of this node within its parent, 1709 * or <code>null</code> if this is a root node. 1710 * <pre> 1711 * ASTNode node = ...; 1712 * ASTNode parent = node.getParent(); 1713 * StructuralPropertyDescriptor location = node.getLocationInParent(); 1714 * assert (parent != null) == (location != null); 1715 * if ((location != null) && location.isChildProperty()) 1716 * assert parent.getStructuralProperty(location) == node; 1717 * if ((location != null) && location.isChildListProperty()) 1718 * assert ((List) parent.getStructuralProperty(location)).contains(node); 1719 * </pre> 1720 * <p> 1721 * Note that the relationship between an AST node and its parent node 1722 * may change over the lifetime of a node. 1723 * </p> 1724 * 1725 * @return the location of this node in its parent, 1726 * or <code>null</code> if this node has no parent 1727 * @since 3.0 1728 */ getLocationInParent()1729 public final StructuralPropertyDescriptor getLocationInParent() { 1730 return this.location; 1731 } 1732 1733 /** 1734 * Returns the root node at or above this node; returns this node if 1735 * it is a root. 1736 * 1737 * @return the root node at or above this node 1738 */ getRoot()1739 public final ASTNode getRoot() { 1740 ASTNode candidate = this; 1741 while (true) { 1742 ASTNode p = candidate.getParent(); 1743 if (p == null) { 1744 // candidate has no parent - that's the guy 1745 return candidate; 1746 } 1747 candidate = p; 1748 } 1749 } 1750 1751 /** 1752 * Returns the value of the given structural property for this node. The value 1753 * returned depends on the kind of property: 1754 * <ul> 1755 * <li>{@link SimplePropertyDescriptor} - the value of the given simple property, 1756 * or <code>null</code> if none; primitive values are "boxed"</li> 1757 * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>), 1758 * or <code>null</code> if none</li> 1759 * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li> 1760 * </ul> 1761 * 1762 * @param property the property 1763 * @return the value, or <code>null</code> if none 1764 * @exception RuntimeException if this node does not have the given property 1765 * @since 3.0 1766 */ getStructuralProperty(StructuralPropertyDescriptor property)1767 public final Object getStructuralProperty(StructuralPropertyDescriptor property) { 1768 if (property instanceof SimplePropertyDescriptor) { 1769 SimplePropertyDescriptor p = (SimplePropertyDescriptor) property; 1770 if (p.getValueType() == int.class) { 1771 int result = internalGetSetIntProperty(p, true, 0); 1772 return Integer.valueOf(result); 1773 } else if (p.getValueType() == boolean.class) { 1774 boolean result = internalGetSetBooleanProperty(p, true, false); 1775 return Boolean.valueOf(result); 1776 } else { 1777 return internalGetSetObjectProperty(p, true, null); 1778 } 1779 } 1780 if (property instanceof ChildPropertyDescriptor) { 1781 return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null); 1782 } 1783 if (property instanceof ChildListPropertyDescriptor) { 1784 return internalGetChildListProperty((ChildListPropertyDescriptor) property); 1785 } 1786 throw new IllegalArgumentException(); 1787 } 1788 1789 /** 1790 * Sets the value of the given structural property for this node. The value 1791 * passed depends on the kind of property: 1792 * <ul> 1793 * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property, 1794 * or <code>null</code> if none; primitive values are "boxed"</li> 1795 * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>), 1796 * or <code>null</code> if none</li> 1797 * <li>{@link ChildListPropertyDescriptor} - not allowed</li> 1798 * </ul> 1799 * 1800 * @param property the property 1801 * @param value the property value 1802 * @exception RuntimeException if this node does not have the 1803 * given property, or if the given property cannot be set 1804 * @since 3.0 1805 */ setStructuralProperty(StructuralPropertyDescriptor property, Object value)1806 public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) { 1807 if (property instanceof SimplePropertyDescriptor) { 1808 SimplePropertyDescriptor p = (SimplePropertyDescriptor) property; 1809 if (p.getValueType() == int.class) { 1810 int arg = ((Integer) value).intValue(); 1811 internalGetSetIntProperty(p, false, arg); 1812 return; 1813 } else if (p.getValueType() == boolean.class) { 1814 boolean arg = ((Boolean) value).booleanValue(); 1815 internalGetSetBooleanProperty(p, false, arg); 1816 return; 1817 } else { 1818 if (value == null && p.isMandatory()) { 1819 throw new IllegalArgumentException(); 1820 } 1821 internalGetSetObjectProperty(p, false, value); 1822 return; 1823 } 1824 } 1825 if (property instanceof ChildPropertyDescriptor) { 1826 ChildPropertyDescriptor p = (ChildPropertyDescriptor) property; 1827 ASTNode child = (ASTNode) value; 1828 if (child == null && p.isMandatory()) { 1829 throw new IllegalArgumentException(); 1830 } 1831 internalGetSetChildProperty(p, false, child); 1832 return; 1833 } 1834 if (property instanceof ChildListPropertyDescriptor) { 1835 throw new IllegalArgumentException("Cannot set the list of child list property"); //$NON-NLS-1$ 1836 } 1837 } 1838 1839 /** 1840 * Sets the value of the given int-valued property for this node. 1841 * The default implementation of this method throws an exception explaining 1842 * that this node does not have such a property. This method should be 1843 * extended in subclasses that have at least one simple property whose value 1844 * type is int. 1845 * 1846 * @param property the property 1847 * @param get <code>true</code> for a get operation, and 1848 * <code>false</code> for a set operation 1849 * @param value the new property value; ignored for get operations 1850 * @return the value; always returns 1851 * <code>0</code> for set operations 1852 * @exception RuntimeException if this node does not have the 1853 * given property, or if the given value cannot be set as specified 1854 * @since 3.0 1855 */ internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value)1856 int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) { 1857 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ 1858 } 1859 1860 /** 1861 * Sets the value of the given boolean-valued property for this node. 1862 * The default implementation of this method throws an exception explaining 1863 * that this node does not have such a property. This method should be 1864 * extended in subclasses that have at least one simple property whose value 1865 * type is boolean. 1866 * 1867 * @param property the property 1868 * @param get <code>true</code> for a get operation, and 1869 * <code>false</code> for a set operation 1870 * @param value the new property value; ignored for get operations 1871 * @return the value; always returns 1872 * <code>false</code> for set operations 1873 * @exception RuntimeException if this node does not have the 1874 * given property, or if the given value cannot be set as specified 1875 * @since 3.0 1876 */ internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value)1877 boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) { 1878 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ 1879 } 1880 1881 /** 1882 * Sets the value of the given property for this node. 1883 * The default implementation of this method throws an exception explaining 1884 * that this node does not have such a property. This method should be 1885 * extended in subclasses that have at least one simple property whose value 1886 * type is a reference type. 1887 * 1888 * @param property the property 1889 * @param get <code>true</code> for a get operation, and 1890 * <code>false</code> for a set operation 1891 * @param value the new property value, or <code>null</code> if none; 1892 * ignored for get operations 1893 * @return the value, or <code>null</code> if none; always returns 1894 * <code>null</code> for set operations 1895 * @exception RuntimeException if this node does not have the 1896 * given property, or if the given value cannot be set as specified 1897 * @since 3.0 1898 */ internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value)1899 Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) { 1900 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ 1901 } 1902 1903 /** 1904 * Sets the child value of the given property for this node. 1905 * The default implementation of this method throws an exception explaining 1906 * that this node does not have such a property. This method should be 1907 * extended in subclasses that have at least one child property. 1908 * 1909 * @param property the property 1910 * @param get <code>true</code> for a get operation, and 1911 * <code>false</code> for a set operation 1912 * @param child the new child value, or <code>null</code> if none; 1913 * always <code>null</code> for get operations 1914 * @return the child, or <code>null</code> if none; always returns 1915 * <code>null</code> for set operations 1916 * @exception RuntimeException if this node does not have the 1917 * given property, or if the given child cannot be set as specified 1918 * @since 3.0 1919 */ internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)1920 ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { 1921 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ 1922 } 1923 1924 /** 1925 * Returns the list value of the given property for this node. 1926 * The default implementation of this method throws an exception explaining 1927 * that this node does not have such a property. This method should be 1928 * extended in subclasses that have at least one child list property. 1929 * 1930 * @param property the property 1931 * @return the list (element type: {@link ASTNode}) 1932 * @exception RuntimeException if the given node does not have the 1933 * given property 1934 * @since 3.0 1935 */ internalGetChildListProperty(ChildListPropertyDescriptor property)1936 List internalGetChildListProperty(ChildListPropertyDescriptor property) { 1937 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ 1938 } 1939 1940 /** 1941 * Returns a list of structural property descriptors for nodes of the 1942 * same type as this node. Clients must not modify the result. 1943 * <p> 1944 * Note that property descriptors are a meta-level mechanism 1945 * for manipulating ASTNodes in a generic way. They are 1946 * unrelated to <code>get/setProperty</code>. 1947 * </p> 1948 * 1949 * @return a list of property descriptors (element type: 1950 * {@link StructuralPropertyDescriptor}) 1951 * @since 3.0 1952 */ structuralPropertiesForType()1953 public final List structuralPropertiesForType() { 1954 return internalStructuralPropertiesForType(this.ast.apiLevel, this.ast.isPreviewEnabled()); 1955 } 1956 1957 /** 1958 * Returns a list of property descriptors for this node type. 1959 * Clients must not modify the result. This abstract method 1960 * must be implemented in each concrete AST node type. 1961 * <p> 1962 * N.B. This method is package-private, so that the implementations 1963 * of this method in each of the concrete AST node types do not 1964 * clutter up the API doc. 1965 * </p> 1966 * 1967 * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants 1968 * @return a list of property descriptors (element type: 1969 * {@link StructuralPropertyDescriptor}) 1970 * @since 3.0 1971 */ internalStructuralPropertiesForType(int apiLevel)1972 abstract List internalStructuralPropertiesForType(int apiLevel); 1973 1974 1975 /** 1976 * Returns a list of property descriptors for this node type. 1977 * Clients must not modify the result. This abstract method 1978 * must be implemented in each concrete AST node type. 1979 * <p> 1980 * N.B. This method is package-private, so that the implementations 1981 * of this method in each of the concrete AST node types do not 1982 * clutter up the API doc. 1983 * </p> 1984 * 1985 * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants 1986 * @param previewEnabled the previewEnabled flag 1987 * @return a list of property descriptors (element type: 1988 * {@link StructuralPropertyDescriptor}) 1989 * @since 3.19 1990 */ internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled)1991 List internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled) { 1992 return internalStructuralPropertiesForType(apiLevel); 1993 } 1994 1995 /** 1996 * Internal helper method that starts the building a list of 1997 * property descriptors for the given node type. 1998 * 1999 * @param nodeClass the class for a concrete node type with n properties 2000 * @param propertyList empty list, with capacity for n+1 elements 2001 */ createPropertyList(Class nodeClass, List propertyList)2002 static void createPropertyList(Class nodeClass, List propertyList) { 2003 // stuff nodeClass at head of list for future ref 2004 propertyList.add(nodeClass); 2005 } 2006 2007 /** 2008 * Internal helper method that adding a property descriptor. 2009 * 2010 * @param property the structural property descriptor 2011 * @param propertyList list beginning with the AST node class 2012 * followed by accumulated structural property descriptors 2013 */ addProperty(StructuralPropertyDescriptor property, List propertyList)2014 static void addProperty(StructuralPropertyDescriptor property, List propertyList) { 2015 Class nodeClass = (Class) propertyList.get(0); 2016 if (property.getNodeClass() != nodeClass) { 2017 // easily made cut-and-paste mistake 2018 throw new RuntimeException("Structural property descriptor has wrong node class!"); //$NON-NLS-1$ 2019 } 2020 propertyList.add(property); 2021 } 2022 2023 /** 2024 * Internal helper method that completes the building of 2025 * a node type's structural property descriptor list. 2026 * 2027 * @param propertyList list beginning with the AST node class 2028 * followed by accumulated structural property descriptors 2029 * @return unmodifiable list of structural property descriptors 2030 * (element type: {@link StructuralPropertyDescriptor}) 2031 */ reapPropertyList(List propertyList)2032 static List reapPropertyList(List propertyList) { 2033 propertyList.remove(0); // remove nodeClass 2034 // compact 2035 ArrayList a = new ArrayList(propertyList.size()); 2036 a.addAll(propertyList); 2037 return Collections.unmodifiableList(a); 2038 } 2039 2040 /** 2041 * Checks that this AST operation is not used when 2042 * building JLS2 level ASTs. 2043 * <p> 2044 * Use this method to prevent access to new properties that have been added in JLS3. 2045 * </p> 2046 * 2047 * @exception UnsupportedOperationException if this operation is used in a JLS2 AST 2048 * @since 3.0 2049 */ unsupportedIn2()2050 final void unsupportedIn2() { 2051 if (this.ast.apiLevel == AST.JLS2_INTERNAL) { 2052 throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$ 2053 } 2054 } 2055 2056 /** 2057 * Checks that this AST operation is not used when 2058 * building JLS2 or JLS3 level ASTs. 2059 * <p> 2060 * Use this method to prevent access to new properties that have been added in JLS4. 2061 * </p> 2062 * 2063 * @exception UnsupportedOperationException if this operation is used in a JLS2 or JLS3 AST 2064 * @since 3.7 2065 */ unsupportedIn2_3()2066 final void unsupportedIn2_3() { 2067 if (this.ast.apiLevel <= AST.JLS3_INTERNAL) { 2068 throw new UnsupportedOperationException("Operation only supported in JLS4 and later AST"); //$NON-NLS-1$ 2069 } 2070 } 2071 2072 /** 2073 * Checks that this AST operation is not used when 2074 * building JLS2 or JLS3 or JLS4 level ASTs. 2075 * <p> 2076 * Use this method to prevent access to new properties that have been added in JLS8. 2077 * </p> 2078 * 2079 * @exception UnsupportedOperationException if this operation is used below JLS8 2080 * @since 3.10 2081 */ unsupportedIn2_3_4()2082 final void unsupportedIn2_3_4() { 2083 if (this.ast.apiLevel < AST.JLS8_INTERNAL) { 2084 throw new UnsupportedOperationException("Operation only supported in JLS8 and later AST"); //$NON-NLS-1$ 2085 } 2086 } 2087 2088 /** 2089 * Checks that this AST operation is not used when 2090 * building JLS2, JLS3, JLS4 or JLS8 level ASTs. 2091 * <p> 2092 * Use this method to prevent access to new properties that have been added in JLS9. 2093 * </p> 2094 * 2095 * @exception UnsupportedOperationException if this operation is used below JLS9 2096 * @since 3.14 2097 */ unsupportedBelow9()2098 final void unsupportedBelow9() { 2099 if (this.ast.apiLevel < AST.JLS9_INTERNAL) { 2100 throw new UnsupportedOperationException("Operation only supported in JLS9 and later AST"); //$NON-NLS-1$ 2101 } 2102 } 2103 /** 2104 * Checks that this AST operation is not used when 2105 * building JLS2, JLS3, JLS4, JLS8 or JLS9 level ASTs. 2106 * <p> 2107 * Use this method to prevent access to new properties that have been added in JLS10 2108 * </p> 2109 * 2110 * @exception UnsupportedOperationException if this operation is used below JLS10 2111 * @since 3.14 2112 */ unsupportedBelow10()2113 final void unsupportedBelow10() { 2114 if (this.ast.apiLevel < AST.JLS10_INTERNAL) { 2115 throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS10 and above"); //$NON-NLS-1$ 2116 } 2117 } 2118 /** 2119 * Checks that this AST operation is not used when 2120 * building JLS2, JLS3, JLS4, JLS8, JLS9 or JLS10 level ASTs. 2121 * <p> 2122 * Use this method to prevent access to new properties that have been added in JLS11 2123 * </p> 2124 * 2125 * @exception UnsupportedOperationException if this operation is used below JLS11 2126 * @since 3.14 2127 */ unsupportedBelow11()2128 final void unsupportedBelow11() { 2129 if (this.ast.apiLevel < AST.JLS11_INTERNAL) { 2130 throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS11 and above"); //$NON-NLS-1$ 2131 } 2132 } 2133 2134 /** 2135 * Checks that this AST operation is not used when 2136 * building JLS2, JLS3, JLS4, JLS8, JLS9,JLS10 or JLS11 level ASTs. 2137 * <p> 2138 * Use this method to prevent access to new properties that have been added in JLS12 2139 * </p> 2140 * 2141 * @exception UnsupportedOperationException if this operation is used below JLS12 2142 * @deprecated 2143 * @since 3.16 2144 */ unsupportedBelow12()2145 final void unsupportedBelow12() { 2146 if (this.ast.apiLevel < AST.JLS12_INTERNAL) { 2147 throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS12 and above"); //$NON-NLS-1$ 2148 } 2149 } 2150 2151 /** 2152 * Checks that this AST operation is not used when 2153 * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12 or JSL13 level ASTs. 2154 * <p> 2155 * Use this method to prevent access to new properties that have been added in JLS14 2156 * </p> 2157 * 2158 * @exception UnsupportedOperationException if this operation is used below JLS14 2159 * @since 3.22 2160 */ unsupportedBelow14()2161 final void unsupportedBelow14() { 2162 if (this.ast.apiLevel < AST.JLS14_INTERNAL) { 2163 throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS14 and above"); //$NON-NLS-1$ 2164 } 2165 } 2166 2167 2168 /** 2169 * Checks that this AST operation is not used when 2170 * building ASTs without previewEnabled flag. 2171 * <p> 2172 * Use this method to prevent access to new properties that have been added with preview feature 2173 * </p> 2174 * 2175 * @exception UnsupportedOperationException if this operation is used with previewEnabled flag as false 2176 * @since 3.19 2177 */ unsupportedWithoutPreviewError()2178 final void unsupportedWithoutPreviewError() { 2179 if (!this.ast.isPreviewEnabled()) { 2180 throw new UnsupportedOperationException("Operation only supported in ASTs with previewEnabled flag as true"); //$NON-NLS-1$ 2181 } 2182 } 2183 2184 /** 2185 * Checks that this AST operation is only used when 2186 * building JLS2 level ASTs. 2187 * <p> 2188 * Use this method to prevent access to deprecated properties (deprecated in JLS3). 2189 * </p> 2190 * 2191 * @exception UnsupportedOperationException if this operation is used in an AST later than JLS2 2192 * @since 3.0 2193 */ 2194 // In API Javadocs, add: * @deprecated In the JLS3 API, this method is replaced by {@link #replacement()}. supportedOnlyIn2()2195 final void supportedOnlyIn2() { 2196 if (this.ast.apiLevel != AST.JLS2_INTERNAL) { 2197 throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$ 2198 } 2199 } 2200 2201 /** 2202 * Checks that this AST operation is only used when 2203 * building JLS2, JLS3 or JLS4 level ASTs. 2204 * <p> 2205 * Use this method to prevent access to deprecated properties (deprecated in JLS8). 2206 * </p> 2207 * 2208 * @exception UnsupportedOperationException if this operation is used in an AST later than JLS4 2209 * @since 3.10 2210 */ 2211 // In API Javadocs, add: * @deprecated In the JLS8 API, this method is replaced by {@link #replacement()}. supportedOnlyIn2_3_4()2212 final void supportedOnlyIn2_3_4() { 2213 if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { 2214 throw new UnsupportedOperationException("Operation only supported in JLS2, JLS3 and JLS4 ASTs"); //$NON-NLS-1$ 2215 } 2216 } 2217 2218 /** 2219 * Checks that this AST operation is only used when 2220 * building JLS12 level ASTs. 2221 * <p> 2222 * Use this method to prevent access to properties available only in JLS12. 2223 * </p> 2224 * 2225 * @exception UnsupportedOperationException if this operation is is not used in JLS12 2226 * @since 3.20 2227 */ 2228 // In API Javadocs, add: * @deprecated In the JLS13 API, this method is replaced by {@link #replacement()}. supportedOnlyIn12()2229 final void supportedOnlyIn12() { 2230 if (this.ast.apiLevel != AST.JLS12_INTERNAL) { 2231 throw new UnsupportedOperationException("Operation only supported in JLS12 AST"); //$NON-NLS-1$ 2232 } 2233 } 2234 2235 /** 2236 * Checks that this AST operation is only used when 2237 * building JLS13 level ASTs. 2238 * <p> 2239 * Use this method to prevent access to new properties available only in JLS13. 2240 * </p> 2241 * 2242 * @exception UnsupportedOperationException if this operation is not used in JLS13 2243 * @since 3.20 2244 */ supportedOnlyIn13()2245 final void supportedOnlyIn13() { 2246 if (this.ast.apiLevel != AST.JLS13_INTERNAL) { 2247 throw new UnsupportedOperationException("Operation only supported in JLS13 AST"); //$NON-NLS-1$ 2248 } 2249 } 2250 2251 /** 2252 * Checks that this AST operation is only used when 2253 * building JLS13 level ASTs. 2254 * <p> 2255 * Use this method to prevent access to new properties available only in JLS14. 2256 * </p> 2257 * 2258 * @exception UnsupportedOperationException if this operation is not used in JLS14 2259 * @since 3.20 2260 */ supportedOnlyIn14()2261 final void supportedOnlyIn14() { 2262 if (this.ast.apiLevel != AST.JLS14_INTERNAL) { 2263 throw new UnsupportedOperationException("Operation only supported in JLS14 AST"); //$NON-NLS-1$ 2264 } 2265 } 2266 /** 2267 * Sets or clears this node's parent node and location. 2268 * <p> 2269 * Note that this method is package-private. The pointer from a node 2270 * to its parent is set implicitly as a side effect of inserting or 2271 * removing the node as a child of another node. This method calls 2272 * <code>ast.modifying()</code>. 2273 * </p> 2274 * 2275 * @param parent the new parent of this node, or <code>null</code> if none 2276 * @param property the location of this node in its parent, 2277 * or <code>null</code> if <code>parent</code> is <code>null</code> 2278 * @see #getLocationInParent 2279 * @see #getParent 2280 * @since 3.0 2281 */ setParent(ASTNode parent, StructuralPropertyDescriptor property)2282 final void setParent(ASTNode parent, StructuralPropertyDescriptor property) { 2283 this.ast.modifying(); 2284 this.parent = parent; 2285 this.location = property; 2286 } 2287 2288 /** 2289 * Removes this node from its parent. Has no effect if this node 2290 * is unparented. If this node appears as an element of a child list 2291 * property of its parent, then this node is removed from the 2292 * list using <code>List.remove</code>. 2293 * If this node appears as the value of a child property of its 2294 * parent, then this node is detached from its parent 2295 * by passing <code>null</code> to the appropriate setter method; 2296 * this operation fails if this node is in a mandatory property. 2297 * 2298 * @since 3.0 2299 */ delete()2300 public final void delete() { 2301 StructuralPropertyDescriptor p = getLocationInParent(); 2302 if (p == null) { 2303 // node is unparented 2304 return; 2305 } 2306 if (p.isChildProperty()) { 2307 getParent().setStructuralProperty(this.location, null); 2308 return; 2309 } 2310 if (p.isChildListProperty()) { 2311 List l = (List) getParent().getStructuralProperty(this.location); 2312 l.remove(this); 2313 } 2314 } 2315 2316 /** 2317 * Checks whether the given new child node is a node 2318 * in a different AST from its parent-to-be, whether it is 2319 * already has a parent, whether adding it to its 2320 * parent-to-be would create a cycle, and whether the child is of 2321 * the right type. The parent-to-be is the enclosing instance. 2322 * 2323 * @param node the parent-to-be node 2324 * @param newChild the new child of the parent 2325 * @param cycleCheck <code>true</code> if cycles are possible and need 2326 * to be checked, <code>false</code> if cycles are impossible and do 2327 * not need to be checked 2328 * @param nodeType a type constraint on child nodes, or <code>null</code> 2329 * if no special check is required 2330 * @exception IllegalArgumentException if: 2331 * <ul> 2332 * <li>the child is null</li> 2333 * <li>the node belongs to a different AST</li> 2334 * <li>the child has the incorrect node type</li> 2335 * <li>the node already has a parent</li> 2336 * <li>a cycle in would be created</li> 2337 * </ul> 2338 */ checkNewChild(ASTNode node, ASTNode newChild, boolean cycleCheck, Class nodeType)2339 static void checkNewChild(ASTNode node, ASTNode newChild, 2340 boolean cycleCheck, Class nodeType) { 2341 if (newChild.ast != node.ast) { 2342 // new child is from a different AST 2343 throw new IllegalArgumentException(); 2344 } 2345 if (newChild.getParent() != null) { 2346 // new child currently has a different parent 2347 throw new IllegalArgumentException(); 2348 } 2349 if (cycleCheck && newChild == node.getRoot()) { 2350 // inserting new child would create a cycle 2351 throw new IllegalArgumentException(); 2352 } 2353 Class childClass = newChild.getClass(); 2354 if (nodeType != null && !nodeType.isAssignableFrom(childClass)) { 2355 // new child is not of the right type 2356 throw new ClassCastException(childClass + " is not an instance of " + nodeType); //$NON-NLS-1$ 2357 } 2358 if ((newChild.typeAndFlags & PROTECT) != 0) { 2359 // new child node is protected => cannot be parented 2360 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 2361 } 2362 } 2363 2364 /** 2365 * Prelude portion of the "3 step program" for replacing the 2366 * old child of this node with another node. 2367 * Here is the code pattern found in all AST node subclasses: 2368 * <pre> 2369 * ASTNode oldChild = this.foo; 2370 * preReplaceChild(oldChild, newFoo, FOO_PROPERTY); 2371 * this.foo = newFoo; 2372 * postReplaceChild(oldChild, newFoo, FOO_PROPERTY); 2373 * </pre> 2374 * The first part (preReplaceChild) does all the precondition checks, 2375 * reports pre-delete events, and changes parent links. 2376 * The old child is delinked from its parent (making it a root node), 2377 * and the new child node is linked to its parent. The new child node 2378 * must be a root node in the same AST as its new parent, and must not 2379 * be an ancestor of this node. All three nodes must be 2380 * modifiable (not PROTECTED). The replace operation must fail 2381 * atomically; so it is crucial that all precondition checks 2382 * be done before any linking and delinking happens. 2383 * The final part (postReplaceChild )reports post-add events. 2384 * <p> 2385 * This method calls <code>ast.modifying()</code> for the nodes affected. 2386 * </p> 2387 * 2388 * @param oldChild the old child of this node, or <code>null</code> if 2389 * there was no old child to replace 2390 * @param newChild the new child of this node, or <code>null</code> if 2391 * there is no replacement child 2392 * @param property the property descriptor of this node describing 2393 * the relationship between node and child 2394 * @exception RuntimeException if: 2395 * <ul> 2396 * <li>the node belongs to a different AST</li> 2397 * <li>the node already has a parent</li> 2398 * <li>a cycle in would be created</li> 2399 * <li>any of the nodes involved are unmodifiable</li> 2400 * </ul> 2401 * @since 3.0 2402 */ preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property)2403 final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) { 2404 if ((this.typeAndFlags & PROTECT) != 0) { 2405 // this node is protected => cannot gain or lose children 2406 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 2407 } 2408 if (newChild != null) { 2409 checkNewChild(this, newChild, property.cycleRisk, null); 2410 } 2411 // delink old child from parent 2412 if (oldChild != null) { 2413 if ((oldChild.typeAndFlags & PROTECT) != 0) { 2414 // old child node is protected => cannot be unparented 2415 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 2416 } 2417 if (newChild != null) { 2418 this.ast.preReplaceChildEvent(this, oldChild, newChild, property); 2419 } else { 2420 this.ast.preRemoveChildEvent(this, oldChild, property); 2421 } 2422 oldChild.setParent(null, null); 2423 } else { 2424 if(newChild != null) { 2425 this.ast.preAddChildEvent(this, newChild, property); 2426 } 2427 } 2428 // link new child to parent 2429 if (newChild != null) { 2430 newChild.setParent(this, property); 2431 // cannot notify postAddChildEvent until parent is linked to child too 2432 } 2433 } 2434 2435 /** 2436 * Postlude portion of the "3 step program" for replacing the 2437 * old child of this node with another node. 2438 * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)} 2439 * for details. 2440 * @since 3.0 2441 */ postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property)2442 final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) { 2443 // link new child to parent 2444 if (newChild != null) { 2445 if (oldChild != null) { 2446 this.ast.postReplaceChildEvent(this, oldChild, newChild, property); 2447 } else { 2448 this.ast.postAddChildEvent(this, newChild, property); 2449 } 2450 } else { 2451 this.ast.postRemoveChildEvent(this, oldChild, property); 2452 } 2453 } 2454 2455 /** 2456 * Prelude portion of the "3 step program" for changing the 2457 * value of a simple property of this node. 2458 * Here is the code pattern found in all AST node subclasses: 2459 * <pre> 2460 * preValueChange(FOO_PROPERTY); 2461 * this.foo = newFoo; 2462 * postValueChange(FOO_PROPERTY); 2463 * </pre> 2464 * The first part (preValueChange) does the precondition check 2465 * to make sure the node is modifiable (not PROTECTED). 2466 * The change operation must fail atomically; so it is crucial 2467 * that the precondition checks are done before the field is 2468 * hammered. The final part (postValueChange)reports post-change 2469 * events. 2470 * <p> 2471 * This method calls <code>ast.modifying()</code> for the node affected. 2472 * </p> 2473 * 2474 * @param property the property descriptor of this node 2475 * @exception RuntimeException if: 2476 * <ul> 2477 * <li>this node is unmodifiable</li> 2478 * </ul> 2479 * @since 3.0 2480 */ preValueChange(SimplePropertyDescriptor property)2481 final void preValueChange(SimplePropertyDescriptor property) { 2482 if ((this.typeAndFlags & PROTECT) != 0) { 2483 // this node is protected => cannot change value of properties 2484 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 2485 } 2486 this.ast.preValueChangeEvent(this, property); 2487 this.ast.modifying(); 2488 } 2489 2490 /** 2491 * Postlude portion of the "3 step program" for replacing the 2492 * old child of this node with another node. 2493 * See {@link #preValueChange(SimplePropertyDescriptor)} for details. 2494 * @since 3.0 2495 */ postValueChange(SimplePropertyDescriptor property)2496 final void postValueChange(SimplePropertyDescriptor property) { 2497 this.ast.postValueChangeEvent(this, property); 2498 } 2499 2500 /** 2501 * Ensures that this node is modifiable (that is, not marked PROTECTED). 2502 * If successful, calls ast.modifying(). 2503 * @exception RuntimeException is not modifiable 2504 */ checkModifiable()2505 final void checkModifiable() { 2506 if ((this.typeAndFlags & PROTECT) != 0) { 2507 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ 2508 } 2509 this.ast.modifying(); 2510 } 2511 2512 /** 2513 * Begin lazy initialization of this node. 2514 * Here is the code pattern found in all AST 2515 * node subclasses: 2516 * <pre> 2517 * if (this.foo == null) { 2518 * // lazy init must be thread-safe for readers 2519 * synchronized (this) { 2520 * if (this.foo == null) { 2521 * preLazyInit(); 2522 * this.foo = ...; // code to create new node 2523 * postLazyInit(this.foo, FOO_PROPERTY); 2524 * } 2525 * } 2526 * } 2527 * </pre> 2528 * @since 3.0 2529 */ preLazyInit()2530 final void preLazyInit() { 2531 // IMPORTANT: this method is called by readers 2532 // ASTNode.this is locked at this point 2533 this.ast.disableEvents(); 2534 // will turn events back on in postLasyInit 2535 } 2536 2537 /** 2538 * End lazy initialization of this node. 2539 * 2540 * @param newChild the new child of this node, or <code>null</code> if 2541 * there is no replacement child 2542 * @param property the property descriptor of this node describing 2543 * the relationship between node and child 2544 * @since 3.0 2545 */ postLazyInit(ASTNode newChild, ChildPropertyDescriptor property)2546 final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) { 2547 // IMPORTANT: this method is called by readers 2548 // ASTNode.this is locked at this point 2549 // newChild is brand new (so no chance of concurrent access) 2550 newChild.setParent(this, property); 2551 // turn events back on (they were turned off in corresponding preLazyInit) 2552 this.ast.reenableEvents(); 2553 } 2554 2555 /** 2556 * Returns the value of the named property of this node, or <code>null</code> if none. 2557 * 2558 * @param propertyName the property name 2559 * @return the property value, or <code>null</code> if none 2560 * @see #setProperty(String,Object) 2561 */ getProperty(String propertyName)2562 public final Object getProperty(String propertyName) { 2563 if (propertyName == null) { 2564 throw new IllegalArgumentException(); 2565 } 2566 if (this.property1 == null) { 2567 // node has no properties at all 2568 return null; 2569 } 2570 if (this.property1 instanceof String) { 2571 // node has only a single property 2572 if (propertyName.equals(this.property1)) { 2573 return this.property2; 2574 } else { 2575 return null; 2576 } 2577 } 2578 // otherwise node has table of properties 2579 Map m = (Map) this.property1; 2580 return m.get(propertyName); 2581 } 2582 2583 /** 2584 * Sets the named property of this node to the given value, 2585 * or to <code>null</code> to clear it. 2586 * <p> 2587 * Clients should employ property names that are sufficiently unique 2588 * to avoid inadvertent conflicts with other clients that might also be 2589 * setting properties on the same node. 2590 * </p> 2591 * <p> 2592 * Note that modifying a property is not considered a modification to the 2593 * AST itself. This is to allow clients to decorate existing nodes with 2594 * their own properties without jeopardizing certain things (like the 2595 * validity of bindings), which rely on the underlying tree remaining static. 2596 * </p> 2597 * 2598 * @param propertyName the property name 2599 * @param data the new property value, or <code>null</code> if none 2600 * @see #getProperty(String) 2601 * @throws IllegalArgumentException if the given property name is <code>null</code> 2602 */ setProperty(String propertyName, Object data)2603 public final void setProperty(String propertyName, Object data) { 2604 if (propertyName == null) { 2605 throw new IllegalArgumentException(); 2606 } 2607 // N.B. DO NOT CALL ast.modifying(); 2608 2609 if (this.property1 == null) { 2610 // node has no properties at all 2611 if (data == null) { 2612 // we already know this 2613 return; 2614 } 2615 // node gets its fist property 2616 this.property1 = propertyName; 2617 this.property2 = data; 2618 return; 2619 } 2620 2621 if (this.property1 instanceof String) { 2622 // node has only a single property 2623 if (propertyName.equals(this.property1)) { 2624 // we're in luck 2625 if (data == null) { 2626 // just deleted last property 2627 this.property1 = null; 2628 this.property2 = null; 2629 } else { 2630 this.property2 = data; 2631 } 2632 return; 2633 } 2634 if (data == null) { 2635 // we already know this 2636 return; 2637 } 2638 // node already has one property - getting its second 2639 // convert to more flexible representation 2640 Map m = new HashMap(3); 2641 m.put(this.property1, this.property2); 2642 m.put(propertyName, data); 2643 this.property1 = m; 2644 this.property2 = null; 2645 return; 2646 } 2647 2648 // node has two or more properties 2649 Map m = (Map) this.property1; 2650 if (data == null) { 2651 m.remove(propertyName); 2652 // check for just one property left 2653 if (m.size() == 1) { 2654 // convert to more efficient representation 2655 Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]); 2656 this.property1 = entries[0].getKey(); 2657 this.property2 = entries[0].getValue(); 2658 } 2659 return; 2660 } else { 2661 m.put(propertyName, data); 2662 // still has two or more properties 2663 return; 2664 } 2665 } 2666 2667 /** 2668 * Returns an unmodifiable table of the properties of this node with 2669 * non-<code>null</code> values. 2670 * 2671 * @return the table of property values keyed by property name 2672 * (key type: <code>String</code>; value type: <code>Object</code>) 2673 */ properties()2674 public final Map properties() { 2675 if (this.property1 == null) { 2676 // node has no properties at all 2677 return UNMODIFIABLE_EMPTY_MAP; 2678 } 2679 if (this.property1 instanceof String) { 2680 // node has a single property 2681 return Collections.singletonMap(this.property1, this.property2); 2682 } 2683 2684 // node has two or more properties 2685 if (this.property2 == null) { 2686 this.property2 = Collections.unmodifiableMap((Map) this.property1); 2687 } 2688 // property2 is unmodifiable wrapper for map in property1 2689 return (Map) this.property2; 2690 } 2691 2692 /** 2693 * Returns the flags associated with this node. 2694 * <p> 2695 * No flags are associated with newly created nodes. 2696 * </p> 2697 * <p> 2698 * The flags are the bitwise-or of individual flags. 2699 * The following flags are currently defined: 2700 * <ul> 2701 * <li>{@link #MALFORMED} - indicates node is syntactically 2702 * malformed</li> 2703 * <li>{@link #ORIGINAL} - indicates original node 2704 * created by ASTParser</li> 2705 * <li>{@link #PROTECT} - indicates node is protected 2706 * from further modification</li> 2707 * <li>{@link #RECOVERED} - indicates node or a part of this node 2708 * is recovered from source that contains a syntax error</li> 2709 * </ul> 2710 * Other bit positions are reserved for future use. 2711 * 2712 * @return the bitwise-or of individual flags 2713 * @see #setFlags(int) 2714 */ getFlags()2715 public final int getFlags() { 2716 return this.typeAndFlags & 0xFFFF; 2717 } 2718 2719 /** 2720 * Sets the flags associated with this node to the given value. 2721 * <p> 2722 * The flags are the bitwise-or of individual flags. 2723 * The following flags are currently defined: 2724 * <ul> 2725 * <li>{@link #MALFORMED} - indicates node is syntactically 2726 * malformed</li> 2727 * <li>{@link #ORIGINAL} - indicates original node 2728 * created by ASTParser</li> 2729 * <li>{@link #PROTECT} - indicates node is protected 2730 * from further modification</li> 2731 * <li>{@link #RECOVERED} - indicates node or a part of this node 2732 * is recovered from source that contains a syntax error</li> 2733 * </ul> 2734 * Other bit positions are reserved for future use. 2735 * <p> 2736 * Note that the flags are <em>not</em> considered a structural 2737 * property of the node, and can be changed even if the 2738 * node is marked as protected. 2739 * </p> 2740 * 2741 * @param flags the bitwise-or of individual flags 2742 * @see #getFlags() 2743 */ setFlags(int flags)2744 public final void setFlags(int flags) { 2745 this.ast.modifying(); 2746 int old = this.typeAndFlags & 0xFFFF0000; 2747 this.typeAndFlags = old | (flags & 0xFFFF); 2748 } 2749 2750 /** 2751 * Returns an integer value identifying the type of this concrete AST node. 2752 * The values are small positive integers, suitable for use in switch statements. 2753 * <p> 2754 * For each concrete node type there is a unique node type constant (name 2755 * and value). The unique node type constant for a concrete node type such as 2756 * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>. 2757 * </p> 2758 * 2759 * @return one of the node type constants 2760 */ getNodeType()2761 public final int getNodeType() { 2762 return this.typeAndFlags >>> 16; 2763 } 2764 2765 /** 2766 * Sets the integer value identifying the type of this concrete AST node. 2767 * The values are small positive integers, suitable for use in switch statements. 2768 * 2769 * @param nodeType one of the node type constants 2770 */ setNodeType(int nodeType)2771 private void setNodeType(int nodeType) { 2772 int old = this.typeAndFlags & 0xFFFF0000; 2773 this.typeAndFlags = old | (nodeType << 16); 2774 } 2775 2776 /** 2777 * Returns an integer value identifying the type of this concrete AST node. 2778 * <p> 2779 * This internal method is implemented in each of the 2780 * concrete node subclasses. 2781 * </p> 2782 * 2783 * @return one of the node type constants 2784 */ getNodeType0()2785 abstract int getNodeType0(); 2786 2787 /** 2788 * The <code>ASTNode</code> implementation of this <code>Object</code> 2789 * method uses object identity (==). Use <code>subtreeMatch</code> to 2790 * compare two subtrees for equality. 2791 * 2792 * @param obj {@inheritDoc} 2793 * @return {@inheritDoc} 2794 * @see #subtreeMatch(ASTMatcher matcher, Object other) 2795 */ 2796 @Override equals(Object obj)2797 public final boolean equals(Object obj) { 2798 return this == obj; // equivalent to Object.equals 2799 } 2800 2801 /* 2802 * (non-Javadoc) 2803 * This makes it consistent with the fact that a equals methods has been provided. 2804 * @see java.lang.Object#hashCode() 2805 */ 2806 @Override hashCode()2807 public final int hashCode() { 2808 return super.hashCode(); 2809 } 2810 2811 /** 2812 * Returns whether the subtree rooted at the given node matches the 2813 * given other object as decided by the given matcher. 2814 * 2815 * @param matcher the matcher 2816 * @param other the other object, or <code>null</code> 2817 * @return <code>true</code> if the subtree matches, or 2818 * <code>false</code> if they do not match 2819 */ subtreeMatch(ASTMatcher matcher, Object other)2820 public final boolean subtreeMatch(ASTMatcher matcher, Object other) { 2821 return subtreeMatch0(matcher, other); 2822 } 2823 2824 /** 2825 * Returns whether the subtree rooted at the given node matches the 2826 * given other object as decided by the given matcher. 2827 * <p> 2828 * This internal method is implemented in each of the 2829 * concrete node subclasses. 2830 * </p> 2831 * 2832 * @param matcher the matcher 2833 * @param other the other object, or <code>null</code> 2834 * @return <code>true</code> if the subtree matches, or 2835 * <code>false</code> if they do not match 2836 */ subtreeMatch0(ASTMatcher matcher, Object other)2837 abstract boolean subtreeMatch0(ASTMatcher matcher, Object other); 2838 2839 /** 2840 * Returns a deep copy of the subtree of AST nodes rooted at the 2841 * given node. The resulting nodes are owned by the given AST, 2842 * which may be different from the ASTs of the given node. 2843 * Even if the given node has a parent, the result node will be unparented. 2844 * <p> 2845 * Source range information on the original nodes is automatically copied to the new 2846 * nodes. Client properties (<code>properties</code>) are not carried over. 2847 * </p> 2848 * <p> 2849 * The node's <code>AST</code> and the target <code>AST</code> must support 2850 * the same API level. 2851 * </p> 2852 * 2853 * @param target the AST that is to own the nodes in the result 2854 * @param node the node to copy, or <code>null</code> if none 2855 * @return the copied node, or <code>null</code> if <code>node</code> 2856 * is <code>null</code> 2857 */ copySubtree(AST target, ASTNode node)2858 public static ASTNode copySubtree(AST target, ASTNode node) { 2859 if (node == null) { 2860 return null; 2861 } 2862 if (target == null) { 2863 throw new IllegalArgumentException(); 2864 } 2865 if (target.apiLevel() != node.getAST().apiLevel()) { 2866 throw new UnsupportedOperationException(); 2867 } 2868 ASTNode newNode = node.clone(target); 2869 return newNode; 2870 } 2871 2872 /** 2873 * Returns a deep copy of the subtrees of AST nodes rooted at the 2874 * given list of nodes. The resulting nodes are owned by the given AST, 2875 * which may be different from the ASTs of the nodes in the list. 2876 * Even if the nodes in the list have parents, the nodes in the result 2877 * will be unparented. 2878 * <p> 2879 * Source range information on the original nodes is automatically copied to the new 2880 * nodes. Client properties (<code>properties</code>) are not carried over. 2881 * </p> 2882 * 2883 * @param target the AST that is to own the nodes in the result 2884 * @param nodes the list of nodes to copy 2885 * (element type: {@link ASTNode}) 2886 * @return the list of copied subtrees 2887 * (element type: {@link ASTNode}) 2888 */ copySubtrees(AST target, List nodes)2889 public static List copySubtrees(AST target, List nodes) { 2890 List result = new ArrayList(nodes.size()); 2891 for (Iterator it = nodes.iterator(); it.hasNext(); ) { 2892 ASTNode oldNode = (ASTNode) it.next(); 2893 ASTNode newNode = oldNode.clone(target); 2894 result.add(newNode); 2895 } 2896 return result; 2897 } 2898 2899 /** 2900 * Returns a deep copy of the subtree of AST nodes rooted at this node. 2901 * The resulting nodes are owned by the given AST, which may be different 2902 * from the AST of this node. Even if this node has a parent, the 2903 * result node will be unparented. 2904 * <p> 2905 * This method reports pre- and post-clone events, and dispatches 2906 * to <code>clone0(AST)</code> which is reimplemented in node subclasses. 2907 * </p> 2908 * 2909 * @param target the AST that is to own the nodes in the result 2910 * @return the root node of the copies subtree 2911 */ clone(AST target)2912 final ASTNode clone(AST target) { 2913 this.ast.preCloneNodeEvent(this); 2914 ASTNode c = clone0(target); 2915 this.ast.postCloneNodeEvent(this, c); 2916 return c; 2917 } 2918 2919 /** 2920 * Returns a deep copy of the subtree of AST nodes rooted at this node. 2921 * The resulting nodes are owned by the given AST, which may be different 2922 * from the AST of this node. Even if this node has a parent, the 2923 * result node will be unparented. 2924 * <p> 2925 * This method must be implemented in subclasses. 2926 * </p> 2927 * <p> 2928 * General template for implementation on each concrete ASTNode class: 2929 * <pre> 2930 * <code> 2931 * ConcreteNodeType result = new ConcreteNodeType(target); 2932 * result.setSourceRange(getStartPosition(), getLength()); 2933 * result.setChildProperty( 2934 * (ChildPropertyType) ASTNode.copySubtree(target, getChildProperty())); 2935 * result.setSimpleProperty(isSimpleProperty()); 2936 * result.childrenProperty().addAll( 2937 * ASTNode.copySubtrees(target, childrenProperty())); 2938 * return result; 2939 * </code> 2940 * </pre> 2941 * </p> 2942 * <p> 2943 * This method does not report pre- and post-clone events. 2944 * All callers should instead call <code>clone(AST)</code> 2945 * to ensure that pre- and post-clone events are reported. 2946 * </p> 2947 * <p> 2948 * N.B. This method is package-private, so that the implementations 2949 * of this method in each of the concrete AST node types do not 2950 * clutter up the API doc. 2951 * </p> 2952 * 2953 * @param target the AST that is to own the nodes in the result 2954 * @return the root node of the copies subtree 2955 */ clone0(AST target)2956 abstract ASTNode clone0(AST target); 2957 2958 /** 2959 * Accepts the given visitor on a visit of the current node. 2960 * 2961 * @param visitor the visitor object 2962 * @exception IllegalArgumentException if the visitor is null 2963 */ accept(ASTVisitor visitor)2964 public final void accept(ASTVisitor visitor) { 2965 if (visitor == null) { 2966 throw new IllegalArgumentException(); 2967 } 2968 // begin with the generic pre-visit 2969 if (visitor.preVisit2(this)) { 2970 // dynamic dispatch to internal method for type-specific visit/endVisit 2971 accept0(visitor); 2972 } 2973 // end with the generic post-visit 2974 visitor.postVisit(this); 2975 } 2976 2977 /** 2978 * Accepts the given visitor on a type-specific visit of the current node. 2979 * This method must be implemented in all concrete AST node types. 2980 * <p> 2981 * General template for implementation on each concrete ASTNode class: 2982 * <pre> 2983 * <code> 2984 * boolean visitChildren = visitor.visit(this); 2985 * if (visitChildren) { 2986 * // visit children in normal left to right reading order 2987 * acceptChild(visitor, getProperty1()); 2988 * acceptChildren(visitor, this.rawListProperty); 2989 * acceptChild(visitor, getProperty2()); 2990 * } 2991 * visitor.endVisit(this); 2992 * </code> 2993 * </pre> 2994 * Note that the caller (<code>accept</code>) take cares of invoking 2995 * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>. 2996 * </p> 2997 * 2998 * @param visitor the visitor object 2999 */ accept0(ASTVisitor visitor)3000 abstract void accept0(ASTVisitor visitor); 3001 3002 /** 3003 * Accepts the given visitor on a visit of the current node. 3004 * <p> 3005 * This method should be used by the concrete implementations of 3006 * <code>accept0</code> to traverse optional properties. Equivalent 3007 * to <code>child.accept(visitor)</code> if <code>child</code> 3008 * is not <code>null</code>. 3009 * </p> 3010 * 3011 * @param visitor the visitor object 3012 * @param child the child AST node to dispatch too, or <code>null</code> 3013 * if none 3014 */ acceptChild(ASTVisitor visitor, ASTNode child)3015 final void acceptChild(ASTVisitor visitor, ASTNode child) { 3016 if (child == null) { 3017 return; 3018 } 3019 child.accept(visitor); 3020 } 3021 3022 /** 3023 * Accepts the given visitor on a visit of the given live list of 3024 * child nodes. 3025 * <p> 3026 * This method must be used by the concrete implementations of 3027 * <code>accept</code> to traverse list-values properties; it 3028 * encapsulates the proper handling of on-the-fly changes to the list. 3029 * </p> 3030 * 3031 * @param visitor the visitor object 3032 * @param children the child AST node to dispatch too, or <code>null</code> 3033 * if none 3034 */ acceptChildren(ASTVisitor visitor, ASTNode.NodeList children)3035 final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) { 3036 // use a cursor to keep track of where we are up to 3037 // (the list may be changing under foot) 3038 NodeList.Cursor cursor = children.newCursor(); 3039 try { 3040 while (cursor.hasNext()) { 3041 ASTNode child = (ASTNode) cursor.next(); 3042 child.accept(visitor); 3043 } 3044 } finally { 3045 children.releaseCursor(cursor); 3046 } 3047 } 3048 3049 /** 3050 * Returns the character index into the original source file indicating 3051 * where the source fragment corresponding to this node begins. 3052 * <p> 3053 * The parser supplies useful well-defined source ranges to the nodes it creates. 3054 * See {@link ASTParser#setKind(int)} for details 3055 * on precisely where source ranges begin and end. 3056 * </p> 3057 * 3058 * @return the 0-based character index, or <code>-1</code> 3059 * if no source position information is recorded for this node 3060 * @see #getLength() 3061 * @see ASTParser 3062 */ getStartPosition()3063 public final int getStartPosition() { 3064 return this.startPosition; 3065 } 3066 3067 /** 3068 * Returns the length in characters of the original source file indicating 3069 * where the source fragment corresponding to this node ends. 3070 * <p> 3071 * The parser supplies useful well-defined source ranges to the nodes it creates. 3072 * See {@link ASTParser#setKind(int)} methods for details 3073 * on precisely where source ranges begin and end. 3074 * </p> 3075 * 3076 * @return a (possibly 0) length, or <code>0</code> 3077 * if no source position information is recorded for this node 3078 * @see #getStartPosition() 3079 * @see ASTParser 3080 */ getLength()3081 public final int getLength() { 3082 return this.length; 3083 } 3084 3085 /** 3086 * Sets the source range of the original source file where the source 3087 * fragment corresponding to this node was found. 3088 * <p> 3089 * See {@link ASTParser#setKind(int)} for details 3090 * on precisely where source ranges are supposed to begin and end. 3091 * </p> 3092 * 3093 * @param startPosition a 0-based character index, 3094 * or <code>-1</code> if no source position information is 3095 * available for this node 3096 * @param length a (possibly 0) length, 3097 * or <code>0</code> if no source position information is recorded 3098 * for this node 3099 * @see #getStartPosition() 3100 * @see #getLength() 3101 * @see ASTParser 3102 */ setSourceRange(int startPosition, int length)3103 public final void setSourceRange(int startPosition, int length) { 3104 if (startPosition >= 0 && length < 0) { 3105 throw new IllegalArgumentException(); 3106 } 3107 if (startPosition < 0 && length != 0) { 3108 throw new IllegalArgumentException(); 3109 } 3110 // source positions are not considered a structural property 3111 // but we protect them nevertheless 3112 checkModifiable(); 3113 this.startPosition = startPosition; 3114 this.length = length; 3115 } 3116 3117 /** 3118 * Returns a string representation of this node suitable for debugging 3119 * purposes only. 3120 * 3121 * @return a debug string 3122 */ 3123 @Override toString()3124 public final String toString() { 3125 StringBuffer buffer = new StringBuffer(); 3126 int p = buffer.length(); 3127 try { 3128 appendDebugString(buffer); 3129 } catch (RuntimeException e) { 3130 // since debugger sometimes call toString methods, problems can easily happen when 3131 // toString is called on an instance that is being initialized 3132 buffer.setLength(p); 3133 buffer.append("!"); //$NON-NLS-1$ 3134 buffer.append(standardToString()); 3135 } 3136 return buffer.toString(); 3137 } 3138 3139 /** 3140 * Returns the string representation of this node produced by the standard 3141 * <code>Object.toString</code> method. 3142 * 3143 * @return a debug string 3144 */ standardToString()3145 final String standardToString() { 3146 return super.toString(); 3147 } 3148 3149 /** 3150 * Appends a debug representation of this node to the given string buffer. 3151 * <p> 3152 * The <code>ASTNode</code> implementation of this method prints out the entire 3153 * subtree. Subclasses may override to provide a more succinct representation. 3154 * </p> 3155 * 3156 * @param buffer the string buffer to append to 3157 */ appendDebugString(StringBuffer buffer)3158 void appendDebugString(StringBuffer buffer) { 3159 // print the subtree by default 3160 appendPrintString(buffer); 3161 } 3162 3163 /** 3164 * Appends a standard Java source code representation of this subtree to the given 3165 * string buffer. 3166 * 3167 * @param buffer the string buffer to append to 3168 */ appendPrintString(StringBuffer buffer)3169 final void appendPrintString(StringBuffer buffer) { 3170 NaiveASTFlattener printer = new NaiveASTFlattener(); 3171 accept(printer); 3172 buffer.append(printer.getResult()); 3173 } 3174 3175 /** 3176 * Estimate of size of an object header in bytes. 3177 */ 3178 static final int HEADERS = 12; 3179 3180 /** 3181 * Approximate base size of an AST node instance in bytes, 3182 * including object header and instance fields. 3183 * That is, HEADERS + (# instance vars in ASTNode)*4. 3184 */ 3185 static final int BASE_NODE_SIZE = HEADERS + 7 * 4; 3186 3187 /** 3188 * Returns an estimate of the memory footprint, in bytes, 3189 * of the given string. 3190 * 3191 * @param string the string to measure, or <code>null</code> 3192 * @return the size of this string object in bytes, or 3193 * 0 if the string is <code>null</code> 3194 * @since 3.0 3195 */ stringSize(String string)3196 static int stringSize(String string) { 3197 int size = 0; 3198 if (string != null) { 3199 // Strings usually have 4 instance fields, one of which is a char[] 3200 size += HEADERS + 4 * 4; 3201 // char[] has 2 bytes per character 3202 size += HEADERS + 2 * string.length(); 3203 } 3204 return size; 3205 } 3206 3207 /** 3208 * Returns an estimate of the memory footprint in bytes of the entire 3209 * subtree rooted at this node. 3210 * 3211 * @return the size of this subtree in bytes 3212 */ subtreeBytes()3213 public final int subtreeBytes() { 3214 return treeSize(); 3215 } 3216 3217 /** 3218 * Returns an estimate of the memory footprint in bytes of the entire 3219 * subtree rooted at this node. 3220 * <p> 3221 * N.B. This method is package-private, so that the implementations 3222 * of this method in each of the concrete AST node types do not 3223 * clutter up the API doc. 3224 * </p> 3225 * 3226 * @return the size of this subtree in bytes 3227 */ treeSize()3228 abstract int treeSize(); 3229 3230 /** 3231 * Returns an estimate of the memory footprint of this node in bytes. 3232 * The estimate does not include the space occupied by child nodes. 3233 * 3234 * @return the size of this node in bytes 3235 */ memSize()3236 abstract int memSize(); 3237 } 3238