001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: /**
016: * Labeled statement AST node type.
017: *
018: * <pre>
019: * LabeledStatement:
020: * Identifier <b>:</b> Statement
021: * </pre>
022: *
023: * @since 2.0
024: */
025: public class LabeledStatement extends Statement {
026:
027: /**
028: * The "label" structural property of this node type.
029: * @since 3.0
030: */
031: public static final ChildPropertyDescriptor LABEL_PROPERTY = new ChildPropertyDescriptor(
032: LabeledStatement.class,
033: "label", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
034:
035: /**
036: * The "body" structural property of this node type.
037: * @since 3.0
038: */
039: public static final ChildPropertyDescriptor BODY_PROPERTY = new ChildPropertyDescriptor(
040: LabeledStatement.class,
041: "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
042:
043: /**
044: * A list of property descriptors (element type:
045: * {@link StructuralPropertyDescriptor}),
046: * or null if uninitialized.
047: */
048: private static final List PROPERTY_DESCRIPTORS;
049:
050: static {
051: List propertyList = new ArrayList(3);
052: createPropertyList(LabeledStatement.class, propertyList);
053: addProperty(LABEL_PROPERTY, propertyList);
054: addProperty(BODY_PROPERTY, propertyList);
055: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
056: }
057:
058: /**
059: * Returns a list of structural property descriptors for this node type.
060: * Clients must not modify the result.
061: *
062: * @param apiLevel the API level; one of the
063: * <code>AST.JLS*</code> constants
064:
065: * @return a list of property descriptors (element type:
066: * {@link StructuralPropertyDescriptor})
067: * @since 3.0
068: */
069: public static List propertyDescriptors(int apiLevel) {
070: return PROPERTY_DESCRIPTORS;
071: }
072:
073: /**
074: * The label; lazily initialized; defaults to a unspecified,
075: * legal Java identifier.
076: */
077: private SimpleName labelName = null;
078:
079: /**
080: * The body statement; lazily initialized; defaults to an unspecified, but
081: * legal, statement.
082: */
083: private Statement body = null;
084:
085: /**
086: * Creates a new AST node for a labeled statement owned by the given
087: * AST. By default, the statement has an unspecified (but legal) label
088: * and an unspecified (but legal) statement.
089: * <p>
090: * N.B. This constructor is package-private.
091: * </p>
092: *
093: * @param ast the AST that is to own this node
094: */
095: LabeledStatement(AST ast) {
096: super (ast);
097: }
098:
099: /* (omit javadoc for this method)
100: * Method declared on ASTNode.
101: */
102: final List internalStructuralPropertiesForType(int apiLevel) {
103: return propertyDescriptors(apiLevel);
104: }
105:
106: /* (omit javadoc for this method)
107: * Method declared on ASTNode.
108: */
109: final ASTNode internalGetSetChildProperty(
110: ChildPropertyDescriptor property, boolean get, ASTNode child) {
111: if (property == LABEL_PROPERTY) {
112: if (get) {
113: return getLabel();
114: } else {
115: setLabel((SimpleName) child);
116: return null;
117: }
118: }
119: if (property == BODY_PROPERTY) {
120: if (get) {
121: return getBody();
122: } else {
123: setBody((Statement) child);
124: return null;
125: }
126: }
127: // allow default implementation to flag the error
128: return super .internalGetSetChildProperty(property, get, child);
129: }
130:
131: /* (omit javadoc for this method)
132: * Method declared on ASTNode.
133: */
134: final int getNodeType0() {
135: return LABELED_STATEMENT;
136: }
137:
138: /* (omit javadoc for this method)
139: * Method declared on ASTNode.
140: */
141: ASTNode clone0(AST target) {
142: LabeledStatement result = new LabeledStatement(target);
143: result
144: .setSourceRange(this .getStartPosition(), this
145: .getLength());
146: result.setLabel((SimpleName) ASTNode.copySubtree(target,
147: getLabel()));
148: result.setBody((Statement) ASTNode.copySubtree(target,
149: getBody()));
150: return result;
151: }
152:
153: /* (omit javadoc for this method)
154: * Method declared on ASTNode.
155: */
156: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
157: // dispatch to correct overloaded match method
158: return matcher.match(this , other);
159: }
160:
161: /* (omit javadoc for this method)
162: * Method declared on ASTNode.
163: */
164: void accept0(ASTVisitor visitor) {
165: boolean visitChildren = visitor.visit(this );
166: if (visitChildren) {
167: // visit children in normal left to right reading order
168: acceptChild(visitor, getLabel());
169: acceptChild(visitor, getBody());
170: }
171: visitor.endVisit(this );
172: }
173:
174: /**
175: * Returns the label of this labeled statement.
176: *
177: * @return the variable name node
178: */
179: public SimpleName getLabel() {
180: if (this .labelName == null) {
181: // lazy init must be thread-safe for readers
182: synchronized (this ) {
183: if (this .labelName == null) {
184: preLazyInit();
185: this .labelName = new SimpleName(this .ast);
186: postLazyInit(this .labelName, LABEL_PROPERTY);
187: }
188: }
189: }
190: return this .labelName;
191: }
192:
193: /**
194: * Sets the label of this labeled statement.
195: *
196: * @param label the new label
197: * @exception IllegalArgumentException if:
198: * <ul>
199: * <li>the node belongs to a different AST</li>
200: * <li>the node already has a parent</li>
201: * </ul>
202: */
203: public void setLabel(SimpleName label) {
204: if (label == null) {
205: throw new IllegalArgumentException();
206: }
207: ASTNode oldChild = this .labelName;
208: preReplaceChild(oldChild, label, LABEL_PROPERTY);
209: this .labelName = label;
210: postReplaceChild(oldChild, label, LABEL_PROPERTY);
211: }
212:
213: /**
214: * Returns the body of this labeled statement.
215: *
216: * @return the body statement node
217: */
218: public Statement getBody() {
219: if (this .body == null) {
220: // lazy init must be thread-safe for readers
221: synchronized (this ) {
222: if (this .body == null) {
223: preLazyInit();
224: this .body = new EmptyStatement(this .ast);
225: postLazyInit(this .body, BODY_PROPERTY);
226: }
227: }
228: }
229: return this .body;
230: }
231:
232: /**
233: * Sets the body of this labeled statement.
234: * <p>
235: * Special note: The Java language does not allow a local variable declaration
236: * to appear as the body of a labeled statement (they may only appear within a
237: * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
238: * as the body of a <code>LabeledStatement</code>. To get something that will
239: * compile, be sure to embed the <code>VariableDeclarationStatement</code>
240: * inside a <code>Block</code>.
241: * </p>
242: *
243: * @param statement the body statement node
244: * @exception IllegalArgumentException if:
245: * <ul>
246: * <li>the node belongs to a different AST</li>
247: * <li>the node already has a parent</li>
248: * <li>a cycle in would be created</li>
249: * </ul>
250: */
251: public void setBody(Statement statement) {
252: if (statement == null) {
253: throw new IllegalArgumentException();
254: }
255: ASTNode oldChild = this .body;
256: preReplaceChild(oldChild, statement, BODY_PROPERTY);
257: this .body = statement;
258: postReplaceChild(oldChild, statement, BODY_PROPERTY);
259: }
260:
261: /* (omit javadoc for this method)
262: * Method declared on ASTNode.
263: */
264: int memSize() {
265: return super .memSize() + 2 * 4;
266: }
267:
268: /* (omit javadoc for this method)
269: * Method declared on ASTNode.
270: */
271: int treeSize() {
272: return memSize()
273: + (this .labelName == null ? 0 : getLabel().treeSize())
274: + (this .body == null ? 0 : getBody().treeSize());
275: }
276: }
|