5361970574a6e323862713223763beea61ad4c86
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / ArrayType.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  * Type node for an array type.
19  * <p>
20  * Array types are expressed in a recursive manner, one dimension at a time.
21  * </p>
22  * <pre>
23  * ArrayType:
24  *    Type <b>[</b> <b>]</b>
25  * </pre>
26  * 
27  * @since 2.0
28  * @noinstantiate This class is not intended to be instantiated by clients.
29  */
30 public class ArrayType extends Type {
31         
32         /**
33          * The "componentType" structural property of this node type.
34          * @since 3.0
35          */
36         public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY = 
37                 new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
38
39         /**
40          * A list of property descriptors (element type: 
41          * {@link StructuralPropertyDescriptor}),
42          * or null if uninitialized.
43          */
44         private static final List PROPERTY_DESCRIPTORS;
45         
46         static {
47                 List properyList = new ArrayList(2);
48                 createPropertyList(ArrayType.class, properyList);
49                 addProperty(COMPONENT_TYPE_PROPERTY, properyList);
50                 PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
51         }
52
53         /**
54          * Returns a list of structural property descriptors for this node type.
55          * Clients must not modify the result.
56          * 
57          * @param apiLevel the API level; one of the
58          * <code>AST.JLS*</code> constants
59
60          * @return a list of property descriptors (element type: 
61          * {@link StructuralPropertyDescriptor})
62          * @since 3.0
63          */
64         public static List propertyDescriptors(int apiLevel) {
65                 return PROPERTY_DESCRIPTORS;
66         }
67                         
68         /** 
69          * The component type; lazily initialized; defaults to a simple type with
70          * an unspecfied, but legal, name.
71          */
72         private Type componentType = null;
73         
74         /**
75          * Creates a new unparented node for an array type owned by the given AST.
76          * By default, a 1-dimensional array of an unspecified simple type.
77          * <p>
78          * N.B. This constructor is package-private.
79          * </p>
80          * 
81          * @param ast the AST that is to own this node
82          */
83         ArrayType(AST ast) {
84                 super(ast);
85         }
86
87         /* (omit javadoc for this method)
88          * Method declared on ASTNode.
89          */
90         final List internalStructuralPropertiesForType(int apiLevel) {
91                 return propertyDescriptors(apiLevel);
92         }
93         
94         /* (omit javadoc for this method)
95          * Method declared on ASTNode.
96          */
97         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
98                 if (property == COMPONENT_TYPE_PROPERTY) {
99                         if (get) {
100                                 return getComponentType();
101                         } else {
102                                 setComponentType((Type) child);
103                                 return null;
104                         }
105                 }
106                 // allow default implementation to flag the error
107                 return super.internalGetSetChildProperty(property, get, child);
108         }
109         
110         /* (omit javadoc for this method)
111          * Method declared on ASTNode.
112          */
113         final int getNodeType0() {
114                 return ARRAY_TYPE;
115         }
116
117         /* (omit javadoc for this method)
118          * Method declared on ASTNode.
119          */
120         ASTNode clone0(AST target) {
121                 ArrayType result = new ArrayType(target);
122                 result.setSourceRange(this.getStartPosition(), this.getLength());
123                 result.setComponentType((Type) getComponentType().clone(target));
124                 return result;
125         }
126
127         /* (omit javadoc for this method)
128          * Method declared on ASTNode.
129          */
130         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
131                 // dispatch to correct overloaded match method
132                 return matcher.match(this, other);
133         }
134
135         /* (omit javadoc for this method)
136          * Method declared on ASTNode.
137          */
138         void accept0(ASTVisitor visitor) {
139                 boolean visitChildren = visitor.visit(this);
140                 if (visitChildren) {
141                         acceptChild(visitor, getComponentType());
142                 }
143                 visitor.endVisit(this);
144         }
145         
146         /**
147          * Returns the component type of this array type. The component type
148          * may be another array type.
149          * 
150          * @return the component type node
151          */ 
152         public Type getComponentType() {
153                 if (this.componentType == null) {
154                         // lazy init must be thread-safe for readers
155                         synchronized (this) {
156                                 if (this.componentType == null) {
157                                         preLazyInit();
158                                         this.componentType = new SimpleType(this.ast);
159                                         postLazyInit(this.componentType, COMPONENT_TYPE_PROPERTY);
160                                 }
161                         }
162                 }
163                 return this.componentType;
164         }
165
166         /**
167          * Sets the component type of this array type. The component type
168          * may be another array type.
169          * 
170          * @param componentType the component type
171          * @exception IllegalArgumentException if:
172          * <ul>
173          * <li>the node belongs to a different AST</li>
174          * <li>the node already has a parent</li>
175          * <li>a cycle in would be created</li>
176          * </ul>
177          */ 
178         public void setComponentType(Type componentType) {
179                 if (componentType == null) {
180                         throw new IllegalArgumentException();
181                 }
182                 ASTNode oldChild = this.componentType;
183                 preReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
184                 this.componentType = componentType;
185                 postReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
186         }
187
188         /**
189          * Returns the element type of this array type. The element type is
190          * never an array type.
191          * <p>
192          * This is a convenience method that descends a chain of nested array types
193          * until it reaches a non-array type. 
194          * </p>
195          * 
196          * @return the component type node
197          */ 
198         public Type getElementType() {
199                 Type t = getComponentType();
200                 while (t.isArrayType()) {
201                         t = ((ArrayType) t).getComponentType();
202                 }
203                 return t;
204         }
205         
206         /**
207          * Returns the number of dimensions in this array type.
208          * <p>
209          * This is a convenience method that descends a chain of nested array types
210          * until it reaches a non-array type. 
211          * </p>
212          * 
213          * @return the number of dimensions (always positive)
214          */ 
215         public int getDimensions() {
216                 Type t = getComponentType();
217                 int dimensions = 1; // always include this array type
218                 while (t.isArrayType()) {
219                         dimensions++;
220                         t = ((ArrayType) t).getComponentType();
221                 }
222                 return dimensions;
223         }
224         
225         /* (omit javadoc for this method)
226          * Method declared on ASTNode.
227          */
228         int memSize() {
229                 return BASE_NODE_SIZE + 1 * 4;
230         }
231         
232         /* (omit javadoc for this method)
233          * Method declared on ASTNode.
234          */
235         int treeSize() {
236                 return
237                         memSize() 
238                         + (this.componentType == null ? 0 : getComponentType().treeSize());
239         }
240 }
241