c12a904bcba38be5aa0cb8e8def1083e69ac1898
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / TryStatement.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.core.dom;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 /**
18  * Try statement AST node type.
19  *
20  * <pre>
21  * TryStatement:
22  *     <b>try</b> Block 
23  *         { CatchClause }
24  *         [ <b>finally</b> Block ]
25  * </pre>
26  * 
27  * @since 2.0
28  * @noinstantiate This class is not intended to be instantiated by clients.
29  */
30 public class TryStatement extends Statement {
31         
32         /**
33          * The "body" structural property of this node type.
34          * @since 3.0
35          */
36         public static final ChildPropertyDescriptor BODY_PROPERTY = 
37                 new ChildPropertyDescriptor(TryStatement.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
38
39         /**
40          * The "catchClauses" structural property of this node type.
41          * @since 3.0
42          */
43         public static final ChildListPropertyDescriptor CATCH_CLAUSES_PROPERTY = 
44                 new ChildListPropertyDescriptor(TryStatement.class, "catchClauses", CatchClause.class, CYCLE_RISK); //$NON-NLS-1$
45
46         /**
47          * The "finally" structural property of this node type.
48          * @since 3.0
49          */
50         public static final ChildPropertyDescriptor FINALLY_PROPERTY = 
51                 new ChildPropertyDescriptor(TryStatement.class, "finally", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
52
53         /**
54          * A list of property descriptors (element type: 
55          * {@link StructuralPropertyDescriptor}),
56          * or null if uninitialized.
57          */
58         private static final List PROPERTY_DESCRIPTORS;
59         
60         static {
61                 List propertyList = new ArrayList(4);
62                 createPropertyList(TryStatement.class, propertyList);
63                 addProperty(BODY_PROPERTY, propertyList);
64                 addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
65                 addProperty(FINALLY_PROPERTY, propertyList);
66                 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
67         }
68
69         /**
70          * Returns a list of structural property descriptors for this node type.
71          * Clients must not modify the result.
72          * 
73          * @param apiLevel the API level; one of the
74          * <code>AST.JLS*</code> constants
75          * @return a list of property descriptors (element type: 
76          * {@link StructuralPropertyDescriptor})
77          * @since 3.0
78          */
79         public static List propertyDescriptors(int apiLevel) {
80                 return PROPERTY_DESCRIPTORS;
81         }
82                         
83         /**
84          * The body; lazily initialized; defaults to an empty block.
85          */
86         private Block body = null;
87
88         /**
89          * The catch clauses (element type: <code>CatchClause</code>).
90          * Defaults to an empty list.
91          */
92         private ASTNode.NodeList catchClauses =
93                 new ASTNode.NodeList(CATCH_CLAUSES_PROPERTY);
94         
95         /**
96          * The finally block, or <code>null</code> if none.
97          * Defaults to none.
98          */
99         private Block optionalFinallyBody = null;
100
101                         
102         /**
103          * Creates a new AST node for a try statement owned by the given 
104          * AST. By default, the try statement has an empty block, no catch
105          * clauses, and no finally block.
106          * <p>
107          * N.B. This constructor is package-private.
108          * </p>
109          * 
110          * @param ast the AST that is to own this node
111          */
112         TryStatement(AST ast) {
113                 super(ast);
114         }
115
116         /* (omit javadoc for this method)
117          * Method declared on ASTNode.
118          */
119         final List internalStructuralPropertiesForType(int apiLevel) {
120                 return propertyDescriptors(apiLevel);
121         }
122         
123         /* (omit javadoc for this method)
124          * Method declared on ASTNode.
125          */
126         final ASTNode internalGetSetChildProperty(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(ChildListPropertyDescriptor property) {
151                 if (property == CATCH_CLAUSES_PROPERTY) {
152                         return catchClauses();
153                 }
154                 // allow default implementation to flag the error
155                 return super.internalGetChildListProperty(property);
156         }
157
158         /* (omit javadoc for this method)
159          * Method declared on ASTNode.
160          */
161         final int getNodeType0() {
162                 return TRY_STATEMENT;
163         }
164
165         /* (omit javadoc for this method)
166          * Method declared on ASTNode.
167          */
168         ASTNode clone0(AST target) {
169                 TryStatement result = new TryStatement(target);
170                 result.setSourceRange(this.getStartPosition(), this.getLength());
171                 result.copyLeadingComment(this);
172                 result.setBody((Block) getBody().clone(target));
173                 result.catchClauses().addAll(
174                         ASTNode.copySubtrees(target, catchClauses()));
175                 result.setFinally(
176                         (Block) ASTNode.copySubtree(target, getFinally()));
177                 return result;
178         }
179
180         /* (omit javadoc for this method)
181          * Method declared on ASTNode.
182          */
183         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
184                 // dispatch to correct overloaded match method
185                 return matcher.match(this, other);
186         }
187
188         /* (omit javadoc for this method)
189          * Method declared on ASTNode.
190          */
191         void accept0(ASTVisitor visitor) {
192                 boolean visitChildren = visitor.visit(this);
193                 if (visitChildren) {
194                         // visit children in normal left to right reading order
195                         acceptChild(visitor, getBody());
196                         acceptChildren(visitor, this.catchClauses);
197                         acceptChild(visitor, getFinally());
198                 }
199                 visitor.endVisit(this);
200         }
201         
202         /**
203          * Returns the body of this try statement.
204          * 
205          * @return the try body
206          */ 
207         public Block getBody() {
208                 if (this.body == null) {
209                         // lazy init must be thread-safe for readers
210                         synchronized (this) {
211                                 if (this.body == null) {
212                                         preLazyInit();
213                                         this.body = new Block(this.ast);
214                                         postLazyInit(this.body, BODY_PROPERTY);
215                                 }
216                         }
217                 }
218                 return this.body;
219         }
220         
221         /**
222          * Sets the body of this try statement.
223          * 
224          * @param body the block node
225          * @exception IllegalArgumentException if:
226          * <ul>
227          * <li>the node belongs to a different AST</li>
228          * <li>the node already has a parent</li>
229          * <li>a cycle in would be created</li>
230          * </ul>
231          */ 
232         public void setBody(Block body) {
233                 if (body == null) {
234                         throw new IllegalArgumentException();
235                 }
236                 ASTNode oldChild = this.body;
237                 preReplaceChild(oldChild, body, BODY_PROPERTY);
238                 this.body = body;
239                 postReplaceChild(oldChild, body, BODY_PROPERTY);
240         }
241
242         /**
243          * Returns the live ordered list of catch clauses for this try statement.
244          * 
245          * @return the live list of catch clauses
246          *    (element type: <code>CatchClause</code>)
247          */ 
248         public List catchClauses() {
249                 return this.catchClauses;
250         }
251                 
252         /**
253          * Returns the finally block of this try statement, or <code>null</code> if 
254          * this try statement has <b>no</b> finally block.
255          * 
256          * @return the finally block, or <code>null</code> if this try statement
257          *    has none
258          */ 
259         public Block getFinally() {
260                 return this.optionalFinallyBody;
261         }
262
263         /**
264          * Sets or clears the finally block of this try statement.
265          * 
266          * @param block the finally block node, or <code>null</code> if 
267          *    there is none
268          * @exception IllegalArgumentException if:
269          * <ul>
270          * <li>the node belongs to a different AST</li>
271          * <li>the node already has a parent</li>
272          * <li>a cycle in would be created</li>
273          * </ul>
274          */ 
275         public void setFinally(Block block) {
276                 ASTNode oldChild = this.optionalFinallyBody;
277                 preReplaceChild(oldChild, block, FINALLY_PROPERTY);
278                 this.optionalFinallyBody = block;
279                 postReplaceChild(oldChild, block, FINALLY_PROPERTY);
280         }
281         
282         /* (omit javadoc for this method)
283          * Method declared on ASTNode.
284          */
285         int memSize() {
286                 return super.memSize() + 3 * 4;
287         }
288         
289         /* (omit javadoc for this method)
290          * Method declared on ASTNode.
291          */
292         int treeSize() {
293                 return
294                         memSize()
295                         + (this.body == null ? 0 : getBody().treeSize())
296                         + this.catchClauses.listSize()
297                         + (this.optionalFinallyBody == null ? 0 : getFinally().treeSize());
298         }
299 }