6a6855b4a37fecc1d298933130cac29753169817
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / FieldDeclaration.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  * Field declaration node type.
19  * <p>
20  * This kind of node collects several variable declaration fragments
21  * (<code>VariableDeclarationFragment</code>) into a single body declaration
22  * (<code>BodyDeclaration</code>), all sharing the same modifiers and base type.
23  * </p>
24  * <pre>
25  * FieldDeclaration:
26  *    [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
27  *         { <b>,</b> VariableDeclarationFragment } <b>;</b>
28  * </pre>
29  * <p>
30  * When a Javadoc comment is present, the source range begins with the first
31  * character of the "/**" comment delimiter. When there is no Javadoc comment,
32  * the source range begins with the first character of the initial modifier or
33  * type. The source range extends through the last character of the final ";".
34  * </p>
35  * 
36  * @since 2.0
37  * @noinstantiate This class is not intended to be instantiated by clients.
38  */
39 public class FieldDeclaration extends BodyDeclaration {
40         
41         /**
42          * The "javadoc" structural property of this node type.
43          * @since 3.0
44          */
45         public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
46                 internalJavadocPropertyFactory(FieldDeclaration.class);
47
48         /**
49          * The "modifiers" structural property of this node type (JLS2 API only).
50          * @since 3.0
51          */
52         public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
53                 internalModifiersPropertyFactory(FieldDeclaration.class);
54         
55         /**
56          * The "modifiers" structural property of this node type (added in JLS3 API).
57          * @since 3.1
58          */
59         public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
60                 internalModifiers2PropertyFactory(FieldDeclaration.class);
61         
62         /**
63          * The "type" structural property of this node type.
64          * @since 3.0
65          */
66         public static final ChildPropertyDescriptor TYPE_PROPERTY = 
67                 new ChildPropertyDescriptor(FieldDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
68
69         /**
70          * The "fragments" structural property of this node type).
71          * @since 3.0
72          */
73         public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = 
74                 new ChildListPropertyDescriptor(FieldDeclaration.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
75                 
76         /**
77          * A list of property descriptors (element type: 
78          * {@link StructuralPropertyDescriptor}),
79          * or null if uninitialized.
80          * @since 3.0
81          */
82         private static final List PROPERTY_DESCRIPTORS_2_0;
83         
84         /**
85          * A list of property descriptors (element type: 
86          * {@link StructuralPropertyDescriptor}),
87          * or null if uninitialized.
88          * @since 3.1
89          */
90         private static final List PROPERTY_DESCRIPTORS_3_0;
91         
92         static {
93                 List properyList = new ArrayList(5);
94                 createPropertyList(FieldDeclaration.class, properyList);
95                 addProperty(JAVADOC_PROPERTY, properyList);
96                 addProperty(MODIFIERS_PROPERTY, properyList);
97                 addProperty(TYPE_PROPERTY, properyList);
98                 addProperty(FRAGMENTS_PROPERTY, properyList);
99                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
100                 
101                 properyList = new ArrayList(5);
102                 createPropertyList(FieldDeclaration.class, properyList);
103                 addProperty(JAVADOC_PROPERTY, properyList);
104                 addProperty(MODIFIERS2_PROPERTY, properyList);
105                 addProperty(TYPE_PROPERTY, properyList);
106                 addProperty(FRAGMENTS_PROPERTY, properyList);
107                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
108         }
109
110         /**
111          * Returns a list of structural property descriptors for this node type.
112          * Clients must not modify the result.
113          * 
114          * @param apiLevel the API level; one of the
115          * <code>AST.JLS*</code> constants
116
117          * @return a list of property descriptors (element type: 
118          * {@link StructuralPropertyDescriptor})
119          * @since 3.0
120          */
121         public static List propertyDescriptors(int apiLevel) {
122                 if (apiLevel == AST.JLS2_INTERNAL) {
123                         return PROPERTY_DESCRIPTORS_2_0;
124                 } else {
125                         return PROPERTY_DESCRIPTORS_3_0;
126                 }
127         }
128                         
129         /**
130          * The base type; lazily initialized; defaults to an unspecified,
131          * legal type.
132          */
133         private Type baseType = null;
134
135         /**
136          * The list of variable declaration fragments (element type: 
137          * <code VariableDeclarationFragment</code>).  Defaults to an empty list.
138          */
139         private ASTNode.NodeList variableDeclarationFragments = 
140                 new ASTNode.NodeList(FRAGMENTS_PROPERTY);
141
142         /**
143          * Creates a new unparented field declaration statement node owned 
144          * by the given AST.  By default, the field declaration has: no modifiers,
145          * an unspecified (but legal) type, and an empty list of variable 
146          * declaration fragments (which is syntactically illegal).
147          * <p>
148          * N.B. This constructor is package-private.
149          * </p>
150          * 
151          * @param ast the AST that is to own this node
152          */
153         FieldDeclaration(AST ast) {
154                 super(ast);
155         }
156
157         /* (omit javadoc for this method)
158          * Method declared on ASTNode.
159          * @since 3.0
160          */
161         final List internalStructuralPropertiesForType(int apiLevel) {
162                 return propertyDescriptors(apiLevel);
163         }
164         
165         /* (omit javadoc for this method)
166          * Method declared on ASTNode.
167          */
168         final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
169                 if (property == MODIFIERS_PROPERTY) {
170                         if (get) {
171                                 return getModifiers();
172                         } else {
173                                 internalSetModifiers(value);
174                                 return 0;
175                         }
176                 }
177                 // allow default implementation to flag the error
178                 return super.internalGetSetIntProperty(property, get, value);
179         }
180
181         /* (omit javadoc for this method)
182          * Method declared on ASTNode.
183          */
184         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
185                 if (property == JAVADOC_PROPERTY) {
186                         if (get) {
187                                 return getJavadoc();
188                         } else {
189                                 setJavadoc((Javadoc) child);
190                                 return null;
191                         }
192                 }
193                 if (property == TYPE_PROPERTY) {
194                         if (get) {
195                                 return getType();
196                         } else {
197                                 setType((Type) child);
198                                 return null;
199                         }
200                 }
201                 // allow default implementation to flag the error
202                 return super.internalGetSetChildProperty(property, get, child);
203         }
204         
205         /* (omit javadoc for this method)
206          * Method declared on ASTNode.
207          */
208         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
209                 if (property == MODIFIERS2_PROPERTY) {
210                         return modifiers();
211                 }
212                 if (property == FRAGMENTS_PROPERTY) {
213                         return fragments();
214                 }
215                 // allow default implementation to flag the error
216                 return super.internalGetChildListProperty(property);
217         }
218         
219         /* (omit javadoc for this method)
220          * Method declared on BodyDeclaration.
221          */
222         final ChildPropertyDescriptor internalJavadocProperty() {
223                 return JAVADOC_PROPERTY;
224         }
225
226         /* (omit javadoc for this method)
227          * Method declared on BodyDeclaration.
228          */
229         final SimplePropertyDescriptor internalModifiersProperty() {
230                 return MODIFIERS_PROPERTY;
231         }
232
233         /* (omit javadoc for this method)
234          * Method declared on BodyDeclaration.
235          */
236         final ChildListPropertyDescriptor internalModifiers2Property() {
237                 return MODIFIERS2_PROPERTY;
238         }
239
240         /* (omit javadoc for this method)
241          * Method declared on ASTNode.
242          */
243         final int getNodeType0() {
244                 return FIELD_DECLARATION;
245         }
246
247         /* (omit javadoc for this method)
248          * Method declared on ASTNode.
249          */
250         ASTNode clone0(AST target) {
251                 FieldDeclaration result = new FieldDeclaration(target);
252                 result.setSourceRange(this.getStartPosition(), this.getLength());
253                 result.setJavadoc(
254                         (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
255                 if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
256                         result.internalSetModifiers(getModifiers());
257                 }
258                 if (this.ast.apiLevel >= AST.JLS3) {
259                         result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
260                 }
261                 result.setType((Type) getType().clone(target));
262                 result.fragments().addAll(
263                         ASTNode.copySubtrees(target, fragments()));
264                 return result;
265         }
266         
267         /* (omit javadoc for this method)
268          * Method declared on ASTNode.
269          */
270         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
271                 // dispatch to correct overloaded match method
272                 return matcher.match(this, other);
273         }
274         
275         /* (omit javadoc for this method)
276          * Method declared on ASTNode.
277          */
278         void accept0(ASTVisitor visitor) {
279                 boolean visitChildren = visitor.visit(this);
280                 if (visitChildren) {
281                         // visit children in normal left to right reading order
282                         acceptChild(visitor, getJavadoc());
283                         if (this.ast.apiLevel >= AST.JLS3) {
284                                 acceptChildren(visitor, this.modifiers);
285                         }
286                         acceptChild(visitor, getType());
287                         acceptChildren(visitor, this.variableDeclarationFragments);
288                 }
289                 visitor.endVisit(this);
290         }
291         
292         /**
293          * Returns the base type declared in this field declaration.
294          * <p>
295          * N.B. The individual child variable declaration fragments may specify 
296          * additional array dimensions. So the type of the variable are not 
297          * necessarily exactly this type.
298          * </p>
299          * 
300          * @return the base type
301          */ 
302         public Type getType() {
303                 if (this.baseType == null) {
304                         // lazy init must be thread-safe for readers
305                         synchronized (this) {
306                                 if (this.baseType == null) {
307                                         preLazyInit();
308                                         this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
309                                         postLazyInit(this.baseType, TYPE_PROPERTY);
310                                 }
311                         }
312                 }
313                 return this.baseType;
314         }
315
316         /**
317          * Sets the base type declared in this field declaration to the given type.
318          * 
319          * @param type the new base type
320          * @exception IllegalArgumentException if:
321          * <ul>
322          * <li>the node belongs to a different AST</li>
323          * <li>the node already has a parent</li>
324          * </ul>
325          */ 
326         public void setType(Type type) {
327                 if (type == null) {
328                         throw new IllegalArgumentException();
329                 }
330                 ASTNode oldChild = this.baseType;
331                 preReplaceChild(oldChild, type, TYPE_PROPERTY);
332                 this.baseType = type;
333                 postReplaceChild(oldChild, type, TYPE_PROPERTY);
334         }
335
336         /**
337          * Returns the live list of variable declaration fragments in this field 
338          * declaration. Adding and removing nodes from this list affects this node
339          * dynamically. All nodes in this list must be 
340          * <code>VariableDeclarationFragment</code>s; attempts to add any other 
341          * type of node will trigger an exception.
342          * 
343          * @return the live list of variable declaration fragments in this 
344          *    statement (element type: <code>VariableDeclarationFragment</code>)
345          */ 
346         public List fragments() {
347                 return this.variableDeclarationFragments;
348         }
349                 
350         /* (omit javadoc for this method)
351          * Method declared on ASTNode.
352          */
353         int memSize() {
354                 return super.memSize() + 2 * 4;
355         }
356         
357         /* (omit javadoc for this method)
358          * Method declared on ASTNode.
359          */
360         int treeSize() {
361                 return
362                         memSize()
363                         + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
364                         + (this.modifiers == null ? 0 : this.modifiers.listSize())
365                         + (this.baseType == null ? 0 : getType().treeSize())
366                         + this.variableDeclarationFragments.listSize();
367         }
368 }