d986c54952fafb6ef8c0853df0e4f76f03fbbf45
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / ArrayCreation.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 package net.sourceforge.phpdt.core.dom;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17  * Array creation expression AST node type.
18  * For JLS2:
19  * <pre>
20  * ArrayCreation:
21  *    <b>new</b> PrimitiveType <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
22  *    <b>new</b> TypeName <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
23  *    <b>new</b> PrimitiveType <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
24  *    <b>new</b> TypeName <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
25  * </pre>
26  * <p>
27  * The mapping from Java language syntax to AST nodes is as follows:
28  * <ul>
29  * <li>the type node is the array type of the creation expression,
30  *   with one level of array per set of square brackets,</li>
31  * <li>the dimension expressions are collected into the <code>dimensions</code>
32  *   list.</li>
33  * </ul>
34  * </p>
35  * For JLS3, type arguments are added:
36  * <pre>
37  * ArrayCreation:
38  *    <b>new</b> PrimitiveType <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
39  *    <b>new</b> TypeName [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
40  *        <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
41  *    <b>new</b> PrimitiveType <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
42  *    <b>new</b> TypeName [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
43  *        <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
44  * </pre>
45  *
46  * @since 2.0
47  * @noinstantiate This class is not intended to be instantiated by clients.
48  */
49 public class ArrayCreation extends Expression {
50         
51         /**
52          * The "type" structural property of this node type.
53          * @since 3.0
54          */
55         public static final ChildPropertyDescriptor TYPE_PROPERTY = 
56                 new ChildPropertyDescriptor(ArrayCreation.class, "type", ArrayType.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
57
58         /**
59          * The "dimensions" structural property of this node type.
60          * @since 3.0
61          */
62         public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY = 
63                 new ChildListPropertyDescriptor(ArrayCreation.class, "dimensions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
64
65         /**
66          * The "initializer" structural property of this node type.
67          * @since 3.0
68          */
69         public static final ChildPropertyDescriptor INITIALIZER_PROPERTY = 
70                 new ChildPropertyDescriptor(ArrayCreation.class, "initializer", ArrayInitializer.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
71
72         /**
73          * A list of property descriptors (element type: 
74          * {@link StructuralPropertyDescriptor}),
75          * or null if uninitialized.
76          */
77         private static final List PROPERTY_DESCRIPTORS;
78         
79         static {
80                 List properyList = new ArrayList(4);
81                 createPropertyList(ArrayCreation.class, properyList);
82                 addProperty(TYPE_PROPERTY, properyList);
83                 addProperty(DIMENSIONS_PROPERTY, properyList);
84                 addProperty(INITIALIZER_PROPERTY, properyList);
85                 PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
86         }
87
88         /**
89          * Returns a list of structural property descriptors for this node type.
90          * Clients must not modify the result.
91          * 
92          * @param apiLevel the API level; one of the
93          * <code>AST.JLS*</code> constants
94
95          * @return a list of property descriptors (element type: 
96          * {@link StructuralPropertyDescriptor})
97          * @since 3.0
98          */
99         public static List propertyDescriptors(int apiLevel) {
100                 return PROPERTY_DESCRIPTORS;
101         }
102                         
103         /**
104          * The array type; lazily initialized; defaults to a unspecified,
105          * legal array type.
106          */
107         private ArrayType arrayType = null;
108
109         /**
110          * The list of dimension expressions (element type:
111          * <code>Expression</code>). Defaults to an empty list.
112          */
113         private ASTNode.NodeList dimensions =
114                 new ASTNode.NodeList(DIMENSIONS_PROPERTY);
115
116         /**
117          * The optional array initializer, or <code>null</code> if none;
118          * defaults to none.
119          */
120         private ArrayInitializer optionalInitializer = null;
121
122         /**
123          * Creates a new AST node for an array creation expression owned by the 
124          * given AST. By default, the array type is an unspecified 1-dimensional
125          * array, the list of dimensions is empty, and there is no array
126          * initializer.
127          * 
128          * @param ast the AST that is to own this node
129          */
130         ArrayCreation(AST ast) {
131                 super(ast);
132         }
133
134         /* (omit javadoc for this method)
135          * Method declared on ASTNode.
136          */
137         final List internalStructuralPropertiesForType(int apiLevel) {
138                 return propertyDescriptors(apiLevel);
139         }
140                 
141         /* (omit javadoc for this method)
142          * Method declared on ASTNode.
143          */
144         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
145                 if (property == INITIALIZER_PROPERTY) {
146                         if (get) {
147                                 return getInitializer();
148                         } else {
149                                 setInitializer((ArrayInitializer) child);
150                                 return null;
151                         }
152                 }
153                 if (property == TYPE_PROPERTY) {
154                         if (get) {
155                                 return getType();
156                         } else {
157                                 setType((ArrayType) child);
158                                 return null;
159                         }
160                 }
161                 // allow default implementation to flag the error
162                 return super.internalGetSetChildProperty(property, get, child);
163         }
164         
165         /* (omit javadoc for this method)
166          * Method declared on ASTNode.
167          */
168         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
169                 if (property == DIMENSIONS_PROPERTY) {
170                         return dimensions();
171                 }
172                 // allow default implementation to flag the error
173                 return super.internalGetChildListProperty(property);
174         }
175         
176         /* (omit javadoc for this method)
177          * Method declared on ASTNode.
178          */
179         final int getNodeType0() {
180                 return ARRAY_CREATION;
181         }
182
183         /* (omit javadoc for this method)
184          * Method declared on ASTNode.
185          */
186         ASTNode clone0(AST target) {
187                 ArrayCreation result = new ArrayCreation(target);
188                 result.setSourceRange(this.getStartPosition(), this.getLength());
189                 result.setType((ArrayType) getType().clone(target));
190                 result.dimensions().addAll(ASTNode.copySubtrees(target, dimensions()));
191                 result.setInitializer(
192                         (ArrayInitializer) ASTNode.copySubtree(target, getInitializer()));
193                 return result;
194         }
195
196         /* (omit javadoc for this method)
197          * Method declared on ASTNode.
198          */
199         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
200                 // dispatch to correct overloaded match method
201                 return matcher.match(this, other);
202         }
203
204         /* (omit javadoc for this method)
205          * Method declared on ASTNode.
206          */
207         void accept0(ASTVisitor visitor) {
208                 boolean visitChildren = visitor.visit(this);
209                 if (visitChildren) {
210                         // visit children in normal left to right reading order
211                         acceptChild(visitor, getType());
212                         acceptChildren(visitor, this.dimensions);
213                         acceptChild(visitor, getInitializer());
214                 }
215                 visitor.endVisit(this);
216         }
217         
218         /**
219          * Returns the array type in this array creation expression.
220          * 
221          * @return the array type
222          */ 
223         public ArrayType getType() {
224                 if (this.arrayType == null) {
225                         // lazy init must be thread-safe for readers
226                         synchronized (this) {
227                                 if (this.arrayType == null) {
228                                         preLazyInit();
229                                         this.arrayType = this.ast.newArrayType(
230                                                         this.ast.newPrimitiveType(PrimitiveType.INT));
231                                         postLazyInit(this.arrayType, TYPE_PROPERTY);
232                                 }
233                         }
234                 }
235                 return this.arrayType;
236         }
237
238         /**
239          * Sets the array type in this array creation expression.
240          * 
241          * @param type the new array type
242          * @exception IllegalArgumentException if:
243          * <ul>
244          * <li>the node belongs to a different AST</li>
245          * <li>the node already has a parent</li>
246          * </ul>
247          */ 
248         public void setType(ArrayType type) {
249                 if (type == null) {
250                         throw new IllegalArgumentException();
251                 }
252                 // an ArrayCreation cannot occur inside a ArrayType - cycles not possible
253                 ASTNode oldChild = this.arrayType;
254                 preReplaceChild(oldChild, type, TYPE_PROPERTY);
255                 this.arrayType = type;
256                 postReplaceChild(oldChild, type, TYPE_PROPERTY);
257         }
258         
259         /**
260          * Returns the live ordered list of dimension expressions in this array
261          * initializer.
262          * 
263          * @return the live list of dimension expressions
264          *    (element type: <code>Expression</code>)
265          */ 
266         public List dimensions() {
267                 return this.dimensions;
268         }
269         
270         /**
271          * Returns the array initializer of this array creation expression, or 
272          * <code>null</code> if there is none.
273          * 
274          * @return the array initializer node, or <code>null</code> if 
275          *    there is none
276          */ 
277         public ArrayInitializer getInitializer() {
278                 return optionalInitializer;
279         }
280         
281         /**
282          * Sets or clears the array initializer of this array creation expression.
283          * 
284          * @param initializer the array initializer node, or <code>null</code>
285          *    if there is none
286          * @exception IllegalArgumentException if:
287          * <ul>
288          * <li>the node belongs to a different AST</li>
289          * <li>the node already has a parent</li>
290          * <li>a cycle in would be created</li>
291          * </ul>
292          */ 
293         public void setInitializer(ArrayInitializer initializer) {
294                 // an ArrayCreation may occur inside an ArrayInitializer
295                 // must check cycles
296                 ASTNode oldChild = this.optionalInitializer;
297                 preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
298                 this.optionalInitializer = initializer;
299                 postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
300         }
301
302         /* (omit javadoc for this method)
303          * Method declared on ASTNode.
304          */
305         int memSize() {
306                 return BASE_NODE_SIZE + 3 * 4;
307         }
308         
309         /* (omit javadoc for this method)
310          * Method declared on ASTNode.
311          */
312         int treeSize() {
313                 int size = memSize()
314                         + (this.arrayType == null ? 0 : getType().treeSize())
315                         + (this.optionalInitializer == null ? 0 : getInitializer().treeSize())
316                         + this.dimensions.listSize();
317                 return size;
318         }
319 }
320