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