1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2000, 2013 IBM Corporation and others. |
3 | * |
4 | * This program and the accompanying materials |
5 | * are made available under the terms of the Eclipse Public License 2.0 |
6 | * which accompanies this distribution, and is available at |
7 | * https://www.eclipse.org/legal/epl-2.0/ |
8 | * |
9 | * SPDX-License-Identifier: EPL-2.0 |
10 | * |
11 | * Contributors: |
12 | * IBM Corporation - initial API and implementation |
13 | *******************************************************************************/ |
14 | |
15 | package org.eclipse.jdt.core.dom; |
16 | |
17 | import java.util.ArrayList; |
18 | import java.util.List; |
19 | |
20 | /** |
21 | * Enhanced For statement AST node type (added in JLS3 API). |
22 | * |
23 | * <pre> |
24 | * EnhancedForStatement: |
25 | * <b>for</b> <b>(</b> FormalParameter <b>:</b> Expression <b>)</b> |
26 | * Statement |
27 | * </pre> |
28 | * |
29 | * <p>The FormalParameter is represented by a {@link SingleVariableDeclaration} |
30 | * (without an initializer).</p> |
31 | * |
32 | * @since 3.1 |
33 | * @noinstantiate This class is not intended to be instantiated by clients. |
34 | */ |
35 | @SuppressWarnings("rawtypes") |
36 | public class EnhancedForStatement extends Statement { |
37 | |
38 | /** |
39 | * The "parameter" structural property of this node type (child type: {@link SingleVariableDeclaration}). |
40 | */ |
41 | public static final ChildPropertyDescriptor PARAMETER_PROPERTY = |
42 | new ChildPropertyDescriptor(EnhancedForStatement.class, "parameter", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$ |
43 | |
44 | /** |
45 | * The "expression" structural property of this node type (child type: {@link Expression}). |
46 | */ |
47 | public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = |
48 | new ChildPropertyDescriptor(EnhancedForStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$ |
49 | |
50 | /** |
51 | * The "body" structural property of this node type (child type: {@link Statement}). |
52 | */ |
53 | public static final ChildPropertyDescriptor BODY_PROPERTY = |
54 | new ChildPropertyDescriptor(EnhancedForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$ |
55 | |
56 | /** |
57 | * A list of property descriptors (element type: |
58 | * {@link StructuralPropertyDescriptor}), |
59 | * or null if uninitialized. |
60 | */ |
61 | private static final List PROPERTY_DESCRIPTORS; |
62 | |
63 | static { |
64 | List properyList = new ArrayList(4); |
65 | createPropertyList(EnhancedForStatement.class, properyList); |
66 | addProperty(PARAMETER_PROPERTY, properyList); |
67 | addProperty(EXPRESSION_PROPERTY, properyList); |
68 | addProperty(BODY_PROPERTY, properyList); |
69 | PROPERTY_DESCRIPTORS = reapPropertyList(properyList); |
70 | } |
71 | |
72 | /** |
73 | * Returns a list of structural property descriptors for this node type. |
74 | * Clients must not modify the result. |
75 | * |
76 | * @param apiLevel the API level; one of the |
77 | * <code>AST.JLS*</code> constants |
78 | |
79 | * @return a list of property descriptors (element type: |
80 | * {@link StructuralPropertyDescriptor}) |
81 | */ |
82 | public static List propertyDescriptors(int apiLevel) { |
83 | return PROPERTY_DESCRIPTORS; |
84 | } |
85 | |
86 | /** |
87 | * The parameter; lazily initialized; defaults to a unspecified, |
88 | * legal node. |
89 | */ |
90 | private SingleVariableDeclaration parameter = null; |
91 | |
92 | /** |
93 | * The expression; lazily initialized; defaults to a unspecified, but legal, |
94 | * expression. |
95 | */ |
96 | private Expression expression = null; |
97 | |
98 | /** |
99 | * The body statement; lazily initialized; defaults to an empty block |
100 | * statement. |
101 | */ |
102 | private Statement body = null; |
103 | |
104 | /** |
105 | * Creates a new AST node for an enchanced for statement owned by the |
106 | * given AST. By default, the parameter and expression are unspecified |
107 | * but legal subtrees, and the body is an empty block. |
108 | * |
109 | * @param ast the AST that is to own this node |
110 | */ |
111 | EnhancedForStatement(AST ast) { |
112 | super(ast); |
113 | unsupportedIn2(); |
114 | } |
115 | |
116 | @Override |
117 | final List internalStructuralPropertiesForType(int apiLevel) { |
118 | return propertyDescriptors(apiLevel); |
119 | } |
120 | |
121 | @Override |
122 | final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { |
123 | if (property == PARAMETER_PROPERTY) { |
124 | if (get) { |
125 | return getParameter(); |
126 | } else { |
127 | setParameter((SingleVariableDeclaration) child); |
128 | return null; |
129 | } |
130 | } |
131 | if (property == EXPRESSION_PROPERTY) { |
132 | if (get) { |
133 | return getExpression(); |
134 | } else { |
135 | setExpression((Expression) child); |
136 | return null; |
137 | } |
138 | } |
139 | if (property == BODY_PROPERTY) { |
140 | if (get) { |
141 | return getBody(); |
142 | } else { |
143 | setBody((Statement) child); |
144 | return null; |
145 | } |
146 | } |
147 | // allow default implementation to flag the error |
148 | return super.internalGetSetChildProperty(property, get, child); |
149 | } |
150 | |
151 | @Override |
152 | final int getNodeType0() { |
153 | return ENHANCED_FOR_STATEMENT; |
154 | } |
155 | |
156 | @Override |
157 | ASTNode clone0(AST target) { |
158 | EnhancedForStatement result = new EnhancedForStatement(target); |
159 | result.setSourceRange(getStartPosition(), getLength()); |
160 | result.copyLeadingComment(this); |
161 | result.setParameter((SingleVariableDeclaration) getParameter().clone(target)); |
162 | result.setExpression((Expression) getExpression().clone(target)); |
163 | result.setBody( |
164 | (Statement) ASTNode.copySubtree(target, getBody())); |
165 | return result; |
166 | } |
167 | |
168 | @Override |
169 | final boolean subtreeMatch0(ASTMatcher matcher, Object other) { |
170 | // dispatch to correct overloaded match method |
171 | return matcher.match(this, other); |
172 | } |
173 | |
174 | @Override |
175 | void accept0(ASTVisitor visitor) { |
176 | boolean visitChildren = visitor.visit(this); |
177 | if (visitChildren) { |
178 | // visit children in normal left to right reading order |
179 | acceptChild(visitor, getParameter()); |
180 | acceptChild(visitor, getExpression()); |
181 | acceptChild(visitor, getBody()); |
182 | } |
183 | visitor.endVisit(this); |
184 | } |
185 | |
186 | /** |
187 | * Returns the formal parameter in this enhanced for statement. |
188 | * |
189 | * @return the parameter |
190 | */ |
191 | public SingleVariableDeclaration getParameter() { |
192 | if (this.parameter == null) { |
193 | // lazy init must be thread-safe for readers |
194 | synchronized (this) { |
195 | if (this.parameter == null) { |
196 | preLazyInit(); |
197 | this.parameter = this.ast.newSingleVariableDeclaration(); |
198 | postLazyInit(this.parameter, PARAMETER_PROPERTY); |
199 | } |
200 | } |
201 | } |
202 | return this.parameter; |
203 | } |
204 | |
205 | /** |
206 | * Sets the formal parameter in this enhanced for statement. |
207 | * |
208 | * @param parameter the new parameter |
209 | * @exception IllegalArgumentException if: |
210 | * <ul> |
211 | * <li>the node belongs to a different AST</li> |
212 | * <li>the node already has a parent</li> |
213 | * </ul> |
214 | */ |
215 | public void setParameter(SingleVariableDeclaration parameter) { |
216 | if (parameter == null) { |
217 | throw new IllegalArgumentException(); |
218 | } |
219 | ASTNode oldChild = this.parameter; |
220 | preReplaceChild(oldChild, parameter, PARAMETER_PROPERTY); |
221 | this.parameter = parameter; |
222 | postReplaceChild(oldChild, parameter, PARAMETER_PROPERTY); |
223 | } |
224 | |
225 | /** |
226 | * Returns the expression of this enhanced for statement. |
227 | * |
228 | * @return the expression node |
229 | */ |
230 | public Expression getExpression() { |
231 | if (this.expression == null) { |
232 | // lazy init must be thread-safe for readers |
233 | synchronized (this) { |
234 | if (this.expression == null) { |
235 | preLazyInit(); |
236 | this.expression = new SimpleName(this.ast); |
237 | postLazyInit(this.expression, EXPRESSION_PROPERTY); |
238 | } |
239 | } |
240 | } |
241 | return this.expression; |
242 | } |
243 | |
244 | /** |
245 | * Sets the expression of this enhanced for statement. |
246 | * |
247 | * @param expression the new expression node |
248 | * @exception IllegalArgumentException if: |
249 | * <ul> |
250 | * <li>the node belongs to a different AST</li> |
251 | * <li>the node already has a parent</li> |
252 | * <li>a cycle in would be created</li> |
253 | * </ul> |
254 | */ |
255 | public void setExpression(Expression expression) { |
256 | if (expression == null) { |
257 | throw new IllegalArgumentException(); |
258 | } |
259 | ASTNode oldChild = this.expression; |
260 | preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY); |
261 | this.expression = expression; |
262 | postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY); |
263 | } |
264 | |
265 | /** |
266 | * Returns the body of this enchanced for statement. |
267 | * |
268 | * @return the body statement node |
269 | */ |
270 | public Statement getBody() { |
271 | if (this.body == null) { |
272 | // lazy init must be thread-safe for readers |
273 | synchronized (this) { |
274 | if (this.body == null) { |
275 | preLazyInit(); |
276 | this.body = new Block(this.ast); |
277 | postLazyInit(this.body, BODY_PROPERTY); |
278 | } |
279 | } |
280 | } |
281 | return this.body; |
282 | } |
283 | |
284 | /** |
285 | * Sets the body of this enhanced for statement. |
286 | * |
287 | * @param statement the body statement node |
288 | * @exception IllegalArgumentException if: |
289 | * <ul> |
290 | * <li>the node belongs to a different AST</li> |
291 | * <li>the node already has a parent</li> |
292 | * <li>a cycle in would be created</li> |
293 | * </ul> |
294 | */ |
295 | public void setBody(Statement statement) { |
296 | if (statement == null) { |
297 | throw new IllegalArgumentException(); |
298 | } |
299 | ASTNode oldChild = this.body; |
300 | preReplaceChild(oldChild, statement, BODY_PROPERTY); |
301 | this.body = statement; |
302 | postReplaceChild(oldChild, statement, BODY_PROPERTY); |
303 | } |
304 | |
305 | @Override |
306 | int memSize() { |
307 | return super.memSize() + 3 * 4; |
308 | } |
309 | |
310 | @Override |
311 | int treeSize() { |
312 | return |
313 | memSize() |
314 | + (this.parameter == null ? 0 : getParameter().treeSize()) |
315 | + (this.expression == null ? 0 : getExpression().treeSize()) |
316 | + (this.body == null ? 0 : getBody().treeSize()); |
317 | } |
318 | } |
319 |
Members