1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.core.dom;
14 import java.util.AbstractList;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
22 import net.sourceforge.phpdt.internal.core.dom.NaiveASTFlattener;
25 * Abstract superclass of all Abstract Syntax Tree (AST) node types.
27 * An AST node represents a Java source code construct, such
28 * as a name, type, expression, statement, or declaration.
31 * Each AST node belongs to a unique AST instance, called the owning AST.
32 * The children of an AST node always have the same owner as their parent node.
33 * If a node from one AST is to be added to a different AST, the subtree must
34 * be cloned first to ensure that the added nodes have the correct owning AST.
37 * When an AST node is part of an AST, it has a unique parent node.
38 * Clients can navigate upwards, from child to parent, as well as downwards,
39 * from parent to child. Newly created nodes are unparented. When an
40 * unparented node is set as a child of a node (using a
41 * <code>set<i>CHILD</i></code> method), its parent link is set automatically
42 * and the parent link of the former child is set to <code>null</code>.
43 * For nodes with properties that include a list of children (for example,
44 * <code>Block</code> whose <code>statements</code> property is a list
45 * of statements), adding or removing an element to/for the list property
46 * automatically updates the parent links. These lists support the
47 * <code>List.set</code> method; however, the constraint that the same
48 * node cannot appear more than once means that this method cannot be used
49 * to swap elements without first removing the node.
52 * ASTs must not contain cycles. All operations that could create a cycle
53 * detect this possibility and fail.
56 * ASTs do not contain "holes" (missing subtrees). If a node is required to
57 * have a certain property, a syntactically plausible initial value is
61 * The hierarchy of AST node types has some convenient groupings marked
62 * by abstract superclasses:
64 * <li>expressions - <code>Expression</code></li>
65 * <li>names - <code>Name</code> (a sub-kind of expression)</li>
66 * <li>statements - <code>Statement</code></li>
67 * <li>types - <code>Type</code></li>
68 * <li>type body declarations - <code>BodyDeclaration</code></li>
72 * Abstract syntax trees may be hand constructed by clients, using the
73 * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to
74 * create new nodes, and the various <code>set<i>CHILD</i></code> methods
75 * to connect them together.
78 * The class {@link ASTParser} parses a string
79 * containing a Java source code and returns an abstract syntax tree
80 * for it. The resulting nodes carry source ranges relating the node back to
81 * the original source characters. The source range covers the construct
85 * Each AST node carries bit flags, which may convey additional information about
86 * the node. For instance, the parser uses a flag to indicate a syntax error.
87 * Newly created nodes have no flags set.
90 * Each AST node is capable of carrying an open-ended collection of
91 * client-defined properties. Newly created nodes have none.
92 * <code>getProperty</code> and <code>setProperty</code> are used to access
96 * AST nodes are thread-safe for readers provided there are no active writers.
97 * If one thread is modifying an AST, including creating new nodes or cloning
98 * existing ones, it is <b>not</b> safe for another thread to read, visit,
99 * write, create, or clone <em>any</em> of the nodes on the same AST.
100 * When synchronization is required, consider using the common AST
101 * object that owns the node; that is, use
102 * <code>synchronize (node.getAST()) {...}</code>.
105 * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
109 * Compilation units created by <code>ASTParser</code> from a
110 * source document can be serialized after arbitrary modifications
111 * with minimal loss of original formatting. See
112 * {@link CompilationUnit#recordModifications()} for details.
113 * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
114 * an alternative way to describe and serialize changes to a
121 * @noextend This class is not intended to be subclassed by clients.
123 public abstract class ASTNode {
125 * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
127 * There are several things that need to be changed when a
128 * new concrete AST node type (call it "FooBar"):
130 * 1. Create the FooBar AST node type class.
131 * The most effective way to do this is to copy a similar
132 * existing concrete node class to get a template that
133 * includes all the framework methods that must be implemented.
135 * 2. Add node type constant ASTNode.FOO_BAR.
136 * Node constants are numbered consecutively. Add the
137 * constant after the existing ones.
139 * 3. Add entry to ASTNode.nodeClassForType(int).
141 * 4. Add AST.newFooBar() factory method.
143 * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
145 * 6. Add ASTMatcher.match(FooBar,Object) method.
147 * 7. Ensure that SimpleName.isDeclaration() covers FooBar
150 * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
151 * how these nodes should be serialized.
153 * 9. Update the AST test suites.
155 * The next steps are to update AST.parse* to start generating
156 * the new type of nodes, and ASTRewrite to serialize them back out.
160 * Node type constant indicating a node of type
161 * <code>AnonymousClassDeclaration</code>.
162 * @see AnonymousClassDeclaration
164 public static final int ANONYMOUS_CLASS_DECLARATION = 1;
167 * Node type constant indicating a node of type
168 * <code>ArrayAccess</code>.
171 public static final int ARRAY_ACCESS = 2;
174 * Node type constant indicating a node of type
175 * <code>ArrayCreation</code>.
178 public static final int ARRAY_CREATION = 3;
181 * Node type constant indicating a node of type
182 * <code>ArrayInitializer</code>.
183 * @see ArrayInitializer
185 public static final int ARRAY_INITIALIZER = 4;
188 * Node type constant indicating a node of type
189 * <code>ArrayType</code>.
192 public static final int ARRAY_TYPE = 5;
195 * Node type constant indicating a node of type
196 * <code>AssertStatement</code>.
197 * @see AssertStatement
199 public static final int ASSERT_STATEMENT = 6;
202 * Node type constant indicating a node of type
203 * <code>Assignment</code>.
206 public static final int ASSIGNMENT = 7;
209 * Node type constant indicating a node of type
210 * <code>Block</code>.
213 public static final int BLOCK = 8;
216 * Node type constant indicating a node of type
217 * <code>BooleanLiteral</code>.
218 * @see BooleanLiteral
220 public static final int BOOLEAN_LITERAL = 9;
223 * Node type constant indicating a node of type
224 * <code>BreakStatement</code>.
225 * @see BreakStatement
227 public static final int BREAK_STATEMENT = 10;
230 * Node type constant indicating a node of type
231 * <code>CastExpression</code>.
232 * @see CastExpression
234 public static final int CAST_EXPRESSION = 11;
237 * Node type constant indicating a node of type
238 * <code>CatchClause</code>.
241 public static final int CATCH_CLAUSE = 12;
244 * Node type constant indicating a node of type
245 * <code>CharacterLiteral</code>.
246 * @see CharacterLiteral
248 public static final int CHARACTER_LITERAL = 13;
251 * Node type constant indicating a node of type
252 * <code>ClassInstanceCreation</code>.
253 * @see ClassInstanceCreation
255 public static final int CLASS_INSTANCE_CREATION = 14;
258 * Node type constant indicating a node of type
259 * <code>CompilationUnit</code>.
260 * @see CompilationUnit
262 public static final int COMPILATION_UNIT = 15;
265 * Node type constant indicating a node of type
266 * <code>ConditionalExpression</code>.
267 * @see ConditionalExpression
269 public static final int CONDITIONAL_EXPRESSION = 16;
272 * Node type constant indicating a node of type
273 * <code>ConstructorInvocation</code>.
274 * @see ConstructorInvocation
276 public static final int CONSTRUCTOR_INVOCATION = 17;
279 * Node type constant indicating a node of type
280 * <code>ContinueStatement</code>.
281 * @see ContinueStatement
283 public static final int CONTINUE_STATEMENT = 18;
286 * Node type constant indicating a node of type
287 * <code>DoStatement</code>.
290 public static final int DO_STATEMENT = 19;
293 * Node type constant indicating a node of type
294 * <code>EmptyStatement</code>.
295 * @see EmptyStatement
297 public static final int EMPTY_STATEMENT = 20;
300 * Node type constant indicating a node of type
301 * <code>ExpressionStatement</code>.
302 * @see ExpressionStatement
304 public static final int EXPRESSION_STATEMENT = 21;
307 * Node type constant indicating a node of type
308 * <code>FieldAccess</code>.
311 public static final int FIELD_ACCESS = 22;
314 * Node type constant indicating a node of type
315 * <code>FieldDeclaration</code>.
316 * @see FieldDeclaration
318 public static final int FIELD_DECLARATION = 23;
321 * Node type constant indicating a node of type
322 * <code>ForStatement</code>.
325 public static final int FOR_STATEMENT = 24;
328 * Node type constant indicating a node of type
329 * <code>IfStatement</code>.
332 public static final int IF_STATEMENT = 25;
335 * Node type constant indicating a node of type
336 * <code>ImportDeclaration</code>.
337 * @see ImportDeclaration
339 public static final int IMPORT_DECLARATION = 26;
342 * Node type constant indicating a node of type
343 * <code>InfixExpression</code>.
344 * @see InfixExpression
346 public static final int INFIX_EXPRESSION = 27;
349 * Node type constant indicating a node of type
350 * <code>Initializer</code>.
353 public static final int INITIALIZER = 28;
356 * Node type constant indicating a node of type
357 * <code>Javadoc</code>.
360 public static final int JAVADOC = 29;
363 * Node type constant indicating a node of type
364 * <code>LabeledStatement</code>.
365 * @see LabeledStatement
367 public static final int LABELED_STATEMENT = 30;
370 * Node type constant indicating a node of type
371 * <code>MethodDeclaration</code>.
372 * @see MethodDeclaration
374 public static final int METHOD_DECLARATION = 31;
377 * Node type constant indicating a node of type
378 * <code>MethodInvocation</code>.
379 * @see MethodInvocation
381 public static final int METHOD_INVOCATION = 32;
384 * Node type constant indicating a node of type
385 * <code>NullLiteral</code>.
388 public static final int NULL_LITERAL = 33;
391 * Node type constant indicating a node of type
392 * <code>NumberLiteral</code>.
395 public static final int NUMBER_LITERAL = 34;
398 * Node type constant indicating a node of type
399 * <code>PackageDeclaration</code>.
400 * @see PackageDeclaration
402 public static final int PACKAGE_DECLARATION = 35;
405 * Node type constant indicating a node of type
406 * <code>ParenthesizedExpression</code>.
407 * @see ParenthesizedExpression
409 public static final int PARENTHESIZED_EXPRESSION = 36;
412 * Node type constant indicating a node of type
413 * <code>PostfixExpression</code>.
414 * @see PostfixExpression
416 public static final int POSTFIX_EXPRESSION = 37;
419 * Node type constant indicating a node of type
420 * <code>PrefixExpression</code>.
421 * @see PrefixExpression
423 public static final int PREFIX_EXPRESSION = 38;
426 * Node type constant indicating a node of type
427 * <code>PrimitiveType</code>.
430 public static final int PRIMITIVE_TYPE = 39;
433 * Node type constant indicating a node of type
434 * <code>QualifiedName</code>.
437 public static final int QUALIFIED_NAME = 40;
440 * Node type constant indicating a node of type
441 * <code>ReturnStatement</code>.
442 * @see ReturnStatement
444 public static final int RETURN_STATEMENT = 41;
447 * Node type constant indicating a node of type
448 * <code>SimpleName</code>.
451 public static final int SIMPLE_NAME = 42;
454 * Node type constant indicating a node of type
455 * <code>SimpleType</code>.
458 public static final int SIMPLE_TYPE = 43;
461 * Node type constant indicating a node of type
462 * <code>SingleVariableDeclaration</code>.
463 * @see SingleVariableDeclaration
465 public static final int SINGLE_VARIABLE_DECLARATION = 44;
468 * Node type constant indicating a node of type
469 * <code>StringLiteral</code>.
472 public static final int STRING_LITERAL = 45;
475 * Node type constant indicating a node of type
476 * <code>SuperConstructorInvocation</code>.
477 * @see SuperConstructorInvocation
479 public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
482 * Node type constant indicating a node of type
483 * <code>SuperFieldAccess</code>.
484 * @see SuperFieldAccess
486 public static final int SUPER_FIELD_ACCESS = 47;
489 * Node type constant indicating a node of type
490 * <code>SuperMethodInvocation</code>.
491 * @see SuperMethodInvocation
493 public static final int SUPER_METHOD_INVOCATION = 48;
496 * Node type constant indicating a node of type
497 * <code>SwitchCase</code>.
500 public static final int SWITCH_CASE = 49;
503 * Node type constant indicating a node of type
504 * <code>SwitchStatement</code>.
505 * @see SwitchStatement
507 public static final int SWITCH_STATEMENT = 50;
510 * Node type constant indicating a node of type
511 * <code>SynchronizedStatement</code>.
512 * @see SynchronizedStatement
514 public static final int SYNCHRONIZED_STATEMENT = 51;
517 * Node type constant indicating a node of type
518 * <code>ThisExpression</code>.
519 * @see ThisExpression
521 public static final int THIS_EXPRESSION = 52;
524 * Node type constant indicating a node of type
525 * <code>ThrowStatement</code>.
526 * @see ThrowStatement
528 public static final int THROW_STATEMENT = 53;
531 * Node type constant indicating a node of type
532 * <code>TryStatement</code>.
535 public static final int TRY_STATEMENT = 54;
538 * Node type constant indicating a node of type
539 * <code>TypeDeclaration</code>.
540 * @see TypeDeclaration
542 public static final int TYPE_DECLARATION = 55;
545 * Node type constant indicating a node of type
546 * <code>TypeDeclarationStatement</code>.
547 * @see TypeDeclarationStatement
549 public static final int TYPE_DECLARATION_STATEMENT = 56;
552 * Node type constant indicating a node of type
553 * <code>TypeLiteral</code>.
556 public static final int TYPE_LITERAL = 57;
559 * Node type constant indicating a node of type
560 * <code>VariableDeclarationExpression</code>.
561 * @see VariableDeclarationExpression
563 public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
566 * Node type constant indicating a node of type
567 * <code>VariableDeclarationFragment</code>.
568 * @see VariableDeclarationFragment
570 public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
573 * Node type constant indicating a node of type
574 * <code>VariableDeclarationStatement</code>.
575 * @see VariableDeclarationStatement
577 public static final int VARIABLE_DECLARATION_STATEMENT = 60;
580 * Node type constant indicating a node of type
581 * <code>WhileStatement</code>.
582 * @see WhileStatement
584 public static final int WHILE_STATEMENT = 61;
587 * Node type constant indicating a node of type
588 * <code>InstanceofExpression</code>.
589 * @see InstanceofExpression
591 public static final int INSTANCEOF_EXPRESSION = 62;
594 * Node type constant indicating a node of type
595 * <code>LineComment</code>.
599 public static final int LINE_COMMENT = 63;
602 * Node type constant indicating a node of type
603 * <code>BlockComment</code>.
607 public static final int BLOCK_COMMENT = 64;
610 * Node type constant indicating a node of type
611 * <code>TagElement</code>.
615 public static final int TAG_ELEMENT = 65;
618 * Node type constant indicating a node of type
619 * <code>TextElement</code>.
623 public static final int TEXT_ELEMENT = 66;
626 * Node type constant indicating a node of type
627 * <code>MemberRef</code>.
631 public static final int MEMBER_REF = 67;
634 * Node type constant indicating a node of type
635 * <code>MethodRef</code>.
639 public static final int METHOD_REF = 68;
642 * Node type constant indicating a node of type
643 * <code>MethodRefParameter</code>.
644 * @see MethodRefParameter
647 public static final int METHOD_REF_PARAMETER = 69;
650 * Node type constant indicating a node of type
651 * <code>EnhancedForStatement</code>.
652 * @see EnhancedForStatement
655 public static final int ENHANCED_FOR_STATEMENT = 70;
658 * Node type constant indicating a node of type
659 * <code>EnumDeclaration</code>.
660 * @see EnumDeclaration
663 public static final int ENUM_DECLARATION = 71;
666 * Node type constant indicating a node of type
667 * <code>EnumConstantDeclaration</code>.
668 * @see EnumConstantDeclaration
671 public static final int ENUM_CONSTANT_DECLARATION = 72;
674 * Node type constant indicating a node of type
675 * <code>TypeParameter</code>.
679 public static final int TYPE_PARAMETER = 73;
682 * Node type constant indicating a node of type
683 * <code>ParameterizedType</code>.
684 * @see ParameterizedType
687 public static final int PARAMETERIZED_TYPE = 74;
690 * Node type constant indicating a node of type
691 * <code>QualifiedType</code>.
695 public static final int QUALIFIED_TYPE = 75;
698 * Node type constant indicating a node of type
699 * <code>WildcardType</code>.
703 public static final int WILDCARD_TYPE = 76;
706 * Node type constant indicating a node of type
707 * <code>NormalAnnotation</code>.
708 * @see NormalAnnotation
711 public static final int NORMAL_ANNOTATION = 77;
714 * Node type constant indicating a node of type
715 * <code>MarkerAnnotation</code>.
716 * @see MarkerAnnotation
719 public static final int MARKER_ANNOTATION = 78;
722 * Node type constant indicating a node of type
723 * <code>SingleMemberAnnotation</code>.
724 * @see SingleMemberAnnotation
727 public static final int SINGLE_MEMBER_ANNOTATION = 79;
730 * Node type constant indicating a node of type
731 * <code>MemberValuePair</code>.
732 * @see MemberValuePair
735 public static final int MEMBER_VALUE_PAIR = 80;
738 * Node type constant indicating a node of type
739 * <code>AnnotationTypeDeclaration</code>.
740 * @see AnnotationTypeDeclaration
743 public static final int ANNOTATION_TYPE_DECLARATION = 81;
746 * Node type constant indicating a node of type
747 * <code>AnnotationTypeMemberDeclaration</code>.
748 * @see AnnotationTypeMemberDeclaration
751 public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82;
754 * Node type constant indicating a node of type
755 * <code>Modifier</code>.
759 public static final int MODIFIER = 83;
762 * Returns the node class for the corresponding node type.
764 * @param nodeType AST node type
765 * @return the corresponding <code>ASTNode</code> subclass
766 * @exception IllegalArgumentException if <code>nodeType</code> is
767 * not a legal AST node type
768 * @see #getNodeType()
771 public static Class nodeClassForType(int nodeType) {
773 case ANNOTATION_TYPE_DECLARATION :
774 return AnnotationTypeDeclaration.class;
775 case ANNOTATION_TYPE_MEMBER_DECLARATION :
776 return AnnotationTypeMemberDeclaration.class;
777 case ANONYMOUS_CLASS_DECLARATION :
778 return AnonymousClassDeclaration.class;
780 return ArrayAccess.class;
781 case ARRAY_CREATION :
782 return ArrayCreation.class;
783 case ARRAY_INITIALIZER :
784 return ArrayInitializer.class;
786 return ArrayType.class;
787 case ASSERT_STATEMENT :
788 return AssertStatement.class;
790 return Assignment.class;
794 return BlockComment.class;
795 case BOOLEAN_LITERAL :
796 return BooleanLiteral.class;
797 case BREAK_STATEMENT :
798 return BreakStatement.class;
799 case CAST_EXPRESSION :
800 return CastExpression.class;
802 return CatchClause.class;
803 case CHARACTER_LITERAL :
804 return CharacterLiteral.class;
805 case CLASS_INSTANCE_CREATION :
806 return ClassInstanceCreation.class;
807 case COMPILATION_UNIT :
808 return CompilationUnit.class;
809 case CONDITIONAL_EXPRESSION :
810 return ConditionalExpression.class;
811 case CONSTRUCTOR_INVOCATION :
812 return ConstructorInvocation.class;
813 case CONTINUE_STATEMENT :
814 return ContinueStatement.class;
816 return DoStatement.class;
817 case EMPTY_STATEMENT :
818 return EmptyStatement.class;
819 case ENHANCED_FOR_STATEMENT :
820 return EnhancedForStatement.class;
821 case ENUM_CONSTANT_DECLARATION :
822 return EnumConstantDeclaration.class;
823 case ENUM_DECLARATION :
824 return EnumDeclaration.class;
825 case EXPRESSION_STATEMENT :
826 return ExpressionStatement.class;
828 return FieldAccess.class;
829 case FIELD_DECLARATION :
830 return FieldDeclaration.class;
832 return ForStatement.class;
834 return IfStatement.class;
835 case IMPORT_DECLARATION :
836 return ImportDeclaration.class;
837 case INFIX_EXPRESSION :
838 return InfixExpression.class;
840 return Initializer.class;
841 case INSTANCEOF_EXPRESSION :
842 return InstanceofExpression.class;
844 return Javadoc.class;
845 case LABELED_STATEMENT :
846 return LabeledStatement.class;
848 return LineComment.class;
849 case MARKER_ANNOTATION :
850 return MarkerAnnotation.class;
852 return MemberRef.class;
853 case MEMBER_VALUE_PAIR :
854 return MemberValuePair.class;
855 case METHOD_DECLARATION :
856 return MethodDeclaration.class;
857 case METHOD_INVOCATION :
858 return MethodInvocation.class;
860 return MethodRef.class;
861 case METHOD_REF_PARAMETER :
862 return MethodRefParameter.class;
864 return Modifier.class;
865 case NORMAL_ANNOTATION :
866 return NormalAnnotation.class;
868 return NullLiteral.class;
869 case NUMBER_LITERAL :
870 return NumberLiteral.class;
871 case PACKAGE_DECLARATION :
872 return PackageDeclaration.class;
873 case PARAMETERIZED_TYPE :
874 return ParameterizedType.class;
875 case PARENTHESIZED_EXPRESSION :
876 return ParenthesizedExpression.class;
877 case POSTFIX_EXPRESSION :
878 return PostfixExpression.class;
879 case PREFIX_EXPRESSION :
880 return PrefixExpression.class;
881 case PRIMITIVE_TYPE :
882 return PrimitiveType.class;
883 case QUALIFIED_NAME :
884 return QualifiedName.class;
885 case QUALIFIED_TYPE :
886 return QualifiedType.class;
887 case RETURN_STATEMENT :
888 return ReturnStatement.class;
890 return SimpleName.class;
892 return SimpleType.class;
893 case SINGLE_MEMBER_ANNOTATION :
894 return SingleMemberAnnotation.class;
895 case SINGLE_VARIABLE_DECLARATION :
896 return SingleVariableDeclaration.class;
897 case STRING_LITERAL :
898 return StringLiteral.class;
899 case SUPER_CONSTRUCTOR_INVOCATION :
900 return SuperConstructorInvocation.class;
901 case SUPER_FIELD_ACCESS :
902 return SuperFieldAccess.class;
903 case SUPER_METHOD_INVOCATION :
904 return SuperMethodInvocation.class;
906 return SwitchCase.class;
907 case SWITCH_STATEMENT :
908 return SwitchStatement.class;
909 case SYNCHRONIZED_STATEMENT :
910 return SynchronizedStatement.class;
912 return TagElement.class;
914 return TextElement.class;
915 case THIS_EXPRESSION :
916 return ThisExpression.class;
917 case THROW_STATEMENT :
918 return ThrowStatement.class;
920 return TryStatement.class;
921 case TYPE_DECLARATION :
922 return TypeDeclaration.class;
923 case TYPE_DECLARATION_STATEMENT :
924 return TypeDeclarationStatement.class;
926 return TypeLiteral.class;
927 case TYPE_PARAMETER :
928 return TypeParameter.class;
929 case VARIABLE_DECLARATION_EXPRESSION :
930 return VariableDeclarationExpression.class;
931 case VARIABLE_DECLARATION_FRAGMENT :
932 return VariableDeclarationFragment.class;
933 case VARIABLE_DECLARATION_STATEMENT :
934 return VariableDeclarationStatement.class;
935 case WHILE_STATEMENT :
936 return WhileStatement.class;
938 return WildcardType.class;
940 throw new IllegalArgumentException();
946 * N.B. This ia a private field, but declared as package-visible
947 * for more efficient access from inner classes.
953 * Parent AST node, or <code>null</code> if this node is a root.
954 * Initially <code>null</code>.
956 private ASTNode parent = null;
959 * An unmodifiable empty map (used to implement <code>properties()</code>).
961 private static final Map UNMODIFIABLE_EMPTY_MAP
962 = Collections.unmodifiableMap(new HashMap(1));
965 * Primary field used in representing node properties efficiently.
966 * If <code>null</code>, this node has no properties.
967 * If a <code>String</code>, this is the name of this node's sole property,
968 * and <code>property2</code> contains its value.
969 * If a <code>HashMap</code>, this is the table of property name-value
970 * mappings; <code>property2</code>, if non-null is its unmodifiable
972 * Initially <code>null</code>.
976 private Object property1 = null;
979 * Auxillary field used in representing node properties efficiently.
983 private Object property2 = null;
986 * A character index into the original source string,
987 * or <code>-1</code> if no source position information is available
988 * for this node; <code>-1</code> by default.
990 private int startPosition = -1;
993 * A character length, or <code>0</code> if no source position
994 * information is recorded for this node; <code>0</code> by default.
996 private int length = 0;
999 * Flag constant (bit mask, value 1) indicating that there is something
1000 * not quite right with this AST node.
1002 * The standard parser (<code>ASTParser</code>) sets this
1003 * flag on a node to indicate a syntax error detected in the vicinity.
1006 public static final int MALFORMED = 1;
1009 * Flag constant (bit mask, value 2) indicating that this is a node
1010 * that was created by the parser (as opposed to one created by another
1013 * The standard parser (<code>ASTParser</code>) sets this
1014 * flag on the nodes it creates.
1018 public static final int ORIGINAL = 2;
1021 * Flag constant (bit mask, value 4) indicating that this node
1022 * is unmodifiable. When a node is marked unmodifiable, the
1023 * following operations result in a runtime exception:
1025 * <li>Change a simple property of this node.</li>
1026 * <li>Add or remove a child node from this node.</li>
1027 * <li>Parent (or reparent) this node.</li>
1030 * The standard parser (<code>ASTParser</code>) does not set
1031 * this flag on the nodes it creates. However, clients may set
1032 * this flag on a node to prevent further modification of the
1033 * its structural properties.
1037 public static final int PROTECT = 4;
1040 * Flag constant (bit mask, value 8) indicating that this node
1041 * or a part of this node is recovered from source that contains
1042 * a syntax error detected in the vicinity.
1044 * The standard parser (<code>ASTParser</code>) sets this
1045 * flag on a node to indicate a recovered node.
1049 public static final int RECOVERED = 8;
1052 * int containing the node type in the top 16 bits and
1053 * flags in the bottom 16 bits; none set by default.
1055 * N.B. This is a private field, but declared as package-visible
1056 * for more efficient access from inner classes.
1061 int typeAndFlags = 0;
1064 * Property of parent in which this node is a child, or <code>null</code>
1065 * if this node is a root. Initially <code>null</code>.
1067 * @see #getLocationInParent
1070 private StructuralPropertyDescriptor location = null;
1072 /** Internal convenience constant indicating that there is definite risk of cycles.
1075 static final boolean CYCLE_RISK = true;
1077 /** Internal convenience constant indicating that there is no risk of cycles.
1080 static final boolean NO_CYCLE_RISK = false;
1082 /** Internal convenience constant indicating that a structural property is mandatory.
1085 static final boolean MANDATORY = true;
1087 /** Internal convenience constant indicating that a structural property is optional.
1090 static final boolean OPTIONAL = false;
1093 * A specialized implementation of a list of ASTNodes. The
1094 * implementation is based on an ArrayList.
1096 class NodeList extends AbstractList {
1099 * The underlying list in which the nodes of this list are
1100 * stored (element type: <code>ASTNode</code>).
1102 * Be stingy on storage - assume that list will be empty.
1105 * This field declared default visibility (rather than private)
1106 * so that accesses from <code>NodeList.Cursor</code> do not require
1107 * a synthetic accessor method.
1110 ArrayList store = new ArrayList(0);
1113 * The property descriptor for this list.
1115 ChildListPropertyDescriptor propertyDescriptor;
1118 * A cursor for iterating over the elements of the list.
1119 * Does not lose its position if the list is changed during
1122 class Cursor implements Iterator {
1124 * The position of the cursor between elements. If the value
1125 * is N, then the cursor sits between the element at positions
1126 * N-1 and N. Initially just before the first element of the
1129 private int position = 0;
1132 * Method declared on <code>Iterator</code>.
1134 public boolean hasNext() {
1135 return this.position < NodeList.this.store.size();
1139 * Method declared on <code>Iterator</code>.
1141 public Object next() {
1142 Object result = NodeList.this.store.get(this.position);
1148 * Method declared on <code>Iterator</code>.
1150 public void remove() {
1151 throw new UnsupportedOperationException();
1155 * Adjusts this cursor to accomodate an add/remove at the given
1158 * @param index the position at which the element was added
1160 * @param delta +1 for add, and -1 for remove
1162 void update(int index, int delta) {
1163 if (this.position > index) {
1164 // the cursor has passed the added or removed element
1165 this.position += delta;
1171 * A list of currently active cursors (element type:
1172 * <code>Cursor</code>), or <code>null</code> if there are no
1175 * It is important for storage considerations to maintain the
1176 * null-means-empty invariant; otherwise, every NodeList instance
1177 * will waste a lot of space. A cursor is needed only for the duration
1178 * of a visit to the child nodes. Under normal circumstances, only a
1179 * single cursor is needed; multiple cursors are only required if there
1180 * are multiple visits going on at the same time.
1183 private List cursors = null;
1186 * Creates a new empty list of nodes owned by this node.
1187 * This node will be the common parent of all nodes added to
1190 * @param property the property descriptor
1193 NodeList(ChildListPropertyDescriptor property) {
1195 this.propertyDescriptor = property;
1199 * @see java.util.AbstractCollection#size()
1202 return this.store.size();
1206 * @see AbstractList#get(int)
1208 public Object get(int index) {
1209 return this.store.get(index);
1213 * @see List#set(int, java.lang.Object)
1215 public Object set(int index, Object element) {
1216 if (element == null) {
1217 throw new IllegalArgumentException();
1219 if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1220 // this node is protected => cannot gain or lose children
1221 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1223 // delink old child from parent, and link new child to parent
1224 ASTNode newChild = (ASTNode) element;
1225 ASTNode oldChild = (ASTNode) this.store.get(index);
1226 if (oldChild == newChild) {
1229 if ((oldChild.typeAndFlags & PROTECT) != 0) {
1230 // old child is protected => cannot be unparented
1231 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1233 ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
1234 ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
1236 Object result = this.store.set(index, newChild);
1237 // n.b. setParent will call ast.modifying()
1238 oldChild.setParent(null, null);
1239 newChild.setParent(ASTNode.this, this.propertyDescriptor);
1240 ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
1245 * @see List#add(int, java.lang.Object)
1247 public void add(int index, Object element) {
1248 if (element == null) {
1249 throw new IllegalArgumentException();
1251 if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1252 // this node is protected => cannot gain or lose children
1253 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1255 // link new child to parent
1256 ASTNode newChild = (ASTNode) element;
1257 ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
1258 ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
1261 this.store.add(index, element);
1262 updateCursors(index, +1);
1263 // n.b. setParent will call ast.modifying()
1264 newChild.setParent(ASTNode.this, this.propertyDescriptor);
1265 ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
1269 * @see List#remove(int)
1271 public Object remove(int index) {
1272 if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1273 // this node is protected => cannot gain or lose children
1274 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1276 // delink old child from parent
1277 ASTNode oldChild = (ASTNode) this.store.get(index);
1278 if ((oldChild.typeAndFlags & PROTECT) != 0) {
1279 // old child is protected => cannot be unparented
1280 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1283 ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
1284 // n.b. setParent will call ast.modifying()
1285 oldChild.setParent(null, null);
1286 Object result = this.store.remove(index);
1287 updateCursors(index, -1);
1288 ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
1294 * Allocate a cursor to use for a visit. The client must call
1295 * <code>releaseCursor</code> when done.
1297 * This method is internally synchronized on this NodeList.
1298 * It is thread-safe to create a cursor.
1301 * @return a new cursor positioned before the first element
1304 Cursor newCursor() {
1305 synchronized (this) {
1306 // serialize cursor management on this NodeList
1307 if (this.cursors == null) {
1308 // convert null to empty list
1309 this.cursors = new ArrayList(1);
1311 Cursor result = new Cursor();
1312 this.cursors.add(result);
1318 * Releases the given cursor at the end of a visit.
1320 * This method is internally synchronized on this NodeList.
1321 * It is thread-safe to release a cursor.
1324 * @param cursor the cursor
1326 void releaseCursor(Cursor cursor) {
1327 synchronized (this) {
1328 // serialize cursor management on this NodeList
1329 this.cursors.remove(cursor);
1330 if (this.cursors.isEmpty()) {
1331 // important: convert empty list back to null
1332 // otherwise the node will hang on to needless junk
1333 this.cursors = null;
1339 * Adjusts all cursors to accomodate an add/remove at the given
1342 * This method is only used when the list is being modified.
1343 * The AST is not thread-safe if any of the clients are modifying it.
1346 * @param index the position at which the element was added
1348 * @param delta +1 for add, and -1 for remove
1350 private void updateCursors(int index, int delta) {
1351 if (this.cursors == null) {
1352 // there are no cursors to worry about
1355 for (Iterator it = this.cursors.iterator(); it.hasNext(); ) {
1356 Cursor c = (Cursor) it.next();
1357 c.update(index, delta);
1362 * Returns an estimate of the memory footprint of this node list
1363 * instance in bytes.
1365 * <li>1 object header for the NodeList instance</li>
1366 * <li>5 4-byte fields of the NodeList instance</li>
1367 * <li>0 for cursors since null unless walk in progress</li>
1368 * <li>1 object header for the ArrayList instance</li>
1369 * <li>2 4-byte fields of the ArrayList instance</li>
1370 * <li>1 object header for an Object[] instance</li>
1371 * <li>4 bytes in array for each element</li>
1374 * @return the size of this node list in bytes
1377 int result = HEADERS + 5 * 4;
1378 result += HEADERS + 2 * 4;
1379 result += HEADERS + 4 * size();
1384 * Returns an estimate of the memory footprint in bytes of this node
1385 * list and all its subtrees.
1387 * @return the size of this list of subtrees in bytes
1390 int result = memSize();
1391 for (Iterator it = iterator(); it.hasNext(); ) {
1392 ASTNode child = (ASTNode) it.next();
1393 result += child.treeSize();
1400 * Creates a new AST node owned by the given AST. Once established,
1401 * the relationship between an AST node and its owning AST does not change
1402 * over the lifetime of the node. The new node has no parent node,
1403 * and no properties.
1405 * N.B. This constructor is package-private; all subclasses my be
1406 * declared in the same package; clients are unable to declare
1407 * additional subclasses.
1410 * @param ast the AST that is to own this node
1414 throw new IllegalArgumentException();
1418 setNodeType(getNodeType0());
1419 setFlags(ast.getDefaultNodeFlag());
1420 // setFlags calls modifying();
1424 * Returns this node's AST.
1426 * Note that the relationship between an AST node and its owing AST does
1427 * not change over the lifetime of a node.
1430 * @return the AST that owns this node
1432 public final AST getAST() {
1437 * Returns this node's parent node, or <code>null</code> if this is the
1440 * Note that the relationship between an AST node and its parent node
1441 * may change over the lifetime of a node.
1444 * @return the parent of this node, or <code>null</code> if none
1446 public final ASTNode getParent() {
1451 * Returns the location of this node within its parent,
1452 * or <code>null</code> if this is a root node.
1455 * ASTNode node = ...;
1456 * ASTNode parent = node.getParent();
1457 * StructuralPropertyDescriptor location = node.getLocationInParent();
1458 * assert (parent != null) == (location != null);
1459 * if ((location != null) && location.isChildProperty())
1460 * assert parent.getStructuralProperty(location) == node;
1461 * if ((location != null) && location.isChildListProperty())
1462 * assert ((List) parent.getStructuralProperty(location)).contains(node);
1466 * Note that the relationship between an AST node and its parent node
1467 * may change over the lifetime of a node.
1470 * @return the location of this node in its parent,
1471 * or <code>null</code> if this node has no parent
1474 public final StructuralPropertyDescriptor getLocationInParent() {
1475 return this.location;
1479 * Returns the root node at or above this node; returns this node if
1482 * @return the root node at or above this node
1484 public final ASTNode getRoot() {
1485 ASTNode candidate = this;
1487 ASTNode p = candidate.getParent();
1489 // candidate has no parent - that's the guy
1497 * Returns the value of the given structural property for this node. The value
1498 * returned depends on the kind of property:
1500 * <li>{@link SimplePropertyDescriptor} - the value of the given simple property,
1501 * or <code>null</code> if none; primitive values are "boxed"</li>
1502 * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>),
1503 * or <code>null</code> if none</li>
1504 * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li>
1507 * @param property the property
1508 * @return the value, or <code>null</code> if none
1509 * @exception RuntimeException if this node does not have the given property
1512 public final Object getStructuralProperty(StructuralPropertyDescriptor property) {
1513 if (property instanceof SimplePropertyDescriptor) {
1514 SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1515 if (p.getValueType() == int.class) {
1516 int result = internalGetSetIntProperty(p, true, 0);
1517 return new Integer(result);
1518 } else if (p.getValueType() == boolean.class) {
1519 boolean result = internalGetSetBooleanProperty(p, true, false);
1520 return Boolean.valueOf(result);
1522 return internalGetSetObjectProperty(p, true, null);
1525 if (property instanceof ChildPropertyDescriptor) {
1526 return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null);
1528 if (property instanceof ChildListPropertyDescriptor) {
1529 return internalGetChildListProperty((ChildListPropertyDescriptor) property);
1531 throw new IllegalArgumentException();
1535 * Sets the value of the given structural property for this node. The value
1536 * passed depends on the kind of property:
1538 * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property,
1539 * or <code>null</code> if none; primitive values are "boxed"</li>
1540 * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>),
1541 * or <code>null</code> if none</li>
1542 * <li>{@link ChildListPropertyDescriptor} - not allowed</li>
1545 * @param property the property
1546 * @param value the property value
1547 * @exception RuntimeException if this node does not have the
1548 * given property, or if the given property cannot be set
1551 public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) {
1552 if (property instanceof SimplePropertyDescriptor) {
1553 SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1554 if (p.getValueType() == int.class) {
1555 int arg = ((Integer) value).intValue();
1556 internalGetSetIntProperty(p, false, arg);
1558 } else if (p.getValueType() == boolean.class) {
1559 boolean arg = ((Boolean) value).booleanValue();
1560 internalGetSetBooleanProperty(p, false, arg);
1563 if (value == null && p.isMandatory()) {
1564 throw new IllegalArgumentException();
1566 internalGetSetObjectProperty(p, false, value);
1570 if (property instanceof ChildPropertyDescriptor) {
1571 ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
1572 ASTNode child = (ASTNode) value;
1573 if (child == null && p.isMandatory()) {
1574 throw new IllegalArgumentException();
1576 internalGetSetChildProperty(p, false, child);
1579 if (property instanceof ChildListPropertyDescriptor) {
1580 throw new IllegalArgumentException("Cannot set the list of child list property"); //$NON-NLS-1$
1585 * Sets the value of the given int-valued property for this node.
1586 * The default implementation of this method throws an exception explaining
1587 * that this node does not have such a property. This method should be
1588 * extended in subclasses that have at leasy one simple property whose value
1591 * @param property the property
1592 * @param get <code>true</code> for a get operation, and
1593 * <code>false</code> for a set operation
1594 * @param value the new property value; ignored for get operations
1595 * @return the value; always returns
1596 * <code>0</code> for set operations
1597 * @exception RuntimeException if this node does not have the
1598 * given property, or if the given value cannot be set as specified
1601 int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
1602 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1606 * Sets the value of the given boolean-valued property for this node.
1607 * The default implementation of this method throws an exception explaining
1608 * that this node does not have such a property. This method should be
1609 * extended in subclasses that have at leasy one simple property whose value
1612 * @param property the property
1613 * @param get <code>true</code> for a get operation, and
1614 * <code>false</code> for a set operation
1615 * @param value the new property value; ignored for get operations
1616 * @return the value; always returns
1617 * <code>false</code> for set operations
1618 * @exception RuntimeException if this node does not have the
1619 * given property, or if the given value cannot be set as specified
1622 boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
1623 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1627 * Sets the value of the given property for this node.
1628 * The default implementation of this method throws an exception explaining
1629 * that this node does not have such a property. This method should be
1630 * extended in subclasses that have at leasy one simple property whose value
1631 * type is a reference type.
1633 * @param property the property
1634 * @param get <code>true</code> for a get operation, and
1635 * <code>false</code> for a set operation
1636 * @param value the new property value, or <code>null</code> if none;
1637 * ignored for get operations
1638 * @return the value, or <code>null</code> if none; always returns
1639 * <code>null</code> for set operations
1640 * @exception RuntimeException if this node does not have the
1641 * given property, or if the given value cannot be set as specified
1644 Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
1645 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1649 * Sets the child value of the given property for this node.
1650 * The default implementation of this method throws an exception explaining
1651 * that this node does not have such a property. This method should be
1652 * extended in subclasses that have at leasy one child property.
1654 * @param property the property
1655 * @param get <code>true</code> for a get operation, and
1656 * <code>false</code> for a set operation
1657 * @param child the new child value, or <code>null</code> if none;
1658 * always <code>null</code> for get operations
1659 * @return the child, or <code>null</code> if none; always returns
1660 * <code>null</code> for set operations
1661 * @exception RuntimeException if this node does not have the
1662 * given property, or if the given child cannot be set as specified
1665 ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
1666 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1670 * Returns the list value of the given property for this node.
1671 * The default implementation of this method throws an exception explaining
1672 * that this noed does not have such a property. This method should be
1673 * extended in subclasses that have at leasy one child list property.
1675 * @param property the property
1676 * @return the list (element type: {@link ASTNode})
1677 * @exception RuntimeException if the given node does not have the
1681 List internalGetChildListProperty(ChildListPropertyDescriptor property) {
1682 throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1686 * Returns a list of structural property descriptors for nodes of the
1687 * same type as this node. Clients must not modify the result.
1689 * Note that property descriptors are a meta-level mechanism
1690 * for manipulating ASTNodes in a generic way. They are
1691 * unrelated to <code>get/setProperty</code>.
1694 * @return a list of property descriptors (element type:
1695 * {@link StructuralPropertyDescriptor})
1698 public final List structuralPropertiesForType() {
1699 return internalStructuralPropertiesForType(this.ast.apiLevel);
1703 * Returns a list of property descriptors for this node type.
1704 * Clients must not modify the result. This abstract method
1705 * must be implemented in each concrete AST node type.
1707 * N.B. This method is package-private, so that the implementations
1708 * of this method in each of the concrete AST node types do not
1709 * clutter up the API doc.
1712 * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants
1713 * @return a list of property descriptors (element type:
1714 * {@link StructuralPropertyDescriptor})
1717 abstract List internalStructuralPropertiesForType(int apiLevel);
1720 * Internal helper method that starts the building a list of
1721 * property descriptors for the given node type.
1723 * @param nodeClass the class for a concrete node type
1724 * @param propertyList empty list
1726 static void createPropertyList(Class nodeClass, List propertyList) {
1727 // stuff nodeClass at head of list for future ref
1728 propertyList.add(nodeClass);
1732 * Internal helper method that adding a property descriptor.
1734 * @param property the structural property descriptor
1735 * @param propertyList list beginning with the AST node class
1736 * followed by accumulated structural property descriptors
1738 static void addProperty(StructuralPropertyDescriptor property, List propertyList) {
1739 Class nodeClass = (Class) propertyList.get(0);
1740 if (property.getNodeClass() != nodeClass) {
1741 // easily made cut-and-paste mistake
1742 throw new RuntimeException("Structural property descriptor has wrong node class!"); //$NON-NLS-1$
1744 propertyList.add(property);
1748 * Internal helper method that completes the building of
1749 * a node type's structural property descriptor list.
1751 * @param propertyList list beginning with the AST node class
1752 * followed by accumulated structural property descriptors
1753 * @return unmodifiable list of structural property descriptors
1754 * (element type: <code>StructuralPropertyDescriptor</code>)
1756 static List reapPropertyList(List propertyList) {
1757 propertyList.remove(0); // remove nodeClass
1759 ArrayList a = new ArrayList(propertyList.size());
1760 a.addAll(propertyList);
1761 return Collections.unmodifiableList(a);
1765 * Checks that this AST operation is not used when
1766 * building JLS2 level ASTs.
1768 * @exception UnsupportedOperationException
1771 final void unsupportedIn2() {
1772 if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
1773 throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
1778 * Checks that this AST operation is only used when
1779 * building JLS2 level ASTs.
1781 * @exception UnsupportedOperationException
1784 final void supportedOnlyIn2() {
1785 if (this.ast.apiLevel != AST.JLS2_INTERNAL) {
1786 throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$
1791 * Sets or clears this node's parent node and location.
1793 * Note that this method is package-private. The pointer from a node
1794 * to its parent is set implicitly as a side effect of inserting or
1795 * removing the node as a child of another node. This method calls
1796 * <code>ast.modifying()</code>.
1799 * @param parent the new parent of this node, or <code>null</code> if none
1800 * @param property the location of this node in its parent,
1801 * or <code>null</code> if <code>parent</code> is <code>null</code>
1802 * @see #getLocationInParent
1806 final void setParent(ASTNode parent, StructuralPropertyDescriptor property) {
1807 this.ast.modifying();
1808 this.parent = parent;
1809 this.location = property;
1813 * Removes this node from its parent. Has no effect if this node
1814 * is unparented. If this node appears as an element of a child list
1815 * property of its parent, then this node is removed from the
1816 * list using <code>List.remove</code>.
1817 * If this node appears as the value of a child property of its
1818 * parent, then this node is detached from its parent
1819 * by passing <code>null</code> to the appropriate setter method;
1820 * this operation fails if this node is in a mandatory property.
1824 public final void delete() {
1825 StructuralPropertyDescriptor p = getLocationInParent();
1827 // node is unparented
1830 if (p.isChildProperty()) {
1831 getParent().setStructuralProperty(this.location, null);
1834 if (p.isChildListProperty()) {
1835 List l = (List) getParent().getStructuralProperty(this.location);
1841 * Checks whether the given new child node is a node
1842 * in a different AST from its parent-to-be, whether it is
1843 * already has a parent, whether adding it to its
1844 * parent-to-be would create a cycle, and whether the child is of
1845 * the right type. The parent-to-be is the enclosing instance.
1847 * @param node the parent-to-be node
1848 * @param newChild the new child of the parent
1849 * @param cycleCheck <code>true</code> if cycles are possible and need
1850 * to be checked, <code>false</code> if cycles are impossible and do
1851 * not need to be checked
1852 * @param nodeType a type constraint on child nodes, or <code>null</code>
1853 * if no special check is required
1854 * @exception IllegalArgumentException if:
1856 * <li>the child is null</li>
1857 * <li>the node belongs to a different AST</li>
1858 * <li>the child has the incorrect node type</li>
1859 * <li>the node already has a parent</li>
1860 * <li>a cycle in would be created</li>
1863 static void checkNewChild(ASTNode node, ASTNode newChild,
1864 boolean cycleCheck, Class nodeType) {
1865 if (newChild.ast != node.ast) {
1866 // new child is from a different AST
1867 throw new IllegalArgumentException();
1869 if (newChild.getParent() != null) {
1870 // new child currently has a different parent
1871 throw new IllegalArgumentException();
1873 if (cycleCheck && newChild == node.getRoot()) {
1874 // inserting new child would create a cycle
1875 throw new IllegalArgumentException();
1877 Class childClass = newChild.getClass();
1878 if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
1879 // new child is not of the right type
1880 throw new ClassCastException();
1882 if ((newChild.typeAndFlags & PROTECT) != 0) {
1883 // new child node is protected => cannot be parented
1884 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1889 * Prelude portion of the "3 step program" for replacing the
1890 * old child of this node with another node.
1891 * Here is the code pattern found in all AST node subclasses:
1893 * ASTNode oldChild = this.foo;
1894 * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1895 * this.foo = newFoo;
1896 * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1898 * The first part (preReplaceChild) does all the precondition checks,
1899 * reports pre-delete events, and changes parent links.
1900 * The old child is delinked from its parent (making it a root node),
1901 * and the new child node is linked to its parent. The new child node
1902 * must be a root node in the same AST as its new parent, and must not
1903 * be an ancestor of this node. All three nodes must be
1904 * modifiable (not PROTECTED). The replace operation must fail
1905 * atomically; so it is crucial that all precondition checks
1906 * be done before any linking and delinking happens.
1907 * The final part (postReplaceChild )reports post-add events.
1909 * This method calls <code>ast.modifying()</code> for the nodes affected.
1912 * @param oldChild the old child of this node, or <code>null</code> if
1913 * there was no old child to replace
1914 * @param newChild the new child of this node, or <code>null</code> if
1915 * there is no replacement child
1916 * @param property the property descriptor of this node describing
1917 * the relationship between node and child
1918 * @exception RuntimeException if:
1920 * <li>the node belongs to a different AST</li>
1921 * <li>the node already has a parent</li>
1922 * <li>a cycle in would be created</li>
1923 * <li>any of the nodes involved are unmodifiable</li>
1927 final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
1928 if ((this.typeAndFlags & PROTECT) != 0) {
1929 // this node is protected => cannot gain or lose children
1930 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1932 if (newChild != null) {
1933 checkNewChild(this, newChild, property.cycleRisk, null);
1935 // delink old child from parent
1936 if (oldChild != null) {
1937 if ((oldChild.typeAndFlags & PROTECT) != 0) {
1938 // old child node is protected => cannot be unparented
1939 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1941 if (newChild != null) {
1942 this.ast.preReplaceChildEvent(this, oldChild, newChild, property);
1944 this.ast.preRemoveChildEvent(this, oldChild, property);
1946 oldChild.setParent(null, null);
1948 if(newChild != null) {
1949 this.ast.preAddChildEvent(this, newChild, property);
1952 // link new child to parent
1953 if (newChild != null) {
1954 newChild.setParent(this, property);
1955 // cannot notify postAddChildEvent until parent is linked to child too
1960 * Postlude portion of the "3 step program" for replacing the
1961 * old child of this node with another node.
1962 * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
1966 final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
1967 // link new child to parent
1968 if (newChild != null) {
1969 if (oldChild != null) {
1970 this.ast.postReplaceChildEvent(this, oldChild, newChild, property);
1972 this.ast.postAddChildEvent(this, newChild, property);
1975 this.ast.postRemoveChildEvent(this, oldChild, property);
1980 * Prelude portion of the "3 step program" for changing the
1981 * value of a simple property of this node.
1982 * Here is the code pattern found in all AST node subclasses:
1984 * preValueChange(FOO_PROPERTY);
1985 * this.foo = newFoo;
1986 * postValueChange(FOO_PROPERTY);
1988 * The first part (preValueChange) does the precondition check
1989 * to make sure the node is modifiable (not PROTECTED).
1990 * The change operation must fail atomically; so it is crucial
1991 * that the precondition checks are done before the field is
1992 * hammered. The final part (postValueChange)reports post-change
1995 * This method calls <code>ast.modifying()</code> for the node affected.
1998 * @param property the property descriptor of this node
1999 * @exception RuntimeException if:
2001 * <li>this node is unmodifiable</li>
2005 final void preValueChange(SimplePropertyDescriptor property) {
2006 if ((this.typeAndFlags & PROTECT) != 0) {
2007 // this node is protected => cannot change valure of properties
2008 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
2010 this.ast.preValueChangeEvent(this, property);
2011 this.ast.modifying();
2015 * Postlude portion of the "3 step program" for replacing the
2016 * old child of this node with another node.
2017 * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
2020 final void postValueChange(SimplePropertyDescriptor property) {
2021 this.ast.postValueChangeEvent(this, property);
2025 * Ensures that this node is modifiable (that is, not marked PROTECTED).
2026 * If successful, calls ast.modifying().
2027 * @exception RuntimeException is not modifiable
2029 final void checkModifiable() {
2030 if ((this.typeAndFlags & PROTECT) != 0) {
2031 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
2033 this.ast.modifying();
2037 * Begin lazy initialization of this node.
2038 * Here is the code pattern found in all AST
2041 * if (this.foo == null) {
2042 * // lazy init must be thread-safe for readers
2043 * synchronized (this) {
2044 * if (this.foo == null) {
2046 * this.foo = ...; // code to create new node
2047 * postLazyInit(this.foo, FOO_PROPERTY);
2054 final void preLazyInit() {
2055 // IMPORTANT: this method is called by readers
2056 // ASTNode.this is locked at this point
2057 this.ast.disableEvents();
2058 // will turn events back on in postLasyInit
2062 * End lazy initialization of this node.
2064 * @param newChild the new child of this node, or <code>null</code> if
2065 * there is no replacement child
2066 * @param property the property descriptor of this node describing
2067 * the relationship between node and child
2070 final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) {
2071 // IMPORTANT: this method is called by readers
2072 // ASTNode.this is locked at this point
2073 // newChild is brand new (so no chance of concurrent access)
2074 newChild.setParent(this, property);
2075 // turn events back on (they were turned off in corresponding preLazyInit)
2076 this.ast.reenableEvents();
2080 * Returns the named property of this node, or <code>null</code> if none.
2082 * @param propertyName the property name
2083 * @return the property value, or <code>null</code> if none
2084 * @see #setProperty(String,Object)
2086 public final Object getProperty(String propertyName) {
2087 if (propertyName == null) {
2088 throw new IllegalArgumentException();
2090 if (this.property1 == null) {
2091 // node has no properties at all
2094 if (this.property1 instanceof String) {
2095 // node has only a single property
2096 if (propertyName.equals(this.property1)) {
2097 return this.property2;
2102 // otherwise node has table of properties
2103 Map m = (Map) this.property1;
2104 return m.get(propertyName);
2108 * Sets the named property of this node to the given value,
2109 * or to <code>null</code> to clear it.
2111 * Clients should employ property names that are sufficiently unique
2112 * to avoid inadvertent conflicts with other clients that might also be
2113 * setting properties on the same node.
2116 * Note that modifying a property is not considered a modification to the
2117 * AST itself. This is to allow clients to decorate existing nodes with
2118 * their own properties without jeopardizing certain things (like the
2119 * validity of bindings), which rely on the underlying tree remaining static.
2122 * @param propertyName the property name
2123 * @param data the new property value, or <code>null</code> if none
2124 * @see #getProperty(String)
2126 public final void setProperty(String propertyName, Object data) {
2127 if (propertyName == null) {
2128 throw new IllegalArgumentException();
2130 // N.B. DO NOT CALL ast.modifying();
2132 if (this.property1 == null) {
2133 // node has no properties at all
2135 // we already know this
2138 // node gets its fist property
2139 this.property1 = propertyName;
2140 this.property2 = data;
2144 if (this.property1 instanceof String) {
2145 // node has only a single property
2146 if (propertyName.equals(this.property1)) {
2148 this.property2 = data;
2150 // just deleted last property
2151 this.property1 = null;
2152 this.property2 = null;
2157 // we already know this
2160 // node already has one property - getting its second
2161 // convert to more flexible representation
2162 HashMap m = new HashMap(2);
2163 m.put(this.property1, this.property2);
2164 m.put(propertyName, data);
2166 this.property2 = null;
2170 // node has two or more properties
2171 HashMap m = (HashMap) this.property1;
2173 m.remove(propertyName);
2174 // check for just one property left
2175 if (m.size() == 1) {
2176 // convert to more efficient representation
2177 Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]);
2178 this.property1 = entries[0].getKey();
2179 this.property2 = entries[0].getValue();
2183 m.put(propertyName, data);
2184 // still has two or more properties
2190 * Returns an unmodifiable table of the properties of this node with
2191 * non-<code>null</code> values.
2193 * @return the table of property values keyed by property name
2194 * (key type: <code>String</code>; value type: <code>Object</code>)
2196 public final Map properties() {
2197 if (this.property1 == null) {
2198 // node has no properties at all
2199 return UNMODIFIABLE_EMPTY_MAP;
2201 if (this.property1 instanceof String) {
2202 // node has a single property
2203 return Collections.singletonMap(this.property1, this.property2);
2206 // node has two or more properties
2207 if (this.property2 == null) {
2208 this.property2 = Collections.unmodifiableMap((Map) this.property1);
2210 // property2 is unmodifiable wrapper for map in property1
2211 return (Map) this.property2;
2215 * Returns the flags associated with this node.
2217 * No flags are associated with newly created nodes.
2220 * The flags are the bitwise-or of individual flags.
2221 * The following flags are currently defined:
2223 * <li>{@link #MALFORMED} - indicates node is syntactically
2225 * <li>{@link #ORIGINAL} - indicates original node
2226 * created by ASTParser</li>
2227 * <li>{@link #PROTECT} - indicates node is protected
2228 * from further modification</li>
2229 * <li>{@link #RECOVERED} - indicates node or a part of this node
2230 * is recovered from source that contains a syntax error</li>
2232 * Other bit positions are reserved for future use.
2235 * @return the bitwise-or of individual flags
2236 * @see #setFlags(int)
2238 public final int getFlags() {
2239 return this.typeAndFlags & 0xFFFF;
2243 * Sets the flags associated with this node to the given value.
2245 * The flags are the bitwise-or of individual flags.
2246 * The following flags are currently defined:
2248 * <li>{@link #MALFORMED} - indicates node is syntactically
2250 * <li>{@link #ORIGINAL} - indicates original node
2251 * created by ASTParser</li>
2252 * <li>{@link #PROTECT} - indicates node is protected
2253 * from further modification</li>
2254 * <li>{@link #RECOVERED} - indicates node or a part of this node
2255 * is recovered from source that contains a syntax error</li>
2257 * Other bit positions are reserved for future use.
2260 * Note that the flags are <em>not</em> considered a structural
2261 * property of the node, and can be changed even if the
2262 * node is marked as protected.
2265 * @param flags the bitwise-or of individual flags
2268 public final void setFlags(int flags) {
2269 this.ast.modifying();
2270 int old = this.typeAndFlags & 0xFFFF0000;
2271 this.typeAndFlags = old | (flags & 0xFFFF);
2275 * Returns an integer value identifying the type of this concrete AST node.
2276 * The values are small positive integers, suitable for use in switch statements.
2278 * For each concrete node type there is a unique node type constant (name
2279 * and value). The unique node type constant for a concrete node type such as
2280 * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>.
2283 * @return one of the node type constants
2285 public final int getNodeType() {
2286 return this.typeAndFlags >>> 16;
2290 * Sets the integer value identifying the type of this concrete AST node.
2291 * The values are small positive integers, suitable for use in switch statements.
2293 * @param nodeType one of the node type constants
2295 private void setNodeType(int nodeType) {
2296 int old = this.typeAndFlags & 0xFFFF0000;
2297 this.typeAndFlags = old | (nodeType << 16);
2301 * Returns an integer value identifying the type of this concrete AST node.
2303 * This internal method is implemented in each of the
2304 * concrete node subclasses.
2307 * @return one of the node type constants
2309 abstract int getNodeType0();
2312 * The <code>ASTNode</code> implementation of this <code>Object</code>
2313 * method uses object identity (==). Use <code>subtreeMatch</code> to
2314 * compare two subtrees for equality.
2316 * @param obj {@inheritDoc}
2317 * @return {@inheritDoc}
2318 * @see #subtreeMatch(ASTMatcher matcher, Object other)
2320 public final boolean equals(Object obj) {
2321 return this == obj; // equivalent to Object.equals
2326 * This makes it consistent with the fact that a equals methods has been provided.
2327 * @see java.lang.Object#hashCode()
2329 public final int hashCode() {
2330 return super.hashCode();
2334 * Returns whether the subtree rooted at the given node matches the
2335 * given other object as decided by the given matcher.
2337 * @param matcher the matcher
2338 * @param other the other object, or <code>null</code>
2339 * @return <code>true</code> if the subtree matches, or
2340 * <code>false</code> if they do not match
2342 public final boolean subtreeMatch(ASTMatcher matcher, Object other) {
2343 return subtreeMatch0(matcher, other);
2347 * Returns whether the subtree rooted at the given node matches the
2348 * given other object as decided by the given matcher.
2350 * This internal method is implemented in each of the
2351 * concrete node subclasses.
2354 * @param matcher the matcher
2355 * @param other the other object, or <code>null</code>
2356 * @return <code>true</code> if the subtree matches, or
2357 * <code>false</code> if they do not match
2359 abstract boolean subtreeMatch0(ASTMatcher matcher, Object other);
2362 * Returns a deep copy of the subtree of AST nodes rooted at the
2363 * given node. The resulting nodes are owned by the given AST,
2364 * which may be different from the ASTs of the given node.
2365 * Even if the given node has a parent, the result node will be unparented.
2367 * Source range information on the original nodes is automatically copied to the new
2368 * nodes. Client properties (<code>properties</code>) are not carried over.
2371 * The node's <code>AST</code> and the target <code>AST</code> must support
2372 * the same API level.
2375 * @param target the AST that is to own the nodes in the result
2376 * @param node the node to copy, or <code>null</code> if none
2377 * @return the copied node, or <code>null</code> if <code>node</code>
2378 * is <code>null</code>
2380 public static ASTNode copySubtree(AST target, ASTNode node) {
2384 if (target == null) {
2385 throw new IllegalArgumentException();
2387 if (target.apiLevel() != node.getAST().apiLevel()) {
2388 throw new UnsupportedOperationException();
2390 ASTNode newNode = node.clone(target);
2395 * Returns a deep copy of the subtrees of AST nodes rooted at the
2396 * given list of nodes. The resulting nodes are owned by the given AST,
2397 * which may be different from the ASTs of the nodes in the list.
2398 * Even if the nodes in the list have parents, the nodes in the result
2399 * will be unparented.
2401 * Source range information on the original nodes is automatically copied to the new
2402 * nodes. Client properties (<code>properties</code>) are not carried over.
2405 * @param target the AST that is to own the nodes in the result
2406 * @param nodes the list of nodes to copy
2407 * (element type: <code>ASTNode</code>)
2408 * @return the list of copied subtrees
2409 * (element type: <code>ASTNode</code>)
2411 public static List copySubtrees(AST target, List nodes) {
2412 List result = new ArrayList(nodes.size());
2413 for (Iterator it = nodes.iterator(); it.hasNext(); ) {
2414 ASTNode oldNode = (ASTNode) it.next();
2415 ASTNode newNode = oldNode.clone(target);
2416 result.add(newNode);
2422 * Returns a deep copy of the subtree of AST nodes rooted at this node.
2423 * The resulting nodes are owned by the given AST, which may be different
2424 * from the AST of this node. Even if this node has a parent, the
2425 * result node will be unparented.
2427 * This method reports pre- and post-clone events, and dispatches
2428 * to <code>clone0(AST)</code> which is reimplemented in node subclasses.
2431 * @param target the AST that is to own the nodes in the result
2432 * @return the root node of the copies subtree
2434 final ASTNode clone(AST target) {
2435 this.ast.preCloneNodeEvent(this);
2436 ASTNode c = this.clone0(target);
2437 this.ast.postCloneNodeEvent(this, c);
2442 * Returns a deep copy of the subtree of AST nodes rooted at this node.
2443 * The resulting nodes are owned by the given AST, which may be different
2444 * from the AST of this node. Even if this node has a parent, the
2445 * result node will be unparented.
2447 * This method must be implemented in subclasses.
2450 * This method does not report pre- and post-clone events.
2451 * All callers should instead call <code>clone(AST)</code>
2452 * to ensure that pre- and post-clone events are reported.
2455 * N.B. This method is package-private, so that the implementations
2456 * of this method in each of the concrete AST node types do not
2457 * clutter up the API doc.
2460 * @param target the AST that is to own the nodes in the result
2461 * @return the root node of the copies subtree
2463 abstract ASTNode clone0(AST target);
2466 * Accepts the given visitor on a visit of the current node.
2468 * @param visitor the visitor object
2469 * @exception IllegalArgumentException if the visitor is null
2471 public final void accept(ASTVisitor visitor) {
2472 if (visitor == null) {
2473 throw new IllegalArgumentException();
2475 // begin with the generic pre-visit
2476 visitor.preVisit(this);
2477 // dynamic dispatch to internal method for type-specific visit/endVisit
2479 // end with the generic post-visit
2480 visitor.postVisit(this);
2484 * Accepts the given visitor on a type-specific visit of the current node.
2485 * This method must be implemented in all concrete AST node types.
2487 * General template for implementation on each concrete ASTNode class:
2490 * boolean visitChildren = visitor.visit(this);
2491 * if (visitChildren) {
2492 * // visit children in normal left to right reading order
2493 * acceptChild(visitor, getProperty1());
2494 * acceptChildren(visitor, rawListProperty);
2495 * acceptChild(visitor, getProperty2());
2497 * visitor.endVisit(this);
2500 * Note that the caller (<code>accept</code>) take cares of invoking
2501 * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>.
2504 * @param visitor the visitor object
2506 abstract void accept0(ASTVisitor visitor);
2509 * Accepts the given visitor on a visit of the current node.
2511 * This method should be used by the concrete implementations of
2512 * <code>accept0</code> to traverse optional properties. Equivalent
2513 * to <code>child.accept(visitor)</code> if <code>child</code>
2514 * is not <code>null</code>.
2517 * @param visitor the visitor object
2518 * @param child the child AST node to dispatch too, or <code>null</code>
2521 final void acceptChild(ASTVisitor visitor, ASTNode child) {
2522 if (child == null) {
2525 child.accept(visitor);
2529 * Accepts the given visitor on a visit of the given live list of
2532 * This method must be used by the concrete implementations of
2533 * <code>accept</code> to traverse list-values properties; it
2534 * encapsulates the proper handling of on-the-fly changes to the list.
2537 * @param visitor the visitor object
2538 * @param children the child AST node to dispatch too, or <code>null</code>
2541 final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) {
2542 // use a cursor to keep track of where we are up to
2543 // (the list may be changing under foot)
2544 NodeList.Cursor cursor = children.newCursor();
2546 while (cursor.hasNext()) {
2547 ASTNode child = (ASTNode) cursor.next();
2548 child.accept(visitor);
2551 children.releaseCursor(cursor);
2556 * Returns the character index into the original source file indicating
2557 * where the source fragment corresponding to this node begins.
2559 * The parser supplies useful well-defined source ranges to the nodes it creates.
2560 * See {@link ASTParser#setKind(int)} for details
2561 * on precisely where source ranges begin and end.
2564 * @return the 0-based character index, or <code>-1</code>
2565 * if no source position information is recorded for this node
2569 public final int getStartPosition() {
2570 return this.startPosition;
2574 * Returns the length in characters of the original source file indicating
2575 * where the source fragment corresponding to this node ends.
2577 * The parser supplies useful well-defined source ranges to the nodes it creates.
2578 * See {@link ASTParser#setKind(int)} methods for details
2579 * on precisely where source ranges begin and end.
2582 * @return a (possibly 0) length, or <code>0</code>
2583 * if no source position information is recorded for this node
2584 * @see #getStartPosition()
2587 public final int getLength() {
2592 * Sets the source range of the original source file where the source
2593 * fragment corresponding to this node was found.
2595 * See {@link ASTParser#setKind(int)} for details
2596 * on precisely where source ranges are supposed to begin and end.
2599 * @param startPosition a 0-based character index,
2600 * or <code>-1</code> if no source position information is
2601 * available for this node
2602 * @param length a (possibly 0) length,
2603 * or <code>0</code> if no source position information is recorded
2605 * @see #getStartPosition()
2609 public final void setSourceRange(int startPosition, int length) {
2610 if (startPosition >= 0 && length < 0) {
2611 throw new IllegalArgumentException();
2613 if (startPosition < 0 && length != 0) {
2614 throw new IllegalArgumentException();
2616 // source positions are not considered a structural property
2617 // but we protect them nevertheless
2619 this.startPosition = startPosition;
2620 this.length = length;
2624 * Returns a string representation of this node suitable for debugging
2627 * @return a debug string
2629 public final String toString() {
2630 StringBuffer buffer = new StringBuffer();
2631 int p = buffer.length();
2633 appendDebugString(buffer);
2634 } catch (RuntimeException e) {
2635 // since debugger sometimes call toString methods, problems can easily happen when
2636 // toString is called on an instance that is being initialized
2637 buffer.setLength(p);
2638 buffer.append("!"); //$NON-NLS-1$
2639 buffer.append(standardToString());
2641 return buffer.toString();
2645 * Returns the string representation of this node produced by the standard
2646 * <code>Object.toString</code> method.
2648 * @return a debug string
2650 final String standardToString() {
2651 return super.toString();
2655 * Appends a debug representation of this node to the given string buffer.
2657 * The <code>ASTNode</code> implementation of this method prints out the entire
2658 * subtree. Subclasses may override to provide a more succinct representation.
2661 * @param buffer the string buffer to append to
2663 void appendDebugString(StringBuffer buffer) {
2664 // print the subtree by default
2665 appendPrintString(buffer);
2669 * Appends a standard Java source code representation of this subtree to the given
2672 * @param buffer the string buffer to append to
2674 final void appendPrintString(StringBuffer buffer) {
2675 NaiveASTFlattener printer = new NaiveASTFlattener();
2676 this.accept(printer);
2677 buffer.append(printer.getResult());
2681 * Estimate of size of an object header in bytes.
2683 static final int HEADERS = 12;
2686 * Approximate base size of an AST node instance in bytes,
2687 * including object header and instance fields.
2688 * That is, HEADERS + (# instance vars in ASTNode)*4.
2690 static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
2693 * Returns an estimate of the memory footprint, in bytes,
2694 * of the given string.
2696 * @param string the string to measure, or <code>null</code>
2697 * @return the size of this string object in bytes, or
2698 * 0 if the string is <code>null</code>
2701 static int stringSize(String string) {
2703 if (string != null) {
2704 // Strings usually have 4 instance fields, one of which is a char[]
2705 size += HEADERS + 4 * 4;
2706 // char[] has 2 bytes per character
2707 size += HEADERS + 2 * string.length();
2713 * Returns an estimate of the memory footprint in bytes of the entire
2714 * subtree rooted at this node.
2716 * @return the size of this subtree in bytes
2718 public final int subtreeBytes() {
2723 * Returns an estimate of the memory footprint in bytes of the entire
2724 * subtree rooted at this node.
2726 * N.B. This method is package-private, so that the implementations
2727 * of this method in each of the concrete AST node types do not
2728 * clutter up the API doc.
2731 * @return the size of this subtree in bytes
2733 abstract int treeSize();
2736 * Returns an estimate of the memory footprint of this node in bytes.
2737 * The estimate does not include the space occupied by child nodes.
2739 * @return the size of this node in bytes
2741 abstract int memSize();