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: * Try statement AST node type.
017: *
018: * <pre>
019: * TryStatement:
020: * <b>try</b> Block
021: * { CatchClause }
022: * [ <b>finally</b> Block ]
023: * </pre>
024: *
025: * @since 2.0
026: */
027: public class TryStatement extends Statement {
028:
029: /**
030: * The "body" structural property of this node type.
031: * @since 3.0
032: */
033: public static final ChildPropertyDescriptor BODY_PROPERTY = new ChildPropertyDescriptor(
034: TryStatement.class,
035: "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
036:
037: /**
038: * The "catchClauses" structural property of this node type.
039: * @since 3.0
040: */
041: public static final ChildListPropertyDescriptor CATCH_CLAUSES_PROPERTY = new ChildListPropertyDescriptor(
042: TryStatement.class,
043: "catchClauses", CatchClause.class, CYCLE_RISK); //$NON-NLS-1$
044:
045: /**
046: * The "finally" structural property of this node type.
047: * @since 3.0
048: */
049: public static final ChildPropertyDescriptor FINALLY_PROPERTY = new ChildPropertyDescriptor(
050: TryStatement.class,
051: "finally", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
052:
053: /**
054: * A list of property descriptors (element type:
055: * {@link StructuralPropertyDescriptor}),
056: * or null if uninitialized.
057: */
058: private static final List PROPERTY_DESCRIPTORS;
059:
060: static {
061: List propertyList = new ArrayList(4);
062: createPropertyList(TryStatement.class, propertyList);
063: addProperty(BODY_PROPERTY, propertyList);
064: addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
065: addProperty(FINALLY_PROPERTY, propertyList);
066: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
067: }
068:
069: /**
070: * Returns a list of structural property descriptors for this node type.
071: * Clients must not modify the result.
072: *
073: * @param apiLevel the API level; one of the
074: * <code>AST.JLS*</code> constants
075: * @return a list of property descriptors (element type:
076: * {@link StructuralPropertyDescriptor})
077: * @since 3.0
078: */
079: public static List propertyDescriptors(int apiLevel) {
080: return PROPERTY_DESCRIPTORS;
081: }
082:
083: /**
084: * The body; lazily initialized; defaults to an empty block.
085: */
086: private Block body = null;
087:
088: /**
089: * The catch clauses (element type: <code>CatchClause</code>).
090: * Defaults to an empty list.
091: */
092: private ASTNode.NodeList catchClauses = new ASTNode.NodeList(
093: CATCH_CLAUSES_PROPERTY);
094:
095: /**
096: * The finally block, or <code>null</code> if none.
097: * Defaults to none.
098: */
099: private Block optionalFinallyBody = null;
100:
101: /**
102: * Creates a new AST node for a try statement owned by the given
103: * AST. By default, the try statement has an empty block, no catch
104: * clauses, and no finally block.
105: * <p>
106: * N.B. This constructor is package-private.
107: * </p>
108: *
109: * @param ast the AST that is to own this node
110: */
111: TryStatement(AST ast) {
112: super (ast);
113: }
114:
115: /* (omit javadoc for this method)
116: * Method declared on ASTNode.
117: */
118: final List internalStructuralPropertiesForType(int apiLevel) {
119: return propertyDescriptors(apiLevel);
120: }
121:
122: /* (omit javadoc for this method)
123: * Method declared on ASTNode.
124: */
125: final ASTNode internalGetSetChildProperty(
126: ChildPropertyDescriptor property, boolean get, ASTNode child) {
127: if (property == BODY_PROPERTY) {
128: if (get) {
129: return getBody();
130: } else {
131: setBody((Block) child);
132: return null;
133: }
134: }
135: if (property == FINALLY_PROPERTY) {
136: if (get) {
137: return getFinally();
138: } else {
139: setFinally((Block) child);
140: return null;
141: }
142: }
143: // allow default implementation to flag the error
144: return super .internalGetSetChildProperty(property, get, child);
145: }
146:
147: /* (omit javadoc for this method)
148: * Method declared on ASTNode.
149: */
150: final List internalGetChildListProperty(
151: ChildListPropertyDescriptor property) {
152: if (property == CATCH_CLAUSES_PROPERTY) {
153: return catchClauses();
154: }
155: // allow default implementation to flag the error
156: return super .internalGetChildListProperty(property);
157: }
158:
159: /* (omit javadoc for this method)
160: * Method declared on ASTNode.
161: */
162: final int getNodeType0() {
163: return TRY_STATEMENT;
164: }
165:
166: /* (omit javadoc for this method)
167: * Method declared on ASTNode.
168: */
169: ASTNode clone0(AST target) {
170: TryStatement result = new TryStatement(target);
171: result
172: .setSourceRange(this .getStartPosition(), this
173: .getLength());
174: result.copyLeadingComment(this );
175: result.setBody((Block) getBody().clone(target));
176: result.catchClauses().addAll(
177: ASTNode.copySubtrees(target, catchClauses()));
178: result.setFinally((Block) ASTNode.copySubtree(target,
179: getFinally()));
180: return result;
181: }
182:
183: /* (omit javadoc for this method)
184: * Method declared on ASTNode.
185: */
186: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
187: // dispatch to correct overloaded match method
188: return matcher.match(this , other);
189: }
190:
191: /* (omit javadoc for this method)
192: * Method declared on ASTNode.
193: */
194: void accept0(ASTVisitor visitor) {
195: boolean visitChildren = visitor.visit(this );
196: if (visitChildren) {
197: // visit children in normal left to right reading order
198: acceptChild(visitor, getBody());
199: acceptChildren(visitor, this .catchClauses);
200: acceptChild(visitor, getFinally());
201: }
202: visitor.endVisit(this );
203: }
204:
205: /**
206: * Returns the body of this try statement.
207: *
208: * @return the try body
209: */
210: public Block getBody() {
211: if (this .body == null) {
212: // lazy init must be thread-safe for readers
213: synchronized (this ) {
214: if (this .body == null) {
215: preLazyInit();
216: this .body = new Block(this .ast);
217: postLazyInit(this .body, BODY_PROPERTY);
218: }
219: }
220: }
221: return this .body;
222: }
223:
224: /**
225: * Sets the body of this try statement.
226: *
227: * @param body the block node
228: * @exception IllegalArgumentException if:
229: * <ul>
230: * <li>the node belongs to a different AST</li>
231: * <li>the node already has a parent</li>
232: * <li>a cycle in would be created</li>
233: * </ul>
234: */
235: public void setBody(Block body) {
236: if (body == null) {
237: throw new IllegalArgumentException();
238: }
239: ASTNode oldChild = this .body;
240: preReplaceChild(oldChild, body, BODY_PROPERTY);
241: this .body = body;
242: postReplaceChild(oldChild, body, BODY_PROPERTY);
243: }
244:
245: /**
246: * Returns the live ordered list of catch clauses for this try statement.
247: *
248: * @return the live list of catch clauses
249: * (element type: <code>CatchClause</code>)
250: */
251: public List catchClauses() {
252: return this .catchClauses;
253: }
254:
255: /**
256: * Returns the finally block of this try statement, or <code>null</code> if
257: * this try statement has <b>no</b> finally block.
258: *
259: * @return the finally block, or <code>null</code> if this try statement
260: * has none
261: */
262: public Block getFinally() {
263: return this .optionalFinallyBody;
264: }
265:
266: /**
267: * Sets or clears the finally block of this try statement.
268: *
269: * @param block the finally block node, or <code>null</code> if
270: * there is none
271: * @exception IllegalArgumentException if:
272: * <ul>
273: * <li>the node belongs to a different AST</li>
274: * <li>the node already has a parent</li>
275: * <li>a cycle in would be created</li>
276: * </ul>
277: */
278: public void setFinally(Block block) {
279: ASTNode oldChild = this .optionalFinallyBody;
280: preReplaceChild(oldChild, block, FINALLY_PROPERTY);
281: this .optionalFinallyBody = block;
282: postReplaceChild(oldChild, block, FINALLY_PROPERTY);
283: }
284:
285: /* (omit javadoc for this method)
286: * Method declared on ASTNode.
287: */
288: int memSize() {
289: return super .memSize() + 3 * 4;
290: }
291:
292: /* (omit javadoc for this method)
293: * Method declared on ASTNode.
294: */
295: int treeSize() {
296: return memSize()
297: + (this .body == null ? 0 : getBody().treeSize())
298: + this .catchClauses.listSize()
299: + (this .optionalFinallyBody == null ? 0 : getFinally()
300: .treeSize());
301: }
302: }
|