0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.core.dom;
0011:
0012: import java.util.AbstractList;
0013: import java.util.ArrayList;
0014: import java.util.Collections;
0015: import java.util.HashMap;
0016: import java.util.Iterator;
0017: import java.util.List;
0018: import java.util.Map;
0019:
0020: /**
0021: * Abstract superclass of all Abstract Syntax Tree (AST) node types.
0022: * <p>
0023: * An AST node represents a Java source code construct, such
0024: * as a name, type, expression, statement, or declaration.
0025: * </p>
0026: * <p>
0027: * Each AST node belongs to a unique AST instance, called the owning AST.
0028: * The children of an AST node always have the same owner as their parent node.
0029: * If a node from one AST is to be added to a different AST, the subtree must
0030: * be cloned first to ensure that the added nodes have the correct owning AST.
0031: * </p>
0032: * <p>
0033: * When an AST node is part of an AST, it has a unique parent node.
0034: * Clients can navigate upwards, from child to parent, as well as downwards,
0035: * from parent to child. Newly created nodes are unparented. When an
0036: * unparented node is set as a child of a node (using a
0037: * <code>set<i>CHILD</i></code> method), its parent link is set automatically
0038: * and the parent link of the former child is set to <code>null</code>.
0039: * For nodes with properties that include a list of children (for example,
0040: * <code>Block</code> whose <code>statements</code> property is a list
0041: * of statements), adding or removing an element to/for the list property
0042: * automatically updates the parent links. These lists support the
0043: * <code>List.set</code> method; however, the constraint that the same
0044: * node cannot appear more than once means that this method cannot be used
0045: * to swap elements without first removing the node.
0046: * </p>
0047: * <p>
0048: * ASTs must not contain cycles. All operations that could create a cycle
0049: * detect this possibility and fail.
0050: * </p>
0051: * <p>
0052: * ASTs do not contain "holes" (missing subtrees). If a node is required to
0053: * have a certain property, a syntactically plausible initial value is
0054: * always supplied.
0055: * </p>
0056: * <p>
0057: * The hierarchy of AST node types has some convenient groupings marked
0058: * by abstract superclasses:
0059: * <ul>
0060: * <li>expressions - <code>Expression</code></li>
0061: * <li>names - <code>Name</code> (a sub-kind of expression)</li>
0062: * <li>statements - <code>Statement</code></li>
0063: * <li>types - <code>Type</code></li>
0064: * <li>type body declarations - <code>BodyDeclaration</code></li>
0065: * </ul>
0066: * </p>
0067: * <p>
0068: * Abstract syntax trees may be hand constructed by clients, using the
0069: * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to
0070: * create new nodes, and the various <code>set<i>CHILD</i></code> methods
0071: * to connect them together.
0072: * </p>
0073: * <p>
0074: * The class {@link ASTParser} parses a string
0075: * containing a Java source code and returns an abstract syntax tree
0076: * for it. The resulting nodes carry source ranges relating the node back to
0077: * the original source characters. The source range covers the construct
0078: * as a whole.
0079: * </p>
0080: * <p>
0081: * Each AST node carries bit flags, which may convey additional information about
0082: * the node. For instance, the parser uses a flag to indicate a syntax error.
0083: * Newly created nodes have no flags set.
0084: * </p>
0085: * <p>
0086: * Each AST node is capable of carrying an open-ended collection of
0087: * client-defined properties. Newly created nodes have none.
0088: * <code>getProperty</code> and <code>setProperty</code> are used to access
0089: * these properties.
0090: * </p>
0091: * <p>
0092: * AST nodes are thread-safe for readers provided there are no active writers.
0093: * If one thread is modifying an AST, including creating new nodes or cloning
0094: * existing ones, it is <b>not</b> safe for another thread to read, visit,
0095: * write, create, or clone <em>any</em> of the nodes on the same AST.
0096: * When synchronization is required, consider using the common AST
0097: * object that owns the node; that is, use
0098: * <code>synchronize (node.getAST()) {...}</code>.
0099: * </p>
0100: * <p>
0101: * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
0102: * for details.
0103: * </p>
0104: * <p>
0105: * Compilation units created by <code>ASTParser</code> from a
0106: * source document can be serialized after arbitrary modifications
0107: * with minimal loss of original formatting. See
0108: * {@link CompilationUnit#recordModifications()} for details.
0109: * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
0110: * an alternative way to describe and serialize changes to a
0111: * read-only AST.
0112: * </p>
0113: * This class is not intended to be subclassed by clients.
0114: *
0115: * @see ASTParser
0116: * @see ASTVisitor
0117: * @since 2.0
0118: */
0119: public abstract class ASTNode {
0120: /*
0121: * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
0122: *
0123: * There are several things that need to be changed when a
0124: * new concrete AST node type (call it "FooBar"):
0125: *
0126: * 1. Create the FooBar AST node type class.
0127: * The most effective way to do this is to copy a similar
0128: * existing concrete node class to get a template that
0129: * includes all the framework methods that must be implemented.
0130: *
0131: * 2. Add node type constant ASTNode.FOO_BAR.
0132: * Node constants are numbered consecutively. Add the
0133: * constant after the existing ones.
0134: *
0135: * 3. Add entry to ASTNode.nodeClassForType(int).
0136: *
0137: * 4. Add AST.newFooBar() factory method.
0138: *
0139: * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
0140: *
0141: * 6. Add ASTMatcher.match(FooBar,Object) method.
0142: *
0143: * 7. Ensure that SimpleName.isDeclaration() covers FooBar
0144: * nodes if required.
0145: *
0146: * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
0147: * how these nodes should be serialized.
0148: *
0149: * 9. Update the AST test suites.
0150: *
0151: * The next steps are to update AST.parse* to start generating
0152: * the new type of nodes, and ASTRewrite to serialize them back out.
0153: */
0154:
0155: /**
0156: * Node type constant indicating a node of type
0157: * <code>AnonymousClassDeclaration</code>.
0158: * @see AnonymousClassDeclaration
0159: */
0160: public static final int ANONYMOUS_CLASS_DECLARATION = 1;
0161:
0162: /**
0163: * Node type constant indicating a node of type
0164: * <code>ArrayAccess</code>.
0165: * @see ArrayAccess
0166: */
0167: public static final int ARRAY_ACCESS = 2;
0168:
0169: /**
0170: * Node type constant indicating a node of type
0171: * <code>ArrayCreation</code>.
0172: * @see ArrayCreation
0173: */
0174: public static final int ARRAY_CREATION = 3;
0175:
0176: /**
0177: * Node type constant indicating a node of type
0178: * <code>ArrayInitializer</code>.
0179: * @see ArrayInitializer
0180: */
0181: public static final int ARRAY_INITIALIZER = 4;
0182:
0183: /**
0184: * Node type constant indicating a node of type
0185: * <code>ArrayType</code>.
0186: * @see ArrayType
0187: */
0188: public static final int ARRAY_TYPE = 5;
0189:
0190: /**
0191: * Node type constant indicating a node of type
0192: * <code>AssertStatement</code>.
0193: * @see AssertStatement
0194: */
0195: public static final int ASSERT_STATEMENT = 6;
0196:
0197: /**
0198: * Node type constant indicating a node of type
0199: * <code>Assignment</code>.
0200: * @see Assignment
0201: */
0202: public static final int ASSIGNMENT = 7;
0203:
0204: /**
0205: * Node type constant indicating a node of type
0206: * <code>Block</code>.
0207: * @see Block
0208: */
0209: public static final int BLOCK = 8;
0210:
0211: /**
0212: * Node type constant indicating a node of type
0213: * <code>BooleanLiteral</code>.
0214: * @see BooleanLiteral
0215: */
0216: public static final int BOOLEAN_LITERAL = 9;
0217:
0218: /**
0219: * Node type constant indicating a node of type
0220: * <code>BreakStatement</code>.
0221: * @see BreakStatement
0222: */
0223: public static final int BREAK_STATEMENT = 10;
0224:
0225: /**
0226: * Node type constant indicating a node of type
0227: * <code>CastExpression</code>.
0228: * @see CastExpression
0229: */
0230: public static final int CAST_EXPRESSION = 11;
0231:
0232: /**
0233: * Node type constant indicating a node of type
0234: * <code>CatchClause</code>.
0235: * @see CatchClause
0236: */
0237: public static final int CATCH_CLAUSE = 12;
0238:
0239: /**
0240: * Node type constant indicating a node of type
0241: * <code>CharacterLiteral</code>.
0242: * @see CharacterLiteral
0243: */
0244: public static final int CHARACTER_LITERAL = 13;
0245:
0246: /**
0247: * Node type constant indicating a node of type
0248: * <code>ClassInstanceCreation</code>.
0249: * @see ClassInstanceCreation
0250: */
0251: public static final int CLASS_INSTANCE_CREATION = 14;
0252:
0253: /**
0254: * Node type constant indicating a node of type
0255: * <code>CompilationUnit</code>.
0256: * @see CompilationUnit
0257: */
0258: public static final int COMPILATION_UNIT = 15;
0259:
0260: /**
0261: * Node type constant indicating a node of type
0262: * <code>ConditionalExpression</code>.
0263: * @see ConditionalExpression
0264: */
0265: public static final int CONDITIONAL_EXPRESSION = 16;
0266:
0267: /**
0268: * Node type constant indicating a node of type
0269: * <code>ConstructorInvocation</code>.
0270: * @see ConstructorInvocation
0271: */
0272: public static final int CONSTRUCTOR_INVOCATION = 17;
0273:
0274: /**
0275: * Node type constant indicating a node of type
0276: * <code>ContinueStatement</code>.
0277: * @see ContinueStatement
0278: */
0279: public static final int CONTINUE_STATEMENT = 18;
0280:
0281: /**
0282: * Node type constant indicating a node of type
0283: * <code>DoStatement</code>.
0284: * @see DoStatement
0285: */
0286: public static final int DO_STATEMENT = 19;
0287:
0288: /**
0289: * Node type constant indicating a node of type
0290: * <code>EmptyStatement</code>.
0291: * @see EmptyStatement
0292: */
0293: public static final int EMPTY_STATEMENT = 20;
0294:
0295: /**
0296: * Node type constant indicating a node of type
0297: * <code>ExpressionStatement</code>.
0298: * @see ExpressionStatement
0299: */
0300: public static final int EXPRESSION_STATEMENT = 21;
0301:
0302: /**
0303: * Node type constant indicating a node of type
0304: * <code>FieldAccess</code>.
0305: * @see FieldAccess
0306: */
0307: public static final int FIELD_ACCESS = 22;
0308:
0309: /**
0310: * Node type constant indicating a node of type
0311: * <code>FieldDeclaration</code>.
0312: * @see FieldDeclaration
0313: */
0314: public static final int FIELD_DECLARATION = 23;
0315:
0316: /**
0317: * Node type constant indicating a node of type
0318: * <code>ForStatement</code>.
0319: * @see ForStatement
0320: */
0321: public static final int FOR_STATEMENT = 24;
0322:
0323: /**
0324: * Node type constant indicating a node of type
0325: * <code>IfStatement</code>.
0326: * @see IfStatement
0327: */
0328: public static final int IF_STATEMENT = 25;
0329:
0330: /**
0331: * Node type constant indicating a node of type
0332: * <code>ImportDeclaration</code>.
0333: * @see ImportDeclaration
0334: */
0335: public static final int IMPORT_DECLARATION = 26;
0336:
0337: /**
0338: * Node type constant indicating a node of type
0339: * <code>InfixExpression</code>.
0340: * @see InfixExpression
0341: */
0342: public static final int INFIX_EXPRESSION = 27;
0343:
0344: /**
0345: * Node type constant indicating a node of type
0346: * <code>Initializer</code>.
0347: * @see Initializer
0348: */
0349: public static final int INITIALIZER = 28;
0350:
0351: /**
0352: * Node type constant indicating a node of type
0353: * <code>Javadoc</code>.
0354: * @see Javadoc
0355: */
0356: public static final int JAVADOC = 29;
0357:
0358: /**
0359: * Node type constant indicating a node of type
0360: * <code>LabeledStatement</code>.
0361: * @see LabeledStatement
0362: */
0363: public static final int LABELED_STATEMENT = 30;
0364:
0365: /**
0366: * Node type constant indicating a node of type
0367: * <code>MethodDeclaration</code>.
0368: * @see MethodDeclaration
0369: */
0370: public static final int METHOD_DECLARATION = 31;
0371:
0372: /**
0373: * Node type constant indicating a node of type
0374: * <code>MethodInvocation</code>.
0375: * @see MethodInvocation
0376: */
0377: public static final int METHOD_INVOCATION = 32;
0378:
0379: /**
0380: * Node type constant indicating a node of type
0381: * <code>NullLiteral</code>.
0382: * @see NullLiteral
0383: */
0384: public static final int NULL_LITERAL = 33;
0385:
0386: /**
0387: * Node type constant indicating a node of type
0388: * <code>NumberLiteral</code>.
0389: * @see NumberLiteral
0390: */
0391: public static final int NUMBER_LITERAL = 34;
0392:
0393: /**
0394: * Node type constant indicating a node of type
0395: * <code>PackageDeclaration</code>.
0396: * @see PackageDeclaration
0397: */
0398: public static final int PACKAGE_DECLARATION = 35;
0399:
0400: /**
0401: * Node type constant indicating a node of type
0402: * <code>ParenthesizedExpression</code>.
0403: * @see ParenthesizedExpression
0404: */
0405: public static final int PARENTHESIZED_EXPRESSION = 36;
0406:
0407: /**
0408: * Node type constant indicating a node of type
0409: * <code>PostfixExpression</code>.
0410: * @see PostfixExpression
0411: */
0412: public static final int POSTFIX_EXPRESSION = 37;
0413:
0414: /**
0415: * Node type constant indicating a node of type
0416: * <code>PrefixExpression</code>.
0417: * @see PrefixExpression
0418: */
0419: public static final int PREFIX_EXPRESSION = 38;
0420:
0421: /**
0422: * Node type constant indicating a node of type
0423: * <code>PrimitiveType</code>.
0424: * @see PrimitiveType
0425: */
0426: public static final int PRIMITIVE_TYPE = 39;
0427:
0428: /**
0429: * Node type constant indicating a node of type
0430: * <code>QualifiedName</code>.
0431: * @see QualifiedName
0432: */
0433: public static final int QUALIFIED_NAME = 40;
0434:
0435: /**
0436: * Node type constant indicating a node of type
0437: * <code>ReturnStatement</code>.
0438: * @see ReturnStatement
0439: */
0440: public static final int RETURN_STATEMENT = 41;
0441:
0442: /**
0443: * Node type constant indicating a node of type
0444: * <code>SimpleName</code>.
0445: * @see SimpleName
0446: */
0447: public static final int SIMPLE_NAME = 42;
0448:
0449: /**
0450: * Node type constant indicating a node of type
0451: * <code>SimpleType</code>.
0452: * @see SimpleType
0453: */
0454: public static final int SIMPLE_TYPE = 43;
0455:
0456: /**
0457: * Node type constant indicating a node of type
0458: * <code>SingleVariableDeclaration</code>.
0459: * @see SingleVariableDeclaration
0460: */
0461: public static final int SINGLE_VARIABLE_DECLARATION = 44;
0462:
0463: /**
0464: * Node type constant indicating a node of type
0465: * <code>StringLiteral</code>.
0466: * @see StringLiteral
0467: */
0468: public static final int STRING_LITERAL = 45;
0469:
0470: /**
0471: * Node type constant indicating a node of type
0472: * <code>SuperConstructorInvocation</code>.
0473: * @see SuperConstructorInvocation
0474: */
0475: public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
0476:
0477: /**
0478: * Node type constant indicating a node of type
0479: * <code>SuperFieldAccess</code>.
0480: * @see SuperFieldAccess
0481: */
0482: public static final int SUPER_FIELD_ACCESS = 47;
0483:
0484: /**
0485: * Node type constant indicating a node of type
0486: * <code>SuperMethodInvocation</code>.
0487: * @see SuperMethodInvocation
0488: */
0489: public static final int SUPER_METHOD_INVOCATION = 48;
0490:
0491: /**
0492: * Node type constant indicating a node of type
0493: * <code>SwitchCase</code>.
0494: * @see SwitchCase
0495: */
0496: public static final int SWITCH_CASE = 49;
0497:
0498: /**
0499: * Node type constant indicating a node of type
0500: * <code>SwitchStatement</code>.
0501: * @see SwitchStatement
0502: */
0503: public static final int SWITCH_STATEMENT = 50;
0504:
0505: /**
0506: * Node type constant indicating a node of type
0507: * <code>SynchronizedStatement</code>.
0508: * @see SynchronizedStatement
0509: */
0510: public static final int SYNCHRONIZED_STATEMENT = 51;
0511:
0512: /**
0513: * Node type constant indicating a node of type
0514: * <code>ThisExpression</code>.
0515: * @see ThisExpression
0516: */
0517: public static final int THIS_EXPRESSION = 52;
0518:
0519: /**
0520: * Node type constant indicating a node of type
0521: * <code>ThrowStatement</code>.
0522: * @see ThrowStatement
0523: */
0524: public static final int THROW_STATEMENT = 53;
0525:
0526: /**
0527: * Node type constant indicating a node of type
0528: * <code>TryStatement</code>.
0529: * @see TryStatement
0530: */
0531: public static final int TRY_STATEMENT = 54;
0532:
0533: /**
0534: * Node type constant indicating a node of type
0535: * <code>TypeDeclaration</code>.
0536: * @see TypeDeclaration
0537: */
0538: public static final int TYPE_DECLARATION = 55;
0539:
0540: /**
0541: * Node type constant indicating a node of type
0542: * <code>TypeDeclarationStatement</code>.
0543: * @see TypeDeclarationStatement
0544: */
0545: public static final int TYPE_DECLARATION_STATEMENT = 56;
0546:
0547: /**
0548: * Node type constant indicating a node of type
0549: * <code>TypeLiteral</code>.
0550: * @see TypeLiteral
0551: */
0552: public static final int TYPE_LITERAL = 57;
0553:
0554: /**
0555: * Node type constant indicating a node of type
0556: * <code>VariableDeclarationExpression</code>.
0557: * @see VariableDeclarationExpression
0558: */
0559: public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
0560:
0561: /**
0562: * Node type constant indicating a node of type
0563: * <code>VariableDeclarationFragment</code>.
0564: * @see VariableDeclarationFragment
0565: */
0566: public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
0567:
0568: /**
0569: * Node type constant indicating a node of type
0570: * <code>VariableDeclarationStatement</code>.
0571: * @see VariableDeclarationStatement
0572: */
0573: public static final int VARIABLE_DECLARATION_STATEMENT = 60;
0574:
0575: /**
0576: * Node type constant indicating a node of type
0577: * <code>WhileStatement</code>.
0578: * @see WhileStatement
0579: */
0580: public static final int WHILE_STATEMENT = 61;
0581:
0582: /**
0583: * Node type constant indicating a node of type
0584: * <code>InstanceofExpression</code>.
0585: * @see InstanceofExpression
0586: */
0587: public static final int INSTANCEOF_EXPRESSION = 62;
0588:
0589: /**
0590: * Node type constant indicating a node of type
0591: * <code>LineComment</code>.
0592: * @see LineComment
0593: * @since 3.0
0594: */
0595: public static final int LINE_COMMENT = 63;
0596:
0597: /**
0598: * Node type constant indicating a node of type
0599: * <code>BlockComment</code>.
0600: * @see BlockComment
0601: * @since 3.0
0602: */
0603: public static final int BLOCK_COMMENT = 64;
0604:
0605: /**
0606: * Node type constant indicating a node of type
0607: * <code>TagElement</code>.
0608: * @see TagElement
0609: * @since 3.0
0610: */
0611: public static final int TAG_ELEMENT = 65;
0612:
0613: /**
0614: * Node type constant indicating a node of type
0615: * <code>TextElement</code>.
0616: * @see TextElement
0617: * @since 3.0
0618: */
0619: public static final int TEXT_ELEMENT = 66;
0620:
0621: /**
0622: * Node type constant indicating a node of type
0623: * <code>MemberRef</code>.
0624: * @see MemberRef
0625: * @since 3.0
0626: */
0627: public static final int MEMBER_REF = 67;
0628:
0629: /**
0630: * Node type constant indicating a node of type
0631: * <code>MethodRef</code>.
0632: * @see MethodRef
0633: * @since 3.0
0634: */
0635: public static final int METHOD_REF = 68;
0636:
0637: /**
0638: * Node type constant indicating a node of type
0639: * <code>MethodRefParameter</code>.
0640: * @see MethodRefParameter
0641: * @since 3.0
0642: */
0643: public static final int METHOD_REF_PARAMETER = 69;
0644:
0645: /**
0646: * Node type constant indicating a node of type
0647: * <code>EnhancedForStatement</code>.
0648: * @see EnhancedForStatement
0649: * @since 3.1
0650: */
0651: public static final int ENHANCED_FOR_STATEMENT = 70;
0652:
0653: /**
0654: * Node type constant indicating a node of type
0655: * <code>EnumDeclaration</code>.
0656: * @see EnumDeclaration
0657: * @since 3.1
0658: */
0659: public static final int ENUM_DECLARATION = 71;
0660:
0661: /**
0662: * Node type constant indicating a node of type
0663: * <code>EnumConstantDeclaration</code>.
0664: * @see EnumConstantDeclaration
0665: * @since 3.1
0666: */
0667: public static final int ENUM_CONSTANT_DECLARATION = 72;
0668:
0669: /**
0670: * Node type constant indicating a node of type
0671: * <code>TypeParameter</code>.
0672: * @see TypeParameter
0673: * @since 3.1
0674: */
0675: public static final int TYPE_PARAMETER = 73;
0676:
0677: /**
0678: * Node type constant indicating a node of type
0679: * <code>ParameterizedType</code>.
0680: * @see ParameterizedType
0681: * @since 3.1
0682: */
0683: public static final int PARAMETERIZED_TYPE = 74;
0684:
0685: /**
0686: * Node type constant indicating a node of type
0687: * <code>QualifiedType</code>.
0688: * @see QualifiedType
0689: * @since 3.1
0690: */
0691: public static final int QUALIFIED_TYPE = 75;
0692:
0693: /**
0694: * Node type constant indicating a node of type
0695: * <code>WildcardType</code>.
0696: * @see WildcardType
0697: * @since 3.1
0698: */
0699: public static final int WILDCARD_TYPE = 76;
0700:
0701: /**
0702: * Node type constant indicating a node of type
0703: * <code>NormalAnnotation</code>.
0704: * @see NormalAnnotation
0705: * @since 3.1
0706: */
0707: public static final int NORMAL_ANNOTATION = 77;
0708:
0709: /**
0710: * Node type constant indicating a node of type
0711: * <code>MarkerAnnotation</code>.
0712: * @see MarkerAnnotation
0713: * @since 3.1
0714: */
0715: public static final int MARKER_ANNOTATION = 78;
0716:
0717: /**
0718: * Node type constant indicating a node of type
0719: * <code>SingleMemberAnnotation</code>.
0720: * @see SingleMemberAnnotation
0721: * @since 3.1
0722: */
0723: public static final int SINGLE_MEMBER_ANNOTATION = 79;
0724:
0725: /**
0726: * Node type constant indicating a node of type
0727: * <code>MemberValuePair</code>.
0728: * @see MemberValuePair
0729: * @since 3.1
0730: */
0731: public static final int MEMBER_VALUE_PAIR = 80;
0732:
0733: /**
0734: * Node type constant indicating a node of type
0735: * <code>AnnotationTypeDeclaration</code>.
0736: * @see AnnotationTypeDeclaration
0737: * @since 3.1
0738: */
0739: public static final int ANNOTATION_TYPE_DECLARATION = 81;
0740:
0741: /**
0742: * Node type constant indicating a node of type
0743: * <code>AnnotationTypeMemberDeclaration</code>.
0744: * @see AnnotationTypeMemberDeclaration
0745: * @since 3.1
0746: */
0747: public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82;
0748:
0749: /**
0750: * Node type constant indicating a node of type
0751: * <code>Modifier</code>.
0752: * @see Modifier
0753: * @since 3.1
0754: */
0755: public static final int MODIFIER = 83;
0756:
0757: /**
0758: * Returns the node class for the corresponding node type.
0759: *
0760: * @param nodeType AST node type
0761: * @return the corresponding <code>ASTNode</code> subclass
0762: * @exception IllegalArgumentException if <code>nodeType</code> is
0763: * not a legal AST node type
0764: * @see #getNodeType()
0765: * @since 3.0
0766: */
0767: public static Class nodeClassForType(int nodeType) {
0768: switch (nodeType) {
0769: case ANNOTATION_TYPE_DECLARATION:
0770: return AnnotationTypeDeclaration.class;
0771: case ANNOTATION_TYPE_MEMBER_DECLARATION:
0772: return AnnotationTypeMemberDeclaration.class;
0773: case ANONYMOUS_CLASS_DECLARATION:
0774: return AnonymousClassDeclaration.class;
0775: case ARRAY_ACCESS:
0776: return ArrayAccess.class;
0777: case ARRAY_CREATION:
0778: return ArrayCreation.class;
0779: case ARRAY_INITIALIZER:
0780: return ArrayInitializer.class;
0781: case ARRAY_TYPE:
0782: return ArrayType.class;
0783: case ASSERT_STATEMENT:
0784: return AssertStatement.class;
0785: case ASSIGNMENT:
0786: return Assignment.class;
0787: case BLOCK:
0788: return Block.class;
0789: case BLOCK_COMMENT:
0790: return BlockComment.class;
0791: case BOOLEAN_LITERAL:
0792: return BooleanLiteral.class;
0793: case BREAK_STATEMENT:
0794: return BreakStatement.class;
0795: case CAST_EXPRESSION:
0796: return CastExpression.class;
0797: case CATCH_CLAUSE:
0798: return CatchClause.class;
0799: case CHARACTER_LITERAL:
0800: return CharacterLiteral.class;
0801: case CLASS_INSTANCE_CREATION:
0802: return ClassInstanceCreation.class;
0803: case COMPILATION_UNIT:
0804: return CompilationUnit.class;
0805: case CONDITIONAL_EXPRESSION:
0806: return ConditionalExpression.class;
0807: case CONSTRUCTOR_INVOCATION:
0808: return ConstructorInvocation.class;
0809: case CONTINUE_STATEMENT:
0810: return ContinueStatement.class;
0811: case DO_STATEMENT:
0812: return DoStatement.class;
0813: case EMPTY_STATEMENT:
0814: return EmptyStatement.class;
0815: case ENHANCED_FOR_STATEMENT:
0816: return EnhancedForStatement.class;
0817: case ENUM_CONSTANT_DECLARATION:
0818: return EnumConstantDeclaration.class;
0819: case ENUM_DECLARATION:
0820: return EnumDeclaration.class;
0821: case EXPRESSION_STATEMENT:
0822: return ExpressionStatement.class;
0823: case FIELD_ACCESS:
0824: return FieldAccess.class;
0825: case FIELD_DECLARATION:
0826: return FieldDeclaration.class;
0827: case FOR_STATEMENT:
0828: return ForStatement.class;
0829: case IF_STATEMENT:
0830: return IfStatement.class;
0831: case IMPORT_DECLARATION:
0832: return ImportDeclaration.class;
0833: case INFIX_EXPRESSION:
0834: return InfixExpression.class;
0835: case INITIALIZER:
0836: return Initializer.class;
0837: case INSTANCEOF_EXPRESSION:
0838: return InstanceofExpression.class;
0839: case JAVADOC:
0840: return Javadoc.class;
0841: case LABELED_STATEMENT:
0842: return LabeledStatement.class;
0843: case LINE_COMMENT:
0844: return LineComment.class;
0845: case MARKER_ANNOTATION:
0846: return MarkerAnnotation.class;
0847: case MEMBER_REF:
0848: return MemberRef.class;
0849: case MEMBER_VALUE_PAIR:
0850: return MemberValuePair.class;
0851: case METHOD_DECLARATION:
0852: return MethodDeclaration.class;
0853: case METHOD_INVOCATION:
0854: return MethodInvocation.class;
0855: case METHOD_REF:
0856: return MethodRef.class;
0857: case METHOD_REF_PARAMETER:
0858: return MethodRefParameter.class;
0859: case MODIFIER:
0860: return Modifier.class;
0861: case NORMAL_ANNOTATION:
0862: return NormalAnnotation.class;
0863: case NULL_LITERAL:
0864: return NullLiteral.class;
0865: case NUMBER_LITERAL:
0866: return NumberLiteral.class;
0867: case PACKAGE_DECLARATION:
0868: return PackageDeclaration.class;
0869: case PARAMETERIZED_TYPE:
0870: return ParameterizedType.class;
0871: case PARENTHESIZED_EXPRESSION:
0872: return ParenthesizedExpression.class;
0873: case POSTFIX_EXPRESSION:
0874: return PostfixExpression.class;
0875: case PREFIX_EXPRESSION:
0876: return PrefixExpression.class;
0877: case PRIMITIVE_TYPE:
0878: return PrimitiveType.class;
0879: case QUALIFIED_NAME:
0880: return QualifiedName.class;
0881: case QUALIFIED_TYPE:
0882: return QualifiedType.class;
0883: case RETURN_STATEMENT:
0884: return ReturnStatement.class;
0885: case SIMPLE_NAME:
0886: return SimpleName.class;
0887: case SIMPLE_TYPE:
0888: return SimpleType.class;
0889: case SINGLE_MEMBER_ANNOTATION:
0890: return SingleMemberAnnotation.class;
0891: case SINGLE_VARIABLE_DECLARATION:
0892: return SingleVariableDeclaration.class;
0893: case STRING_LITERAL:
0894: return StringLiteral.class;
0895: case SUPER_CONSTRUCTOR_INVOCATION:
0896: return SuperConstructorInvocation.class;
0897: case SUPER_FIELD_ACCESS:
0898: return SuperFieldAccess.class;
0899: case SUPER_METHOD_INVOCATION:
0900: return SuperMethodInvocation.class;
0901: case SWITCH_CASE:
0902: return SwitchCase.class;
0903: case SWITCH_STATEMENT:
0904: return SwitchStatement.class;
0905: case SYNCHRONIZED_STATEMENT:
0906: return SynchronizedStatement.class;
0907: case TAG_ELEMENT:
0908: return TagElement.class;
0909: case TEXT_ELEMENT:
0910: return TextElement.class;
0911: case THIS_EXPRESSION:
0912: return ThisExpression.class;
0913: case THROW_STATEMENT:
0914: return ThrowStatement.class;
0915: case TRY_STATEMENT:
0916: return TryStatement.class;
0917: case TYPE_DECLARATION:
0918: return TypeDeclaration.class;
0919: case TYPE_DECLARATION_STATEMENT:
0920: return TypeDeclarationStatement.class;
0921: case TYPE_LITERAL:
0922: return TypeLiteral.class;
0923: case TYPE_PARAMETER:
0924: return TypeParameter.class;
0925: case VARIABLE_DECLARATION_EXPRESSION:
0926: return VariableDeclarationExpression.class;
0927: case VARIABLE_DECLARATION_FRAGMENT:
0928: return VariableDeclarationFragment.class;
0929: case VARIABLE_DECLARATION_STATEMENT:
0930: return VariableDeclarationStatement.class;
0931: case WHILE_STATEMENT:
0932: return WhileStatement.class;
0933: case WILDCARD_TYPE:
0934: return WildcardType.class;
0935: }
0936: throw new IllegalArgumentException();
0937: }
0938:
0939: /**
0940: * Owning AST.
0941: * <p>
0942: * N.B. This ia a private field, but declared as package-visible
0943: * for more efficient access from inner classes.
0944: * </p>
0945: */
0946: final AST ast;
0947:
0948: /**
0949: * Parent AST node, or <code>null</code> if this node is a root.
0950: * Initially <code>null</code>.
0951: */
0952: private ASTNode parent = null;
0953:
0954: /**
0955: * An unmodifiable empty map (used to implement <code>properties()</code>).
0956: */
0957: private static final Map UNMODIFIABLE_EMPTY_MAP = Collections
0958: .unmodifiableMap(new HashMap(1));
0959:
0960: /**
0961: * Primary field used in representing node properties efficiently.
0962: * If <code>null</code>, this node has no properties.
0963: * If a <code>String</code>, this is the name of this node's sole property,
0964: * and <code>property2</code> contains its value.
0965: * If a <code>HashMap</code>, this is the table of property name-value
0966: * mappings; <code>property2</code>, if non-null is its unmodifiable
0967: * equivalent.
0968: * Initially <code>null</code>.
0969: *
0970: * @see #property2
0971: */
0972: private Object property1 = null;
0973:
0974: /**
0975: * Auxillary field used in representing node properties efficiently.
0976: *
0977: * @see #property1
0978: */
0979: private Object property2 = null;
0980:
0981: /**
0982: * A character index into the original source string,
0983: * or <code>-1</code> if no source position information is available
0984: * for this node; <code>-1</code> by default.
0985: */
0986: private int startPosition = -1;
0987:
0988: /**
0989: * A character length, or <code>0</code> if no source position
0990: * information is recorded for this node; <code>0</code> by default.
0991: */
0992: private int length = 0;
0993:
0994: /**
0995: * Flag constant (bit mask, value 1) indicating that there is something
0996: * not quite right with this AST node.
0997: * <p>
0998: * The standard parser (<code>ASTParser</code>) sets this
0999: * flag on a node to indicate a syntax error detected in the vicinity.
1000: * </p>
1001: */
1002: public static final int MALFORMED = 1;
1003:
1004: /**
1005: * Flag constant (bit mask, value 2) indicating that this is a node
1006: * that was created by the parser (as opposed to one created by another
1007: * party).
1008: * <p>
1009: * The standard parser (<code>ASTParser</code>) sets this
1010: * flag on the nodes it creates.
1011: * </p>
1012: * @since 3.0
1013: */
1014: public static final int ORIGINAL = 2;
1015:
1016: /**
1017: * Flag constant (bit mask, value 4) indicating that this node
1018: * is unmodifiable. When a node is marked unmodifiable, the
1019: * following operations result in a runtime exception:
1020: * <ul>
1021: * <li>Change a simple property of this node.</li>
1022: * <li>Add or remove a child node from this node.</li>
1023: * <li>Parent (or reparent) this node.</li>
1024: * </ul>
1025: * <p>
1026: * The standard parser (<code>ASTParser</code>) does not set
1027: * this flag on the nodes it creates. However, clients may set
1028: * this flag on a node to prevent further modification of the
1029: * its structural properties.
1030: * </p>
1031: * @since 3.0
1032: */
1033: public static final int PROTECT = 4;
1034:
1035: /**
1036: * Flag constant (bit mask, value 8) indicating that this node
1037: * or a part of this node is recovered from source that contains
1038: * a syntax error detected in the vicinity.
1039: * <p>
1040: * The standard parser (<code>ASTParser</code>) sets this
1041: * flag on a node to indicate a recovered node.
1042: * </p>
1043: * @since 3.2
1044: */
1045: public static final int RECOVERED = 8;
1046:
1047: /**
1048: * int containing the node type in the top 16 bits and
1049: * flags in the bottom 16 bits; none set by default.
1050: * <p>
1051: * N.B. This is a private field, but declared as package-visible
1052: * for more efficient access from inner classes.
1053: * </p>
1054: *
1055: * @see #MALFORMED
1056: */
1057: int typeAndFlags = 0;
1058:
1059: /**
1060: * Property of parent in which this node is a child, or <code>null</code>
1061: * if this node is a root. Initially <code>null</code>.
1062: *
1063: * @see #getLocationInParent
1064: * @since 3.0
1065: */
1066: private StructuralPropertyDescriptor location = null;
1067:
1068: /** Internal convenience constant indicating that there is definite risk of cycles.
1069: * @since 3.0
1070: */
1071: static final boolean CYCLE_RISK = true;
1072:
1073: /** Internal convenience constant indicating that there is no risk of cycles.
1074: * @since 3.0
1075: */
1076: static final boolean NO_CYCLE_RISK = false;
1077:
1078: /** Internal convenience constant indicating that a structural property is mandatory.
1079: * @since 3.0
1080: */
1081: static final boolean MANDATORY = true;
1082:
1083: /** Internal convenience constant indicating that a structural property is optional.
1084: * @since 3.0
1085: */
1086: static final boolean OPTIONAL = false;
1087:
1088: /**
1089: * A specialized implementation of a list of ASTNodes. The
1090: * implementation is based on an ArrayList.
1091: */
1092: class NodeList extends AbstractList {
1093:
1094: /**
1095: * The underlying list in which the nodes of this list are
1096: * stored (element type: <code>ASTNode</code>).
1097: * <p>
1098: * Be stingy on storage - assume that list will be empty.
1099: * </p>
1100: * <p>
1101: * This field declared default visibility (rather than private)
1102: * so that accesses from <code>NodeList.Cursor</code> do not require
1103: * a synthetic accessor method.
1104: * </p>
1105: */
1106: ArrayList store = new ArrayList(0);
1107:
1108: /**
1109: * The property descriptor for this list.
1110: */
1111: ChildListPropertyDescriptor propertyDescriptor;
1112:
1113: /**
1114: * A cursor for iterating over the elements of the list.
1115: * Does not lose its position if the list is changed during
1116: * the iteration.
1117: */
1118: class Cursor implements Iterator {
1119: /**
1120: * The position of the cursor between elements. If the value
1121: * is N, then the cursor sits between the element at positions
1122: * N-1 and N. Initially just before the first element of the
1123: * list.
1124: */
1125: private int position = 0;
1126:
1127: /* (non-Javadoc)
1128: * Method declared on <code>Iterator</code>.
1129: */
1130: public boolean hasNext() {
1131: return this .position < NodeList.this .store.size();
1132: }
1133:
1134: /* (non-Javadoc)
1135: * Method declared on <code>Iterator</code>.
1136: */
1137: public Object next() {
1138: Object result = NodeList.this .store.get(this .position);
1139: this .position++;
1140: return result;
1141: }
1142:
1143: /* (non-Javadoc)
1144: * Method declared on <code>Iterator</code>.
1145: */
1146: public void remove() {
1147: throw new UnsupportedOperationException();
1148: }
1149:
1150: /**
1151: * Adjusts this cursor to accomodate an add/remove at the given
1152: * index.
1153: *
1154: * @param index the position at which the element was added
1155: * or removed
1156: * @param delta +1 for add, and -1 for remove
1157: */
1158: void update(int index, int delta) {
1159: if (this .position > index) {
1160: // the cursor has passed the added or removed element
1161: this .position += delta;
1162: }
1163: }
1164: }
1165:
1166: /**
1167: * A list of currently active cursors (element type:
1168: * <code>Cursor</code>), or <code>null</code> if there are no
1169: * active cursors.
1170: * <p>
1171: * It is important for storage considerations to maintain the
1172: * null-means-empty invariant; otherwise, every NodeList instance
1173: * will waste a lot of space. A cursor is needed only for the duration
1174: * of a visit to the child nodes. Under normal circumstances, only a
1175: * single cursor is needed; multiple cursors are only required if there
1176: * are multiple visits going on at the same time.
1177: * </p>
1178: */
1179: private List cursors = null;
1180:
1181: /**
1182: * Creates a new empty list of nodes owned by this node.
1183: * This node will be the common parent of all nodes added to
1184: * this list.
1185: *
1186: * @param property the property descriptor
1187: * @since 3.0
1188: */
1189: NodeList(ChildListPropertyDescriptor property) {
1190: super ();
1191: this .propertyDescriptor = property;
1192: }
1193:
1194: /* (non-javadoc)
1195: * @see java.util.AbstractCollection#size()
1196: */
1197: public int size() {
1198: return this .store.size();
1199: }
1200:
1201: /* (non-javadoc)
1202: * @see AbstractList#get(int)
1203: */
1204: public Object get(int index) {
1205: return this .store.get(index);
1206: }
1207:
1208: /* (non-javadoc)
1209: * @see List#set(int, java.lang.Object)
1210: */
1211: public Object set(int index, Object element) {
1212: if (element == null) {
1213: throw new IllegalArgumentException();
1214: }
1215: if ((ASTNode.this .typeAndFlags & PROTECT) != 0) {
1216: // this node is protected => cannot gain or lose children
1217: throw new IllegalArgumentException(
1218: "AST node cannot be modified"); //$NON-NLS-1$
1219: }
1220: // delink old child from parent, and link new child to parent
1221: ASTNode newChild = (ASTNode) element;
1222: ASTNode oldChild = (ASTNode) this .store.get(index);
1223: if (oldChild == newChild) {
1224: return oldChild;
1225: }
1226: if ((oldChild.typeAndFlags & PROTECT) != 0) {
1227: // old child is protected => cannot be unparented
1228: throw new IllegalArgumentException(
1229: "AST node cannot be modified"); //$NON-NLS-1$
1230: }
1231: ASTNode.checkNewChild(ASTNode.this , newChild,
1232: this .propertyDescriptor.cycleRisk,
1233: this .propertyDescriptor.elementType);
1234: ASTNode.this .ast.preReplaceChildEvent(ASTNode.this ,
1235: oldChild, newChild, this .propertyDescriptor);
1236:
1237: Object result = this .store.set(index, newChild);
1238: // n.b. setParent will call ast.modifying()
1239: oldChild.setParent(null, null);
1240: newChild.setParent(ASTNode.this , this .propertyDescriptor);
1241: ASTNode.this .ast.postReplaceChildEvent(ASTNode.this ,
1242: oldChild, newChild, this .propertyDescriptor);
1243: return result;
1244: }
1245:
1246: /* (non-javadoc)
1247: * @see List#add(int, java.lang.Object)
1248: */
1249: public void add(int index, Object element) {
1250: if (element == null) {
1251: throw new IllegalArgumentException();
1252: }
1253: if ((ASTNode.this .typeAndFlags & PROTECT) != 0) {
1254: // this node is protected => cannot gain or lose children
1255: throw new IllegalArgumentException(
1256: "AST node cannot be modified"); //$NON-NLS-1$
1257: }
1258: // link new child to parent
1259: ASTNode newChild = (ASTNode) element;
1260: ASTNode.checkNewChild(ASTNode.this , newChild,
1261: this .propertyDescriptor.cycleRisk,
1262: this .propertyDescriptor.elementType);
1263: ASTNode.this .ast.preAddChildEvent(ASTNode.this , newChild,
1264: this .propertyDescriptor);
1265:
1266: this .store.add(index, element);
1267: updateCursors(index, +1);
1268: // n.b. setParent will call ast.modifying()
1269: newChild.setParent(ASTNode.this , this .propertyDescriptor);
1270: ASTNode.this .ast.postAddChildEvent(ASTNode.this , newChild,
1271: this .propertyDescriptor);
1272: }
1273:
1274: /* (non-javadoc)
1275: * @see List#remove(int)
1276: */
1277: public Object remove(int index) {
1278: if ((ASTNode.this .typeAndFlags & PROTECT) != 0) {
1279: // this node is protected => cannot gain or lose children
1280: throw new IllegalArgumentException(
1281: "AST node cannot be modified"); //$NON-NLS-1$
1282: }
1283: // delink old child from parent
1284: ASTNode oldChild = (ASTNode) this .store.get(index);
1285: if ((oldChild.typeAndFlags & PROTECT) != 0) {
1286: // old child is protected => cannot be unparented
1287: throw new IllegalArgumentException(
1288: "AST node cannot be modified"); //$NON-NLS-1$
1289: }
1290:
1291: ASTNode.this .ast.preRemoveChildEvent(ASTNode.this ,
1292: oldChild, this .propertyDescriptor);
1293: // n.b. setParent will call ast.modifying()
1294: oldChild.setParent(null, null);
1295: Object result = this .store.remove(index);
1296: updateCursors(index, -1);
1297: ASTNode.this .ast.postRemoveChildEvent(ASTNode.this ,
1298: oldChild, this .propertyDescriptor);
1299: return result;
1300:
1301: }
1302:
1303: /**
1304: * Allocate a cursor to use for a visit. The client must call
1305: * <code>releaseCursor</code> when done.
1306: * <p>
1307: * This method is internally synchronized on this NodeList.
1308: * It is thread-safe to create a cursor.
1309: * </p>
1310: *
1311: * @return a new cursor positioned before the first element
1312: * of the list
1313: */
1314: Cursor newCursor() {
1315: synchronized (this ) {
1316: // serialize cursor management on this NodeList
1317: if (this .cursors == null) {
1318: // convert null to empty list
1319: this .cursors = new ArrayList(1);
1320: }
1321: Cursor result = new Cursor();
1322: this .cursors.add(result);
1323: return result;
1324: }
1325: }
1326:
1327: /**
1328: * Releases the given cursor at the end of a visit.
1329: * <p>
1330: * This method is internally synchronized on this NodeList.
1331: * It is thread-safe to release a cursor.
1332: * </p>
1333: *
1334: * @param cursor the cursor
1335: */
1336: void releaseCursor(Cursor cursor) {
1337: synchronized (this ) {
1338: // serialize cursor management on this NodeList
1339: this .cursors.remove(cursor);
1340: if (this .cursors.isEmpty()) {
1341: // important: convert empty list back to null
1342: // otherwise the node will hang on to needless junk
1343: this .cursors = null;
1344: }
1345: }
1346: }
1347:
1348: /**
1349: * Adjusts all cursors to accomodate an add/remove at the given
1350: * index.
1351: * <p>
1352: * This method is only used when the list is being modified.
1353: * The AST is not thread-safe if any of the clients are modifying it.
1354: * </p>
1355: *
1356: * @param index the position at which the element was added
1357: * or removed
1358: * @param delta +1 for add, and -1 for remove
1359: */
1360: private void updateCursors(int index, int delta) {
1361: if (this .cursors == null) {
1362: // there are no cursors to worry about
1363: return;
1364: }
1365: for (Iterator it = this .cursors.iterator(); it.hasNext();) {
1366: Cursor c = (Cursor) it.next();
1367: c.update(index, delta);
1368: }
1369: }
1370:
1371: /**
1372: * Returns an estimate of the memory footprint of this node list
1373: * instance in bytes.
1374: * <ul>
1375: * <li>1 object header for the NodeList instance</li>
1376: * <li>5 4-byte fields of the NodeList instance</li>
1377: * <li>0 for cursors since null unless walk in progress</li>
1378: * <li>1 object header for the ArrayList instance</li>
1379: * <li>2 4-byte fields of the ArrayList instance</li>
1380: * <li>1 object header for an Object[] instance</li>
1381: * <li>4 bytes in array for each element</li>
1382: * </ul>
1383: *
1384: * @return the size of this node list in bytes
1385: */
1386: int memSize() {
1387: int result = HEADERS + 5 * 4;
1388: result += HEADERS + 2 * 4;
1389: result += HEADERS + 4 * size();
1390: return result;
1391: }
1392:
1393: /**
1394: * Returns an estimate of the memory footprint in bytes of this node
1395: * list and all its subtrees.
1396: *
1397: * @return the size of this list of subtrees in bytes
1398: */
1399: int listSize() {
1400: int result = memSize();
1401: for (Iterator it = iterator(); it.hasNext();) {
1402: ASTNode child = (ASTNode) it.next();
1403: result += child.treeSize();
1404: }
1405: return result;
1406: }
1407: }
1408:
1409: /**
1410: * Creates a new AST node owned by the given AST. Once established,
1411: * the relationship between an AST node and its owning AST does not change
1412: * over the lifetime of the node. The new node has no parent node,
1413: * and no properties.
1414: * <p>
1415: * N.B. This constructor is package-private; all subclasses my be
1416: * declared in the same package; clients are unable to declare
1417: * additional subclasses.
1418: * </p>
1419: *
1420: * @param ast the AST that is to own this node
1421: */
1422: ASTNode(AST ast) {
1423: if (ast == null) {
1424: throw new IllegalArgumentException();
1425: }
1426:
1427: this .ast = ast;
1428: setNodeType(getNodeType0());
1429: setFlags(ast.getDefaultNodeFlag());
1430: // setFlags calls modifying();
1431: }
1432:
1433: /**
1434: * Returns this node's AST.
1435: * <p>
1436: * Note that the relationship between an AST node and its owing AST does
1437: * not change over the lifetime of a node.
1438: * </p>
1439: *
1440: * @return the AST that owns this node
1441: */
1442: public final AST getAST() {
1443: return this .ast;
1444: }
1445:
1446: /**
1447: * Returns this node's parent node, or <code>null</code> if this is the
1448: * root node.
1449: * <p>
1450: * Note that the relationship between an AST node and its parent node
1451: * may change over the lifetime of a node.
1452: * </p>
1453: *
1454: * @return the parent of this node, or <code>null</code> if none
1455: */
1456: public final ASTNode getParent() {
1457: return this .parent;
1458: }
1459:
1460: /**
1461: * Returns the location of this node within its parent,
1462: * or <code>null</code> if this is a root node.
1463: * <p>
1464: * <pre>
1465: * ASTNode node = ...;
1466: * ASTNode parent = node.getParent();
1467: * StructuralPropertyDescriptor location = node.getLocationInParent();
1468: * assert (parent != null) == (location != null);
1469: * if ((location != null) && location.isChildProperty())
1470: * assert parent.getStructuralProperty(location) == node;
1471: * if ((location != null) && location.isChildListProperty())
1472: * assert ((List) parent.getStructuralProperty(location)).contains(node);
1473: * </pre>
1474: * </p>
1475: * <p>
1476: * Note that the relationship between an AST node and its parent node
1477: * may change over the lifetime of a node.
1478: * </p>
1479: *
1480: * @return the location of this node in its parent,
1481: * or <code>null</code> if this node has no parent
1482: * @since 3.0
1483: */
1484: public final StructuralPropertyDescriptor getLocationInParent() {
1485: return this .location;
1486: }
1487:
1488: /**
1489: * Returns the root node at or above this node; returns this node if
1490: * it is a root.
1491: *
1492: * @return the root node at or above this node
1493: */
1494: public final ASTNode getRoot() {
1495: ASTNode candidate = this ;
1496: while (true) {
1497: ASTNode p = candidate.getParent();
1498: if (p == null) {
1499: // candidate has no parent - that's the guy
1500: return candidate;
1501: }
1502: candidate = p;
1503: }
1504: }
1505:
1506: /**
1507: * Returns the value of the given structural property for this node. The value
1508: * returned depends on the kind of property:
1509: * <ul>
1510: * <li>{@link SimplePropertyDescriptor} - the value of the given simple property,
1511: * or <code>null</code> if none; primitive values are "boxed"</li>
1512: * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>),
1513: * or <code>null</code> if none</li>
1514: * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li>
1515: * </ul>
1516: *
1517: * @param property the property
1518: * @return the value, or <code>null</code> if none
1519: * @exception RuntimeException if this node does not have the given property
1520: * @since 3.0
1521: */
1522: public final Object getStructuralProperty(
1523: StructuralPropertyDescriptor property) {
1524: if (property instanceof SimplePropertyDescriptor) {
1525: SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1526: if (p.getValueType() == int.class) {
1527: int result = internalGetSetIntProperty(p, true, 0);
1528: return new Integer(result);
1529: } else if (p.getValueType() == boolean.class) {
1530: boolean result = internalGetSetBooleanProperty(p, true,
1531: false);
1532: return Boolean.valueOf(result);
1533: } else {
1534: return internalGetSetObjectProperty(p, true, null);
1535: }
1536: }
1537: if (property instanceof ChildPropertyDescriptor) {
1538: return internalGetSetChildProperty(
1539: (ChildPropertyDescriptor) property, true, null);
1540: }
1541: if (property instanceof ChildListPropertyDescriptor) {
1542: return internalGetChildListProperty((ChildListPropertyDescriptor) property);
1543: }
1544: throw new IllegalArgumentException();
1545: }
1546:
1547: /**
1548: * Sets the value of the given structural property for this node. The value
1549: * passed depends on the kind of property:
1550: * <ul>
1551: * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property,
1552: * or <code>null</code> if none; primitive values are "boxed"</li>
1553: * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>),
1554: * or <code>null</code> if none</li>
1555: * <li>{@link ChildListPropertyDescriptor} - not allowed</li>
1556: * </ul>
1557: *
1558: * @param property the property
1559: * @param value the property value
1560: * @exception RuntimeException if this node does not have the
1561: * given property, or if the given property cannot be set
1562: * @since 3.0
1563: */
1564: public final void setStructuralProperty(
1565: StructuralPropertyDescriptor property, Object value) {
1566: if (property instanceof SimplePropertyDescriptor) {
1567: SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1568: if (p.getValueType() == int.class) {
1569: int arg = ((Integer) value).intValue();
1570: internalGetSetIntProperty(p, false, arg);
1571: return;
1572: } else if (p.getValueType() == boolean.class) {
1573: boolean arg = ((Boolean) value).booleanValue();
1574: internalGetSetBooleanProperty(p, false, arg);
1575: return;
1576: } else {
1577: if (value == null && p.isMandatory()) {
1578: throw new IllegalArgumentException();
1579: }
1580: internalGetSetObjectProperty(p, false, value);
1581: return;
1582: }
1583: }
1584: if (property instanceof ChildPropertyDescriptor) {
1585: ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
1586: ASTNode child = (ASTNode) value;
1587: if (child == null && p.isMandatory()) {
1588: throw new IllegalArgumentException();
1589: }
1590: internalGetSetChildProperty(p, false, child);
1591: return;
1592: }
1593: if (property instanceof ChildListPropertyDescriptor) {
1594: throw new IllegalArgumentException(
1595: "Cannot set the list of child list property"); //$NON-NLS-1$
1596: }
1597: }
1598:
1599: /**
1600: * Sets the value of the given int-valued property for this node.
1601: * The default implementation of this method throws an exception explaining
1602: * that this node does not have such a property. This method should be
1603: * extended in subclasses that have at leasy one simple property whose value
1604: * type is int.
1605: *
1606: * @param property the property
1607: * @param get <code>true</code> for a get operation, and
1608: * <code>false</code> for a set operation
1609: * @param value the new property value; ignored for get operations
1610: * @return the value; always returns
1611: * <code>0</code> for set operations
1612: * @exception RuntimeException if this node does not have the
1613: * given property, or if the given value cannot be set as specified
1614: * @since 3.0
1615: */
1616: int internalGetSetIntProperty(SimplePropertyDescriptor property,
1617: boolean get, int value) {
1618: throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1619: }
1620:
1621: /**
1622: * Sets the value of the given boolean-valued property for this node.
1623: * The default implementation of this method throws an exception explaining
1624: * that this node does not have such a property. This method should be
1625: * extended in subclasses that have at leasy one simple property whose value
1626: * type is boolean.
1627: *
1628: * @param property the property
1629: * @param get <code>true</code> for a get operation, and
1630: * <code>false</code> for a set operation
1631: * @param value the new property value; ignored for get operations
1632: * @return the value; always returns
1633: * <code>false</code> for set operations
1634: * @exception RuntimeException if this node does not have the
1635: * given property, or if the given value cannot be set as specified
1636: * @since 3.0
1637: */
1638: boolean internalGetSetBooleanProperty(
1639: SimplePropertyDescriptor property, boolean get,
1640: boolean value) {
1641: throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1642: }
1643:
1644: /**
1645: * Sets the value of the given property for this node.
1646: * The default implementation of this method throws an exception explaining
1647: * that this node does not have such a property. This method should be
1648: * extended in subclasses that have at leasy one simple property whose value
1649: * type is a reference type.
1650: *
1651: * @param property the property
1652: * @param get <code>true</code> for a get operation, and
1653: * <code>false</code> for a set operation
1654: * @param value the new property value, or <code>null</code> if none;
1655: * ignored for get operations
1656: * @return the value, or <code>null</code> if none; always returns
1657: * <code>null</code> for set operations
1658: * @exception RuntimeException if this node does not have the
1659: * given property, or if the given value cannot be set as specified
1660: * @since 3.0
1661: */
1662: Object internalGetSetObjectProperty(
1663: SimplePropertyDescriptor property, boolean get, Object value) {
1664: throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1665: }
1666:
1667: /**
1668: * Sets the child value of the given property for this node.
1669: * The default implementation of this method throws an exception explaining
1670: * that this node does not have such a property. This method should be
1671: * extended in subclasses that have at leasy one child property.
1672: *
1673: * @param property the property
1674: * @param get <code>true</code> for a get operation, and
1675: * <code>false</code> for a set operation
1676: * @param child the new child value, or <code>null</code> if none;
1677: * always <code>null</code> for get operations
1678: * @return the child, or <code>null</code> if none; always returns
1679: * <code>null</code> for set operations
1680: * @exception RuntimeException if this node does not have the
1681: * given property, or if the given child cannot be set as specified
1682: * @since 3.0
1683: */
1684: ASTNode internalGetSetChildProperty(
1685: ChildPropertyDescriptor property, boolean get, ASTNode child) {
1686: throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1687: }
1688:
1689: /**
1690: * Returns the list value of the given property for this node.
1691: * The default implementation of this method throws an exception explaining
1692: * that this noed does not have such a property. This method should be
1693: * extended in subclasses that have at leasy one child list property.
1694: *
1695: * @param property the property
1696: * @return the list (element type: {@link ASTNode})
1697: * @exception RuntimeException if the given node does not have the
1698: * given property
1699: * @since 3.0
1700: */
1701: List internalGetChildListProperty(
1702: ChildListPropertyDescriptor property) {
1703: throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
1704: }
1705:
1706: /**
1707: * Returns a list of structural property descriptors for nodes of the
1708: * same type as this node. Clients must not modify the result.
1709: * <p>
1710: * Note that property descriptors are a meta-level mechanism
1711: * for manipulating ASTNodes in a generic way. They are
1712: * unrelated to <code>get/setProperty</code>.
1713: * </p>
1714: *
1715: * @return a list of property descriptors (element type:
1716: * {@link StructuralPropertyDescriptor})
1717: * @since 3.0
1718: */
1719: public final List structuralPropertiesForType() {
1720: return internalStructuralPropertiesForType(this .ast.apiLevel);
1721: }
1722:
1723: /**
1724: * Returns a list of property descriptors for this node type.
1725: * Clients must not modify the result. This abstract method
1726: * must be implemented in each concrete AST node type.
1727: * <p>
1728: * N.B. This method is package-private, so that the implementations
1729: * of this method in each of the concrete AST node types do not
1730: * clutter up the API doc.
1731: * </p>
1732: *
1733: * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants
1734: * @return a list of property descriptors (element type:
1735: * {@link StructuralPropertyDescriptor})
1736: * @since 3.0
1737: */
1738: abstract List internalStructuralPropertiesForType(int apiLevel);
1739:
1740: /**
1741: * Internal helper method that starts the building a list of
1742: * property descriptors for the given node type.
1743: *
1744: * @param nodeClass the class for a concrete node type
1745: * @param propertyList empty list
1746: */
1747: static void createPropertyList(Class nodeClass, List propertyList) {
1748: // stuff nodeClass at head of list for future ref
1749: propertyList.add(nodeClass);
1750: }
1751:
1752: /**
1753: * Internal helper method that adding a property descriptor.
1754: *
1755: * @param property the structural property descriptor
1756: * @param propertyList list beginning with the AST node class
1757: * followed by accumulated structural property descriptors
1758: */
1759: static void addProperty(StructuralPropertyDescriptor property,
1760: List propertyList) {
1761: Class nodeClass = (Class) propertyList.get(0);
1762: if (property.getNodeClass() != nodeClass) {
1763: // easily made cut-and-paste mistake
1764: throw new RuntimeException(
1765: "Structural property descriptor has wrong node class!"); //$NON-NLS-1$
1766: }
1767: propertyList.add(property);
1768: }
1769:
1770: /**
1771: * Internal helper method that completes the building of
1772: * a node type's structural property descriptor list.
1773: *
1774: * @param propertyList list beginning with the AST node class
1775: * followed by accumulated structural property descriptors
1776: * @return unmodifiable list of structural property descriptors
1777: * (element type: <code>StructuralPropertyDescriptor</code>)
1778: */
1779: static List reapPropertyList(List propertyList) {
1780: propertyList.remove(0); // remove nodeClass
1781: // compact
1782: ArrayList a = new ArrayList(propertyList.size());
1783: a.addAll(propertyList);
1784: return Collections.unmodifiableList(a);
1785: }
1786:
1787: /**
1788: * Checks that this AST operation is not used when
1789: * building JLS2 level ASTs.
1790:
1791: * @exception UnsupportedOperationException
1792: * @since 3.0
1793: */
1794: final void unsupportedIn2() {
1795: if (this .ast.apiLevel == AST.JLS2_INTERNAL) {
1796: throw new UnsupportedOperationException(
1797: "Operation not supported in JLS2 AST"); //$NON-NLS-1$
1798: }
1799: }
1800:
1801: /**
1802: * Checks that this AST operation is only used when
1803: * building JLS2 level ASTs.
1804:
1805: * @exception UnsupportedOperationException
1806: * @since 3.0
1807: */
1808: final void supportedOnlyIn2() {
1809: if (this .ast.apiLevel != AST.JLS2_INTERNAL) {
1810: throw new UnsupportedOperationException(
1811: "Operation only supported in JLS2 AST"); //$NON-NLS-1$
1812: }
1813: }
1814:
1815: /**
1816: * Sets or clears this node's parent node and location.
1817: * <p>
1818: * Note that this method is package-private. The pointer from a node
1819: * to its parent is set implicitly as a side effect of inserting or
1820: * removing the node as a child of another node. This method calls
1821: * <code>ast.modifying()</code>.
1822: * </p>
1823: *
1824: * @param parent the new parent of this node, or <code>null</code> if none
1825: * @param property the location of this node in its parent,
1826: * or <code>null</code> if <code>parent</code> is <code>null</code>
1827: * @see #getLocationInParent
1828: * @see #getParent
1829: * @since 3.0
1830: */
1831: final void setParent(ASTNode parent,
1832: StructuralPropertyDescriptor property) {
1833: this .ast.modifying();
1834: this .parent = parent;
1835: this .location = property;
1836: }
1837:
1838: /**
1839: * Removes this node from its parent. Has no effect if this node
1840: * is unparented. If this node appears as an element of a child list
1841: * property of its parent, then this node is removed from the
1842: * list using <code>List.remove</code>.
1843: * If this node appears as the value of a child property of its
1844: * parent, then this node is detached from its parent
1845: * by passing <code>null</code> to the appropriate setter method;
1846: * this operation fails if this node is in a mandatory property.
1847: *
1848: * @since 3.0
1849: */
1850: public final void delete() {
1851: StructuralPropertyDescriptor p = getLocationInParent();
1852: if (p == null) {
1853: // node is unparented
1854: return;
1855: }
1856: if (p.isChildProperty()) {
1857: getParent().setStructuralProperty(this .location, null);
1858: return;
1859: }
1860: if (p.isChildListProperty()) {
1861: List l = (List) getParent().getStructuralProperty(
1862: this .location);
1863: l.remove(this );
1864: }
1865: }
1866:
1867: /**
1868: * Checks whether the given new child node is a node
1869: * in a different AST from its parent-to-be, whether it is
1870: * already has a parent, whether adding it to its
1871: * parent-to-be would create a cycle, and whether the child is of
1872: * the right type. The parent-to-be is the enclosing instance.
1873: *
1874: * @param node the parent-to-be node
1875: * @param newChild the new child of the parent
1876: * @param cycleCheck <code>true</code> if cycles are possible and need
1877: * to be checked, <code>false</code> if cycles are impossible and do
1878: * not need to be checked
1879: * @param nodeType a type constraint on child nodes, or <code>null</code>
1880: * if no special check is required
1881: * @exception IllegalArgumentException if:
1882: * <ul>
1883: * <li>the child is null</li>
1884: * <li>the node belongs to a different AST</li>
1885: * <li>the child has the incorrect node type</li>
1886: * <li>the node already has a parent</li>
1887: * <li>a cycle in would be created</li>
1888: * </ul>
1889: */
1890: static void checkNewChild(ASTNode node, ASTNode newChild,
1891: boolean cycleCheck, Class nodeType) {
1892: if (newChild.ast != node.ast) {
1893: // new child is from a different AST
1894: throw new IllegalArgumentException();
1895: }
1896: if (newChild.getParent() != null) {
1897: // new child currently has a different parent
1898: throw new IllegalArgumentException();
1899: }
1900: if (cycleCheck && newChild == node.getRoot()) {
1901: // inserting new child would create a cycle
1902: throw new IllegalArgumentException();
1903: }
1904: Class childClass = newChild.getClass();
1905: if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
1906: // new child is not of the right type
1907: throw new ClassCastException();
1908: }
1909: if ((newChild.typeAndFlags & PROTECT) != 0) {
1910: // new child node is protected => cannot be parented
1911: throw new IllegalArgumentException(
1912: "AST node cannot be modified"); //$NON-NLS-1$
1913: }
1914: }
1915:
1916: /**
1917: * Prelude portion of the "3 step program" for replacing the
1918: * old child of this node with another node.
1919: * Here is the code pattern found in all AST node subclasses:
1920: * <pre>
1921: * ASTNode oldChild = this.foo;
1922: * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1923: * this.foo = newFoo;
1924: * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1925: * </pre>
1926: * The first part (preReplaceChild) does all the precondition checks,
1927: * reports pre-delete events, and changes parent links.
1928: * The old child is delinked from its parent (making it a root node),
1929: * and the new child node is linked to its parent. The new child node
1930: * must be a root node in the same AST as its new parent, and must not
1931: * be an ancestor of this node. All three nodes must be
1932: * modifiable (not PROTECTED). The replace operation must fail
1933: * atomically; so it is crucial that all precondition checks
1934: * be done before any linking and delinking happens.
1935: * The final part (postReplaceChild )reports post-add events.
1936: * <p>
1937: * This method calls <code>ast.modifying()</code> for the nodes affected.
1938: * </p>
1939: *
1940: * @param oldChild the old child of this node, or <code>null</code> if
1941: * there was no old child to replace
1942: * @param newChild the new child of this node, or <code>null</code> if
1943: * there is no replacement child
1944: * @param property the property descriptor of this node describing
1945: * the relationship between node and child
1946: * @exception RuntimeException if:
1947: * <ul>
1948: * <li>the node belongs to a different AST</li>
1949: * <li>the node already has a parent</li>
1950: * <li>a cycle in would be created</li>
1951: * <li>any of the nodes involved are unmodifiable</li>
1952: * </ul>
1953: * @since 3.0
1954: */
1955: final void preReplaceChild(ASTNode oldChild, ASTNode newChild,
1956: ChildPropertyDescriptor property) {
1957: if ((this .typeAndFlags & PROTECT) != 0) {
1958: // this node is protected => cannot gain or lose children
1959: throw new IllegalArgumentException(
1960: "AST node cannot be modified"); //$NON-NLS-1$
1961: }
1962: if (newChild != null) {
1963: checkNewChild(this , newChild, property.cycleRisk, null);
1964: }
1965: // delink old child from parent
1966: if (oldChild != null) {
1967: if ((oldChild.typeAndFlags & PROTECT) != 0) {
1968: // old child node is protected => cannot be unparented
1969: throw new IllegalArgumentException(
1970: "AST node cannot be modified"); //$NON-NLS-1$
1971: }
1972: if (newChild != null) {
1973: this .ast.preReplaceChildEvent(this , oldChild, newChild,
1974: property);
1975: } else {
1976: this .ast.preRemoveChildEvent(this , oldChild, property);
1977: }
1978: oldChild.setParent(null, null);
1979: } else {
1980: if (newChild != null) {
1981: this .ast.preAddChildEvent(this , newChild, property);
1982: }
1983: }
1984: // link new child to parent
1985: if (newChild != null) {
1986: newChild.setParent(this , property);
1987: // cannot notify postAddChildEvent until parent is linked to child too
1988: }
1989: }
1990:
1991: /**
1992: * Postlude portion of the "3 step program" for replacing the
1993: * old child of this node with another node.
1994: * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
1995: * for details.
1996: * @since 3.0
1997: */
1998: final void postReplaceChild(ASTNode oldChild, ASTNode newChild,
1999: ChildPropertyDescriptor property) {
2000: // link new child to parent
2001: if (newChild != null) {
2002: if (oldChild != null) {
2003: this .ast.postReplaceChildEvent(this , oldChild,
2004: newChild, property);
2005: } else {
2006: this .ast.postAddChildEvent(this , newChild, property);
2007: }
2008: } else {
2009: this .ast.postRemoveChildEvent(this , oldChild, property);
2010: }
2011: }
2012:
2013: /**
2014: * Prelude portion of the "3 step program" for changing the
2015: * value of a simple property of this node.
2016: * Here is the code pattern found in all AST node subclasses:
2017: * <pre>
2018: * preValueChange(FOO_PROPERTY);
2019: * this.foo = newFoo;
2020: * postValueChange(FOO_PROPERTY);
2021: * </pre>
2022: * The first part (preValueChange) does the precondition check
2023: * to make sure the node is modifiable (not PROTECTED).
2024: * The change operation must fail atomically; so it is crucial
2025: * that the precondition checks are done before the field is
2026: * hammered. The final part (postValueChange)reports post-change
2027: * events.
2028: * <p>
2029: * This method calls <code>ast.modifying()</code> for the node affected.
2030: * </p>
2031: *
2032: * @param property the property descriptor of this node
2033: * @exception RuntimeException if:
2034: * <ul>
2035: * <li>this node is unmodifiable</li>
2036: * </ul>
2037: * @since 3.0
2038: */
2039: final void preValueChange(SimplePropertyDescriptor property) {
2040: if ((this .typeAndFlags & PROTECT) != 0) {
2041: // this node is protected => cannot change valure of properties
2042: throw new IllegalArgumentException(
2043: "AST node cannot be modified"); //$NON-NLS-1$
2044: }
2045: this .ast.preValueChangeEvent(this , property);
2046: this .ast.modifying();
2047: }
2048:
2049: /**
2050: * Postlude portion of the "3 step program" for replacing the
2051: * old child of this node with another node.
2052: * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
2053: * @since 3.0
2054: */
2055: final void postValueChange(SimplePropertyDescriptor property) {
2056: this .ast.postValueChangeEvent(this , property);
2057: }
2058:
2059: /**
2060: * Ensures that this node is modifiable (that is, not marked PROTECTED).
2061: * If successful, calls ast.modifying().
2062: * @exception RuntimeException is not modifiable
2063: */
2064: final void checkModifiable() {
2065: if ((this .typeAndFlags & PROTECT) != 0) {
2066: throw new IllegalArgumentException(
2067: "AST node cannot be modified"); //$NON-NLS-1$
2068: }
2069: this .ast.modifying();
2070: }
2071:
2072: /**
2073: * Begin lazy initialization of this node.
2074: * Here is the code pattern found in all AST
2075: * node subclasses:
2076: * <pre>
2077: * if (this.foo == null) {
2078: * // lazy init must be thread-safe for readers
2079: * synchronized (this) {
2080: * if (this.foo == null) {
2081: * preLazyInit();
2082: * this.foo = ...; // code to create new node
2083: * postLazyInit(this.foo, FOO_PROPERTY);
2084: * }
2085: * }
2086: * }
2087: * </pre>
2088: * @since 3.0
2089: */
2090: final void preLazyInit() {
2091: // IMPORTANT: this method is called by readers
2092: // ASTNode.this is locked at this point
2093: this .ast.disableEvents();
2094: // will turn events back on in postLasyInit
2095: }
2096:
2097: /**
2098: * End lazy initialization of this node.
2099: *
2100: * @param newChild the new child of this node, or <code>null</code> if
2101: * there is no replacement child
2102: * @param property the property descriptor of this node describing
2103: * the relationship between node and child
2104: * @since 3.0
2105: */
2106: final void postLazyInit(ASTNode newChild,
2107: ChildPropertyDescriptor property) {
2108: // IMPORTANT: this method is called by readers
2109: // ASTNode.this is locked at this point
2110: // newChild is brand new (so no chance of concurrent access)
2111: newChild.setParent(this , property);
2112: // turn events back on (they were turned off in corresponding preLazyInit)
2113: this .ast.reenableEvents();
2114: }
2115:
2116: /**
2117: * Returns the named property of this node, or <code>null</code> if none.
2118: *
2119: * @param propertyName the property name
2120: * @return the property value, or <code>null</code> if none
2121: * @see #setProperty(String,Object)
2122: */
2123: public final Object getProperty(String propertyName) {
2124: if (propertyName == null) {
2125: throw new IllegalArgumentException();
2126: }
2127: if (this .property1 == null) {
2128: // node has no properties at all
2129: return null;
2130: }
2131: if (this .property1 instanceof String) {
2132: // node has only a single property
2133: if (propertyName.equals(this .property1)) {
2134: return this .property2;
2135: } else {
2136: return null;
2137: }
2138: }
2139: // otherwise node has table of properties
2140: Map m = (Map) this .property1;
2141: return m.get(propertyName);
2142: }
2143:
2144: /**
2145: * Sets the named property of this node to the given value,
2146: * or to <code>null</code> to clear it.
2147: * <p>
2148: * Clients should employ property names that are sufficiently unique
2149: * to avoid inadvertent conflicts with other clients that might also be
2150: * setting properties on the same node.
2151: * </p>
2152: * <p>
2153: * Note that modifying a property is not considered a modification to the
2154: * AST itself. This is to allow clients to decorate existing nodes with
2155: * their own properties without jeopardizing certain things (like the
2156: * validity of bindings), which rely on the underlying tree remaining static.
2157: * </p>
2158: *
2159: * @param propertyName the property name
2160: * @param data the new property value, or <code>null</code> if none
2161: * @see #getProperty(String)
2162: */
2163: public final void setProperty(String propertyName, Object data) {
2164: if (propertyName == null) {
2165: throw new IllegalArgumentException();
2166: }
2167: // N.B. DO NOT CALL ast.modifying();
2168:
2169: if (this .property1 == null) {
2170: // node has no properties at all
2171: if (data == null) {
2172: // we already know this
2173: return;
2174: }
2175: // node gets its fist property
2176: this .property1 = propertyName;
2177: this .property2 = data;
2178: return;
2179: }
2180:
2181: if (this .property1 instanceof String) {
2182: // node has only a single property
2183: if (propertyName.equals(this .property1)) {
2184: // we're in luck
2185: this .property2 = data;
2186: if (data == null) {
2187: // just deleted last property
2188: this .property1 = null;
2189: this .property2 = null;
2190: }
2191: return;
2192: }
2193: if (data == null) {
2194: // we already know this
2195: return;
2196: }
2197: // node already has one property - getting its second
2198: // convert to more flexible representation
2199: HashMap m = new HashMap(2);
2200: m.put(this .property1, this .property2);
2201: m.put(propertyName, data);
2202: this .property1 = m;
2203: this .property2 = null;
2204: return;
2205: }
2206:
2207: // node has two or more properties
2208: HashMap m = (HashMap) this .property1;
2209: if (data == null) {
2210: m.remove(propertyName);
2211: // check for just one property left
2212: if (m.size() == 1) {
2213: // convert to more efficient representation
2214: Map.Entry[] entries = (Map.Entry[]) m.entrySet()
2215: .toArray(new Map.Entry[1]);
2216: this .property1 = entries[0].getKey();
2217: this .property2 = entries[0].getValue();
2218: }
2219: return;
2220: } else {
2221: m.put(propertyName, data);
2222: // still has two or more properties
2223: return;
2224: }
2225: }
2226:
2227: /**
2228: * Returns an unmodifiable table of the properties of this node with
2229: * non-<code>null</code> values.
2230: *
2231: * @return the table of property values keyed by property name
2232: * (key type: <code>String</code>; value type: <code>Object</code>)
2233: */
2234: public final Map properties() {
2235: if (this .property1 == null) {
2236: // node has no properties at all
2237: return UNMODIFIABLE_EMPTY_MAP;
2238: }
2239: if (this .property1 instanceof String) {
2240: // node has a single property
2241: return Collections.singletonMap(this .property1,
2242: this .property2);
2243: }
2244:
2245: // node has two or more properties
2246: if (this .property2 == null) {
2247: this .property2 = Collections
2248: .unmodifiableMap((Map) this .property1);
2249: }
2250: // property2 is unmodifiable wrapper for map in property1
2251: return (Map) this .property2;
2252: }
2253:
2254: /**
2255: * Returns the flags associated with this node.
2256: * <p>
2257: * No flags are associated with newly created nodes.
2258: * </p>
2259: * <p>
2260: * The flags are the bitwise-or of individual flags.
2261: * The following flags are currently defined:
2262: * <ul>
2263: * <li>{@link #MALFORMED} - indicates node is syntactically
2264: * malformed</li>
2265: * <li>{@link #ORIGINAL} - indicates original node
2266: * created by ASTParser</li>
2267: * <li>{@link #PROTECT} - indicates node is protected
2268: * from further modification</li>
2269: * <li>{@link #RECOVERED} - indicates node or a part of this node
2270: * is recovered from source that contains a syntax error</li>
2271: * </ul>
2272: * Other bit positions are reserved for future use.
2273: * </p>
2274: *
2275: * @return the bitwise-or of individual flags
2276: * @see #setFlags(int)
2277: */
2278: public final int getFlags() {
2279: return this .typeAndFlags & 0xFFFF;
2280: }
2281:
2282: /**
2283: * Sets the flags associated with this node to the given value.
2284: * <p>
2285: * The flags are the bitwise-or of individual flags.
2286: * The following flags are currently defined:
2287: * <ul>
2288: * <li>{@link #MALFORMED} - indicates node is syntactically
2289: * malformed</li>
2290: * <li>{@link #ORIGINAL} - indicates original node
2291: * created by ASTParser</li>
2292: * <li>{@link #PROTECT} - indicates node is protected
2293: * from further modification</li>
2294: * <li>{@link #RECOVERED} - indicates node or a part of this node
2295: * is recovered from source that contains a syntax error</li>
2296: * </ul>
2297: * Other bit positions are reserved for future use.
2298: * </p>
2299: * <p>
2300: * Note that the flags are <em>not</em> considered a structural
2301: * property of the node, and can be changed even if the
2302: * node is marked as protected.
2303: * </p>
2304: *
2305: * @param flags the bitwise-or of individual flags
2306: * @see #getFlags()
2307: */
2308: public final void setFlags(int flags) {
2309: this .ast.modifying();
2310: int old = this .typeAndFlags & 0xFFFF0000;
2311: this .typeAndFlags = old | (flags & 0xFFFF);
2312: }
2313:
2314: /**
2315: * Returns an integer value identifying the type of this concrete AST node.
2316: * The values are small positive integers, suitable for use in switch statements.
2317: * <p>
2318: * For each concrete node type there is a unique node type constant (name
2319: * and value). The unique node type constant for a concrete node type such as
2320: * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>.
2321: * </p>
2322: *
2323: * @return one of the node type constants
2324: */
2325: public final int getNodeType() {
2326: return this .typeAndFlags >>> 16;
2327: }
2328:
2329: /**
2330: * Sets the integer value identifying the type of this concrete AST node.
2331: * The values are small positive integers, suitable for use in switch statements.
2332: *
2333: * @param nodeType one of the node type constants
2334: */
2335: private void setNodeType(int nodeType) {
2336: int old = this .typeAndFlags & 0xFFFF0000;
2337: this .typeAndFlags = old | (nodeType << 16);
2338: }
2339:
2340: /**
2341: * Returns an integer value identifying the type of this concrete AST node.
2342: * <p>
2343: * This internal method is implemented in each of the
2344: * concrete node subclasses.
2345: * </p>
2346: *
2347: * @return one of the node type constants
2348: */
2349: abstract int getNodeType0();
2350:
2351: /**
2352: * The <code>ASTNode</code> implementation of this <code>Object</code>
2353: * method uses object identity (==). Use <code>subtreeMatch</code> to
2354: * compare two subtrees for equality.
2355: *
2356: * @param obj {@inheritDoc}
2357: * @return {@inheritDoc}
2358: * @see #subtreeMatch(ASTMatcher matcher, Object other)
2359: */
2360: public final boolean equals(Object obj) {
2361: return this == obj; // equivalent to Object.equals
2362: }
2363:
2364: /*
2365: * (non-Javadoc)
2366: * This makes it consistent with the fact that a equals methods has been provided.
2367: * @see java.lang.Object#hashCode()
2368: */
2369: public final int hashCode() {
2370: return super .hashCode();
2371: }
2372:
2373: /**
2374: * Returns whether the subtree rooted at the given node matches the
2375: * given other object as decided by the given matcher.
2376: *
2377: * @param matcher the matcher
2378: * @param other the other object, or <code>null</code>
2379: * @return <code>true</code> if the subtree matches, or
2380: * <code>false</code> if they do not match
2381: */
2382: public final boolean subtreeMatch(ASTMatcher matcher, Object other) {
2383: return subtreeMatch0(matcher, other);
2384: }
2385:
2386: /**
2387: * Returns whether the subtree rooted at the given node matches the
2388: * given other object as decided by the given matcher.
2389: * <p>
2390: * This internal method is implemented in each of the
2391: * concrete node subclasses.
2392: * </p>
2393: *
2394: * @param matcher the matcher
2395: * @param other the other object, or <code>null</code>
2396: * @return <code>true</code> if the subtree matches, or
2397: * <code>false</code> if they do not match
2398: */
2399: abstract boolean subtreeMatch0(ASTMatcher matcher, Object other);
2400:
2401: /**
2402: * Returns a deep copy of the subtree of AST nodes rooted at the
2403: * given node. The resulting nodes are owned by the given AST,
2404: * which may be different from the ASTs of the given node.
2405: * Even if the given node has a parent, the result node will be unparented.
2406: * <p>
2407: * Source range information on the original nodes is automatically copied to the new
2408: * nodes. Client properties (<code>properties</code>) are not carried over.
2409: * </p>
2410: * <p>
2411: * The node's <code>AST</code> and the target <code>AST</code> must support
2412: * the same API level.
2413: * </p>
2414: *
2415: * @param target the AST that is to own the nodes in the result
2416: * @param node the node to copy, or <code>null</code> if none
2417: * @return the copied node, or <code>null</code> if <code>node</code>
2418: * is <code>null</code>
2419: */
2420: public static ASTNode copySubtree(AST target, ASTNode node) {
2421: if (node == null) {
2422: return null;
2423: }
2424: if (target == null) {
2425: throw new IllegalArgumentException();
2426: }
2427: if (target.apiLevel() != node.getAST().apiLevel()) {
2428: throw new UnsupportedOperationException();
2429: }
2430: ASTNode newNode = node.clone(target);
2431: return newNode;
2432: }
2433:
2434: /**
2435: * Returns a deep copy of the subtrees of AST nodes rooted at the
2436: * given list of nodes. The resulting nodes are owned by the given AST,
2437: * which may be different from the ASTs of the nodes in the list.
2438: * Even if the nodes in the list have parents, the nodes in the result
2439: * will be unparented.
2440: * <p>
2441: * Source range information on the original nodes is automatically copied to the new
2442: * nodes. Client properties (<code>properties</code>) are not carried over.
2443: * </p>
2444: *
2445: * @param target the AST that is to own the nodes in the result
2446: * @param nodes the list of nodes to copy
2447: * (element type: <code>ASTNode</code>)
2448: * @return the list of copied subtrees
2449: * (element type: <code>ASTNode</code>)
2450: */
2451: public static List copySubtrees(AST target, List nodes) {
2452: List result = new ArrayList(nodes.size());
2453: for (Iterator it = nodes.iterator(); it.hasNext();) {
2454: ASTNode oldNode = (ASTNode) it.next();
2455: ASTNode newNode = oldNode.clone(target);
2456: result.add(newNode);
2457: }
2458: return result;
2459: }
2460:
2461: /**
2462: * Returns a deep copy of the subtree of AST nodes rooted at this node.
2463: * The resulting nodes are owned by the given AST, which may be different
2464: * from the AST of this node. Even if this node has a parent, the
2465: * result node will be unparented.
2466: * <p>
2467: * This method reports pre- and post-clone events, and dispatches
2468: * to <code>clone0(AST)</code> which is reimplemented in node subclasses.
2469: * </p>
2470: *
2471: * @param target the AST that is to own the nodes in the result
2472: * @return the root node of the copies subtree
2473: */
2474: final ASTNode clone(AST target) {
2475: this .ast.preCloneNodeEvent(this );
2476: ASTNode c = this .clone0(target);
2477: this .ast.postCloneNodeEvent(this , c);
2478: return c;
2479: }
2480:
2481: /**
2482: * Returns a deep copy of the subtree of AST nodes rooted at this node.
2483: * The resulting nodes are owned by the given AST, which may be different
2484: * from the AST of this node. Even if this node has a parent, the
2485: * result node will be unparented.
2486: * <p>
2487: * This method must be implemented in subclasses.
2488: * </p>
2489: * <p>
2490: * This method does not report pre- and post-clone events.
2491: * All callers should instead call <code>clone(AST)</code>
2492: * to ensure that pre- and post-clone events are reported.
2493: * </p>
2494: * <p>
2495: * N.B. This method is package-private, so that the implementations
2496: * of this method in each of the concrete AST node types do not
2497: * clutter up the API doc.
2498: * </p>
2499: *
2500: * @param target the AST that is to own the nodes in the result
2501: * @return the root node of the copies subtree
2502: */
2503: abstract ASTNode clone0(AST target);
2504:
2505: /**
2506: * Accepts the given visitor on a visit of the current node.
2507: *
2508: * @param visitor the visitor object
2509: * @exception IllegalArgumentException if the visitor is null
2510: */
2511: public final void accept(ASTVisitor visitor) {
2512: if (visitor == null) {
2513: throw new IllegalArgumentException();
2514: }
2515: // begin with the generic pre-visit
2516: visitor.preVisit(this );
2517: // dynamic dispatch to internal method for type-specific visit/endVisit
2518: accept0(visitor);
2519: // end with the generic post-visit
2520: visitor.postVisit(this );
2521: }
2522:
2523: /**
2524: * Accepts the given visitor on a type-specific visit of the current node.
2525: * This method must be implemented in all concrete AST node types.
2526: * <p>
2527: * General template for implementation on each concrete ASTNode class:
2528: * <pre>
2529: * <code>
2530: * boolean visitChildren = visitor.visit(this);
2531: * if (visitChildren) {
2532: * // visit children in normal left to right reading order
2533: * acceptChild(visitor, getProperty1());
2534: * acceptChildren(visitor, rawListProperty);
2535: * acceptChild(visitor, getProperty2());
2536: * }
2537: * visitor.endVisit(this);
2538: * </code>
2539: * </pre>
2540: * Note that the caller (<code>accept</code>) take cares of invoking
2541: * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>.
2542: * </p>
2543: *
2544: * @param visitor the visitor object
2545: */
2546: abstract void accept0(ASTVisitor visitor);
2547:
2548: /**
2549: * Accepts the given visitor on a visit of the current node.
2550: * <p>
2551: * This method should be used by the concrete implementations of
2552: * <code>accept0</code> to traverse optional properties. Equivalent
2553: * to <code>child.accept(visitor)</code> if <code>child</code>
2554: * is not <code>null</code>.
2555: * </p>
2556: *
2557: * @param visitor the visitor object
2558: * @param child the child AST node to dispatch too, or <code>null</code>
2559: * if none
2560: */
2561: final void acceptChild(ASTVisitor visitor, ASTNode child) {
2562: if (child == null) {
2563: return;
2564: }
2565: child.accept(visitor);
2566: }
2567:
2568: /**
2569: * Accepts the given visitor on a visit of the given live list of
2570: * child nodes.
2571: * <p>
2572: * This method must be used by the concrete implementations of
2573: * <code>accept</code> to traverse list-values properties; it
2574: * encapsulates the proper handling of on-the-fly changes to the list.
2575: * </p>
2576: *
2577: * @param visitor the visitor object
2578: * @param children the child AST node to dispatch too, or <code>null</code>
2579: * if none
2580: */
2581: final void acceptChildren(ASTVisitor visitor,
2582: ASTNode.NodeList children) {
2583: // use a cursor to keep track of where we are up to
2584: // (the list may be changing under foot)
2585: NodeList.Cursor cursor = children.newCursor();
2586: try {
2587: while (cursor.hasNext()) {
2588: ASTNode child = (ASTNode) cursor.next();
2589: child.accept(visitor);
2590: }
2591: } finally {
2592: children.releaseCursor(cursor);
2593: }
2594: }
2595:
2596: /**
2597: * Returns the character index into the original source file indicating
2598: * where the source fragment corresponding to this node begins.
2599: * <p>
2600: * The parser supplies useful well-defined source ranges to the nodes it creates.
2601: * See {@link ASTParser#setKind(int)} for details
2602: * on precisely where source ranges begin and end.
2603: * </p>
2604: *
2605: * @return the 0-based character index, or <code>-1</code>
2606: * if no source position information is recorded for this node
2607: * @see #getLength()
2608: * @see ASTParser
2609: */
2610: public final int getStartPosition() {
2611: return this .startPosition;
2612: }
2613:
2614: /**
2615: * Returns the length in characters of the original source file indicating
2616: * where the source fragment corresponding to this node ends.
2617: * <p>
2618: * The parser supplies useful well-defined source ranges to the nodes it creates.
2619: * See {@link ASTParser#setKind(int)} methods for details
2620: * on precisely where source ranges begin and end.
2621: * </p>
2622: *
2623: * @return a (possibly 0) length, or <code>0</code>
2624: * if no source position information is recorded for this node
2625: * @see #getStartPosition()
2626: * @see ASTParser
2627: */
2628: public final int getLength() {
2629: return this .length;
2630: }
2631:
2632: /**
2633: * Sets the source range of the original source file where the source
2634: * fragment corresponding to this node was found.
2635: * <p>
2636: * See {@link ASTParser#setKind(int)} for details
2637: * on precisely where source ranges are supposed to begin and end.
2638: * </p>
2639: *
2640: * @param startPosition a 0-based character index,
2641: * or <code>-1</code> if no source position information is
2642: * available for this node
2643: * @param length a (possibly 0) length,
2644: * or <code>0</code> if no source position information is recorded
2645: * for this node
2646: * @see #getStartPosition()
2647: * @see #getLength()
2648: * @see ASTParser
2649: */
2650: public final void setSourceRange(int startPosition, int length) {
2651: if (startPosition >= 0 && length < 0) {
2652: throw new IllegalArgumentException();
2653: }
2654: if (startPosition < 0 && length != 0) {
2655: throw new IllegalArgumentException();
2656: }
2657: // source positions are not considered a structural property
2658: // but we protect them nevertheless
2659: checkModifiable();
2660: this .startPosition = startPosition;
2661: this .length = length;
2662: }
2663:
2664: /**
2665: * Returns a string representation of this node suitable for debugging
2666: * purposes only.
2667: *
2668: * @return a debug string
2669: */
2670: public final String toString() {
2671: StringBuffer buffer = new StringBuffer();
2672: int p = buffer.length();
2673: try {
2674: appendDebugString(buffer);
2675: } catch (RuntimeException e) {
2676: // since debugger sometimes call toString methods, problems can easily happen when
2677: // toString is called on an instance that is being initialized
2678: buffer.setLength(p);
2679: buffer.append("!"); //$NON-NLS-1$
2680: buffer.append(standardToString());
2681: }
2682: return buffer.toString();
2683: }
2684:
2685: /**
2686: * Returns the string representation of this node produced by the standard
2687: * <code>Object.toString</code> method.
2688: *
2689: * @return a debug string
2690: */
2691: final String standardToString() {
2692: return super .toString();
2693: }
2694:
2695: /**
2696: * Appends a debug representation of this node to the given string buffer.
2697: * <p>
2698: * The <code>ASTNode</code> implementation of this method prints out the entire
2699: * subtree. Subclasses may override to provide a more succinct representation.
2700: * </p>
2701: *
2702: * @param buffer the string buffer to append to
2703: */
2704: void appendDebugString(StringBuffer buffer) {
2705: // print the subtree by default
2706: appendPrintString(buffer);
2707: }
2708:
2709: /**
2710: * Appends a standard Java source code representation of this subtree to the given
2711: * string buffer.
2712: *
2713: * @param buffer the string buffer to append to
2714: */
2715: final void appendPrintString(StringBuffer buffer) {
2716: NaiveASTFlattener printer = new NaiveASTFlattener();
2717: this .accept(printer);
2718: buffer.append(printer.getResult());
2719: }
2720:
2721: /**
2722: * Estimate of size of an object header in bytes.
2723: */
2724: static final int HEADERS = 12;
2725:
2726: /**
2727: * Approximate base size of an AST node instance in bytes,
2728: * including object header and instance fields.
2729: * That is, HEADERS + (# instance vars in ASTNode)*4.
2730: */
2731: static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
2732:
2733: /**
2734: * Returns an estimate of the memory footprint, in bytes,
2735: * of the given string.
2736: *
2737: * @param string the string to measure, or <code>null</code>
2738: * @return the size of this string object in bytes, or
2739: * 0 if the string is <code>null</code>
2740: * @since 3.0
2741: */
2742: static int stringSize(String string) {
2743: int size = 0;
2744: if (string != null) {
2745: // Strings usually have 4 instance fields, one of which is a char[]
2746: size += HEADERS + 4 * 4;
2747: // char[] has 2 bytes per character
2748: size += HEADERS + 2 * string.length();
2749: }
2750: return size;
2751: }
2752:
2753: /**
2754: * Returns an estimate of the memory footprint in bytes of the entire
2755: * subtree rooted at this node.
2756: *
2757: * @return the size of this subtree in bytes
2758: */
2759: public final int subtreeBytes() {
2760: return treeSize();
2761: }
2762:
2763: /**
2764: * Returns an estimate of the memory footprint in bytes of the entire
2765: * subtree rooted at this node.
2766: * <p>
2767: * N.B. This method is package-private, so that the implementations
2768: * of this method in each of the concrete AST node types do not
2769: * clutter up the API doc.
2770: * </p>
2771: *
2772: * @return the size of this subtree in bytes
2773: */
2774: abstract int treeSize();
2775:
2776: /**
2777: * Returns an estimate of the memory footprint of this node in bytes.
2778: * The estimate does not include the space occupied by child nodes.
2779: *
2780: * @return the size of this node in bytes
2781: */
2782: abstract int memSize();
2783: }
|