9c29675184f31c0ea784f24dd6ceeed42cdf9a13
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / IfStatement.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  * If statement AST node type.
19  * <pre>
20  * IfStatement:
21  *    <b>if</b> <b>(</b> Expression <b>)</b> Statement [ <b>else</b> Statement]
22  * </pre>
23  * 
24  * @since 2.0
25  * @noinstantiate This class is not intended to be instantiated by clients.
26  */
27 public class IfStatement extends Statement {
28         
29         /**
30          * The "expression" structural property of this node type.
31          * @since 3.0
32          */
33         public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
34                 new ChildPropertyDescriptor(IfStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
35
36         /**
37          * The "thenStatement" structural property of this node type.
38          * @since 3.0
39          */
40         public static final ChildPropertyDescriptor THEN_STATEMENT_PROPERTY = 
41                 new ChildPropertyDescriptor(IfStatement.class, "thenStatement", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
42
43         /**
44          * The "elseStatement" structural property of this node type.
45          * @since 3.0
46          */
47         public static final ChildPropertyDescriptor ELSE_STATEMENT_PROPERTY = 
48                 new ChildPropertyDescriptor(IfStatement.class, "elseStatement", Statement.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
49
50         /**
51          * A list of property descriptors (element type: 
52          * {@link StructuralPropertyDescriptor}),
53          * or null if uninitialized.
54          */
55         private static final List PROPERTY_DESCRIPTORS;
56         
57         static {
58                 List properyList = new ArrayList(4);
59                 createPropertyList(IfStatement.class, properyList);
60                 addProperty(EXPRESSION_PROPERTY, properyList);
61                 addProperty(THEN_STATEMENT_PROPERTY, properyList);
62                 addProperty(ELSE_STATEMENT_PROPERTY, properyList);
63                 PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
64         }
65
66         /**
67          * Returns a list of structural property descriptors for this node type.
68          * Clients must not modify the result.
69          * 
70          * @param apiLevel the API level; one of the
71          * <code>AST.JLS*</code> constants
72
73          * @return a list of property descriptors (element type: 
74          * {@link StructuralPropertyDescriptor})
75          * @since 3.0
76          */
77         public static List propertyDescriptors(int apiLevel) {
78                 return PROPERTY_DESCRIPTORS;
79         }
80                         
81         /**
82          * The expression; lazily initialized; defaults to an unspecified, but 
83          * legal, expression.
84          */
85         private Expression expression = null;
86
87         /**
88          * The then statement; lazily initialized; defaults to an unspecified, but 
89          * legal, statement.
90          */
91         private Statement thenStatement = null;
92
93         /**
94          * The else statement; <code>null</code> for none; defaults to none.
95          */
96         private Statement optionalElseStatement = null;
97
98         /**
99          * Creates a new unparented if statement node owned by the given 
100          * AST. By default, the expresssion is unspecified,
101          * but legal, the then statement is an empty block, and there is no else
102          * statement.
103          * <p>
104          * N.B. This constructor is package-private.
105          * </p>
106          * 
107          * @param ast the AST that is to own this node
108          */
109         IfStatement(AST ast) {
110                 super(ast);
111         }
112         
113         /* (omit javadoc for this method)
114          * Method declared on ASTNode.
115          */
116         final List internalStructuralPropertiesForType(int apiLevel) {
117                 return propertyDescriptors(apiLevel);
118         }
119         
120         /* (omit javadoc for this method)
121          * Method declared on ASTNode.
122          */
123         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
124                 if (property == EXPRESSION_PROPERTY) {
125                         if (get) {
126                                 return getExpression();
127                         } else {
128                                 setExpression((Expression) child);
129                                 return null;
130                         }
131                 }
132                 if (property == THEN_STATEMENT_PROPERTY) {
133                         if (get) {
134                                 return getThenStatement();
135                         } else {
136                                 setThenStatement((Statement) child);
137                                 return null;
138                         }
139                 }
140                 if (property == ELSE_STATEMENT_PROPERTY) {
141                         if (get) {
142                                 return getElseStatement();
143                         } else {
144                                 setElseStatement((Statement) child);
145                                 return null;
146                         }
147                 }
148                 // allow default implementation to flag the error
149                 return super.internalGetSetChildProperty(property, get, child);
150         }
151         
152         /* (omit javadoc for this method)
153          * Method declared on ASTNode.
154          */
155         final int getNodeType0() {
156                 return IF_STATEMENT;
157         }
158
159         /* (omit javadoc for this method)
160          * Method declared on ASTNode.
161          */
162         ASTNode clone0(AST target) {
163                 IfStatement result = new IfStatement(target);
164                 result.setSourceRange(this.getStartPosition(), this.getLength());
165                 result.copyLeadingComment(this);
166                 result.setExpression((Expression) getExpression().clone(target));
167                 result.setThenStatement(
168                         (Statement) getThenStatement().clone(target));
169                 result.setElseStatement(
170                         (Statement) ASTNode.copySubtree(target, getElseStatement()));
171                 return result;
172         }
173
174         /* (omit javadoc for this method)
175          * Method declared on ASTNode.
176          */
177         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
178                 // dispatch to correct overloaded match method
179                 return matcher.match(this, other);
180         }
181
182         /* (omit javadoc for this method)
183          * Method declared on ASTNode.
184          */
185         void accept0(ASTVisitor visitor) {
186                 boolean visitChildren = visitor.visit(this);
187                 if (visitChildren) {
188                         // visit children in normal left to right reading order
189                         acceptChild(visitor, getExpression());
190                         acceptChild(visitor, getThenStatement());
191                         acceptChild(visitor, getElseStatement());
192                 }
193                 visitor.endVisit(this);
194         }
195         
196         /**
197          * Returns the expression of this if statement.
198          * 
199          * @return the expression node
200          */ 
201         public Expression getExpression() {
202                 if (this.expression == null) {
203                         // lazy init must be thread-safe for readers
204                         synchronized (this) {
205                                 if (this.expression == null) {
206                                         preLazyInit();
207                                         this.expression = new SimpleName(this.ast);
208                                         postLazyInit(this.expression, EXPRESSION_PROPERTY);
209                                 }
210                         }
211                 }
212                 return this.expression;
213         }
214         
215         /**
216          * Sets the condition of this if statement.
217          * 
218          * @param expression the expression node
219          * @exception IllegalArgumentException if:
220          * <ul>
221          * <li>the node belongs to a different AST</li>
222          * <li>the node already has a parent</li>
223          * <li>a cycle in would be created</li>
224          * </ul>
225          */ 
226         public void setExpression(Expression expression) {
227                 if (expression == null) {
228                         throw new IllegalArgumentException();
229                 }
230                 ASTNode oldChild = this.expression;
231                 preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
232                 this.expression = expression;
233                 postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
234         }
235
236         /**
237          * Returns the "then" part of this if statement.
238          * 
239          * @return the "then" statement node
240          */ 
241         public Statement getThenStatement() {
242                 if (this.thenStatement == null) {
243                         // lazy init must be thread-safe for readers
244                         synchronized (this) {
245                                 if (this.thenStatement == null) {
246                                         preLazyInit();
247                                         this.thenStatement = new Block(this.ast);
248                                         postLazyInit(this.thenStatement, THEN_STATEMENT_PROPERTY);
249                                 }
250                         }
251                 }
252                 return this.thenStatement;
253         }
254         
255         /**
256          * Sets the "then" part of this if statement.
257          * <p>
258          * Special note: The Java language does not allow a local variable declaration
259          * to appear as the "then" part of an if statement (they may only appear within a
260          * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
261          * as the thenStatement of a <code>IfStatement</code>. To get something that will
262          * compile, be sure to embed the <code>VariableDeclarationStatement</code>
263          * inside a <code>Block</code>.
264          * </p>
265          * 
266          * @param statement the "then" statement node
267          * @exception IllegalArgumentException if:
268          * <ul>
269          * <li>the node belongs to a different AST</li>
270          * <li>the node already has a parent</li>
271          * <li>a cycle in would be created</li>
272          * </ul>
273          */ 
274         public void setThenStatement(Statement statement) {
275                 if (statement == null) {
276                         throw new IllegalArgumentException();
277                 }
278                 ASTNode oldChild = this.thenStatement;
279                 preReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
280                 this.thenStatement = statement;
281                 postReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
282         }
283
284         /**
285          * Returns the "else" part of this if statement, or <code>null</code> if
286          * this if statement has <b>no</b> "else" part.
287          * <p>
288          * Note that there is a subtle difference between having no else 
289          * statement and having an empty statement ("{}") or null statement (";").
290          * </p>
291          * 
292          * @return the "else" statement node, or <code>null</code> if none
293          */ 
294         public Statement getElseStatement() {
295                 return this.optionalElseStatement;
296         }
297
298         /**
299          * Sets or clears the "else" part of this if statement.
300          * <p>
301          * Note that there is a subtle difference between having no else part
302          * (as in <code>"if(true){}"</code>) and having an empty block (as in
303          * "if(true){}else{}") or null statement (as in "if(true){}else;"). 
304          * </p>
305          * <p>
306          * Special note: The Java language does not allow a local variable declaration
307          * to appear as the "else" part of an if statement (they may only appear within a
308          * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
309          * as the elseStatement of a <code>IfStatement</code>. To get something that will
310          * compile, be sure to embed the <code>VariableDeclarationStatement</code>
311          * inside a <code>Block</code>.
312          * </p>
313          * 
314          * @param statement the "else" statement node, or <code>null</code> if 
315          *    there is none
316          * @exception IllegalArgumentException if:
317          * <ul>
318          * <li>the node belongs to a different AST</li>
319          * <li>the node already has a parent</li>
320          * <li>a cycle in would be created</li>
321          * </ul>
322          */ 
323         public void setElseStatement(Statement statement) {
324                 ASTNode oldChild = this.optionalElseStatement;
325                 preReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
326                 this.optionalElseStatement = statement;
327                 postReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
328         }
329         
330         /* (omit javadoc for this method)
331          * Method declared on ASTNode.
332          */
333         int memSize() {
334                 return super.memSize() + 3 * 4;
335         }
336         
337         /* (omit javadoc for this method)
338          * Method declared on ASTNode.
339          */
340         int treeSize() {
341                 return
342                         memSize()
343                         + (this.expression == null ? 0 : getExpression().treeSize())
344                         + (this.thenStatement == null ? 0 : getThenStatement().treeSize())
345                         + (this.optionalElseStatement == null ? 0 : getElseStatement().treeSize());
346         }
347 }
348