001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: /**
017: * Local variable declaration statement AST node type.
018: * <p>
019: * This kind of node collects several variable declaration fragments
020: * (<code>VariableDeclarationFragment</code>) into a statement
021: * (<code>Statement</code>), all sharing the same modifiers and base type.
022: * </p>
023: * For JLS2:
024: * <pre>
025: * VariableDeclarationStatement:
026: * { Modifier } Type VariableDeclarationFragment
027: * { <b>,</b> VariableDeclarationFragment } <b>;</b>
028: * </pre>
029: * For JLS3, the modifier flags were replaced by
030: * a list of modifier nodes (intermixed with annotations):
031: * <pre>
032: * VariableDeclarationStatement:
033: * { ExtendedModifier } Type VariableDeclarationFragment
034: * { <b>,</b> VariableDeclarationFragment } <b>;</b>
035: * </pre>
036: * <p>
037: * Note: This type of node is a convenience of sorts.
038: * An equivalent way to represent the same statement is to use
039: * a <code>VariableDeclarationExpression</code>
040: * wrapped in an <code>ExpressionStatement</code>.
041: * </p>
042: *
043: * @since 2.0
044: */
045: public class VariableDeclarationStatement extends Statement {
046:
047: /**
048: * The "modifiers" structural property of this node type (JLS2 API only).
049: * @since 3.0
050: */
051: public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = new SimplePropertyDescriptor(
052: VariableDeclarationStatement.class,
053: "modifiers", int.class, MANDATORY); //$NON-NLS-1$
054:
055: /**
056: * The "modifiers" structural property of this node type (added in JLS3 API).
057: * @since 3.1
058: */
059: public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = new ChildListPropertyDescriptor(
060: VariableDeclarationStatement.class,
061: "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
062:
063: /**
064: * The "type" structural property of this node type.
065: * @since 3.0
066: */
067: public static final ChildPropertyDescriptor TYPE_PROPERTY = new ChildPropertyDescriptor(
068: VariableDeclarationStatement.class,
069: "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
070:
071: /**
072: * The "fragments" structural property of this node type).
073: * @since 3.0
074: */
075: public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = new ChildListPropertyDescriptor(
076: VariableDeclarationStatement.class,
077: "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
078:
079: /**
080: * A list of property descriptors (element type:
081: * {@link StructuralPropertyDescriptor}),
082: * or null if uninitialized.
083: * @since 3.0
084: */
085: private static final List PROPERTY_DESCRIPTORS_2_0;
086:
087: /**
088: * A list of property descriptors (element type:
089: * {@link StructuralPropertyDescriptor}),
090: * or null if uninitialized.
091: * @since 3.1
092: */
093: private static final List PROPERTY_DESCRIPTORS_3_0;
094:
095: static {
096: List propertyList = new ArrayList(4);
097: createPropertyList(VariableDeclarationStatement.class,
098: propertyList);
099: addProperty(MODIFIERS_PROPERTY, propertyList);
100: addProperty(TYPE_PROPERTY, propertyList);
101: addProperty(FRAGMENTS_PROPERTY, propertyList);
102: PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
103:
104: propertyList = new ArrayList(4);
105: createPropertyList(VariableDeclarationStatement.class,
106: propertyList);
107: addProperty(MODIFIERS2_PROPERTY, propertyList);
108: addProperty(TYPE_PROPERTY, propertyList);
109: addProperty(FRAGMENTS_PROPERTY, propertyList);
110: PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
111: }
112:
113: /**
114: * Returns a list of structural property descriptors for this node type.
115: * Clients must not modify the result.
116: *
117: * @param apiLevel the API level; one of the
118: * <code>AST.JLS*</code> constants
119:
120: * @return a list of property descriptors (element type:
121: * {@link StructuralPropertyDescriptor})
122: * @since 3.0
123: */
124: public static List propertyDescriptors(int apiLevel) {
125: if (apiLevel == AST.JLS2_INTERNAL) {
126: return PROPERTY_DESCRIPTORS_2_0;
127: } else {
128: return PROPERTY_DESCRIPTORS_3_0;
129: }
130: }
131:
132: /**
133: * The extended modifiers (element type: <code>IExtendedModifier</code>).
134: * Null in JLS2. Added in JLS3; defaults to an empty list
135: * (see constructor).
136: * @since 3.1
137: */
138: private ASTNode.NodeList modifiers = null;
139:
140: /**
141: * The modifier flagss; bit-wise or of Modifier flags.
142: * Defaults to none. Not used in JLS3.
143: */
144: private int modifierFlags = Modifier.NONE;
145:
146: /**
147: * The base type; lazily initialized; defaults to an unspecified,
148: * legal type.
149: */
150: private Type baseType = null;
151:
152: /**
153: * The list of variable variable declaration fragments (element type:
154: * <code VariableDeclarationFragment</code>). Defaults to an empty list.
155: */
156: private ASTNode.NodeList variableDeclarationFragments = new ASTNode.NodeList(
157: FRAGMENTS_PROPERTY);
158:
159: /**
160: * Creates a new unparented local variable declaration statement node owned
161: * by the given AST. By default, the variable declaration has: no modifiers,
162: * an unspecified (but legal) type, and an empty list of variable
163: * declaration fragments (which is syntactically illegal).
164: * <p>
165: * N.B. This constructor is package-private.
166: * </p>
167: *
168: * @param ast the AST that is to own this node
169: */
170: VariableDeclarationStatement(AST ast) {
171: super (ast);
172: if (ast.apiLevel >= AST.JLS3) {
173: this .modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
174: }
175: }
176:
177: /* (omit javadoc for this method)
178: * Method declared on ASTNode.
179: */
180: final List internalStructuralPropertiesForType(int apiLevel) {
181: return propertyDescriptors(apiLevel);
182: }
183:
184: /* (omit javadoc for this method)
185: * Method declared on ASTNode.
186: */
187: final int internalGetSetIntProperty(
188: SimplePropertyDescriptor property, boolean get, int value) {
189: if (property == MODIFIERS_PROPERTY) {
190: if (get) {
191: return getModifiers();
192: } else {
193: setModifiers(value);
194: return 0;
195: }
196: }
197: // allow default implementation to flag the error
198: return super .internalGetSetIntProperty(property, get, value);
199: }
200:
201: /* (omit javadoc for this method)
202: * Method declared on ASTNode.
203: */
204: final ASTNode internalGetSetChildProperty(
205: ChildPropertyDescriptor property, boolean get, ASTNode child) {
206: if (property == TYPE_PROPERTY) {
207: if (get) {
208: return getType();
209: } else {
210: setType((Type) child);
211: return null;
212: }
213: }
214: // allow default implementation to flag the error
215: return super .internalGetSetChildProperty(property, get, child);
216: }
217:
218: /* (omit javadoc for this method)
219: * Method declared on ASTNode.
220: */
221: final List internalGetChildListProperty(
222: ChildListPropertyDescriptor property) {
223: if (property == MODIFIERS2_PROPERTY) {
224: return modifiers();
225: }
226: if (property == FRAGMENTS_PROPERTY) {
227: return fragments();
228: }
229: // allow default implementation to flag the error
230: return super .internalGetChildListProperty(property);
231: }
232:
233: /* (omit javadoc for this method)
234: * Method declared on ASTNode.
235: */
236: final int getNodeType0() {
237: return VARIABLE_DECLARATION_STATEMENT;
238: }
239:
240: /* (omit javadoc for this method)
241: * Method declared on ASTNode.
242: */
243: ASTNode clone0(AST target) {
244: VariableDeclarationStatement result = new VariableDeclarationStatement(
245: target);
246: result
247: .setSourceRange(this .getStartPosition(), this
248: .getLength());
249: result.copyLeadingComment(this );
250: if (this .ast.apiLevel == AST.JLS2_INTERNAL) {
251: result.setModifiers(getModifiers());
252: }
253: if (this .ast.apiLevel >= AST.JLS3) {
254: result.modifiers().addAll(
255: ASTNode.copySubtrees(target, modifiers()));
256: }
257: result.setType((Type) getType().clone(target));
258: result.fragments().addAll(
259: ASTNode.copySubtrees(target, fragments()));
260: return result;
261: }
262:
263: /* (omit javadoc for this method)
264: * Method declared on ASTNode.
265: */
266: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
267: // dispatch to correct overloaded match method
268: return matcher.match(this , other);
269: }
270:
271: /* (omit javadoc for this method)
272: * Method declared on ASTNode.
273: */
274: void accept0(ASTVisitor visitor) {
275: boolean visitChildren = visitor.visit(this );
276: if (visitChildren) {
277: // visit children in normal left to right reading order
278: if (this .ast.apiLevel >= AST.JLS3) {
279: acceptChildren(visitor, this .modifiers);
280: }
281: acceptChild(visitor, getType());
282: acceptChildren(visitor, this .variableDeclarationFragments);
283: }
284: visitor.endVisit(this );
285: }
286:
287: /**
288: * Returns the live ordered list of modifiers and annotations
289: * of this declaration (added in JLS3 API).
290: * <p>
291: * Note that the final modifier is the only meaningful modifier for local
292: * variable declarations.
293: * </p>
294: *
295: * @return the live list of modifiers and annotations
296: * (element type: <code>IExtendedModifier</code>)
297: * @exception UnsupportedOperationException if this operation is used in
298: * a JLS2 AST
299: * @since 3.1
300: */
301: public List modifiers() {
302: // more efficient than just calling unsupportedIn2() to check
303: if (this .modifiers == null) {
304: unsupportedIn2();
305: }
306: return this .modifiers;
307: }
308:
309: /**
310: * Returns the modifiers explicitly specified on this declaration.
311: * <p>
312: * In the JLS3 API, this method is a convenience method that
313: * computes these flags from <code>modifiers()</code>.
314: * </p>
315: *
316: * @return the bit-wise or of <code>Modifier</code> constants
317: * @see Modifier
318: */
319: public int getModifiers() {
320: // more efficient than checking getAST().API_LEVEL
321: if (this .modifiers == null) {
322: // JLS2 behavior - bona fide property
323: return this .modifierFlags;
324: } else {
325: // JLS3 behavior - convenience method
326: // performance could be improved by caching computed flags
327: // but this would require tracking changes to this.modifiers
328: int computedModifierFlags = Modifier.NONE;
329: for (Iterator it = modifiers().iterator(); it.hasNext();) {
330: Object x = it.next();
331: if (x instanceof Modifier) {
332: computedModifierFlags |= ((Modifier) x)
333: .getKeyword().toFlagValue();
334: }
335: }
336: return computedModifierFlags;
337: }
338: }
339:
340: /**
341: * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
342: * <p>
343: * Note that the final modifier is the only meaningful modifier for local
344: * variable declarations.
345: * </p>
346: *
347: * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
348: * @exception UnsupportedOperationException if this operation is used in
349: * an AST later than JLS2
350: * @see Modifier
351: * @deprecated In the JLS3 API, this method is replaced by
352: * {@link #modifiers()} which contains a list of a <code>Modifier</code> nodes.
353: */
354: public void setModifiers(int modifiers) {
355: internalSetModifiers(modifiers);
356: }
357:
358: /**
359: * Internal synonym for deprecated method. Used to avoid
360: * deprecation warnings.
361: * @since 3.1
362: */
363: /*package*/final void internalSetModifiers(int pmodifiers) {
364: supportedOnlyIn2();
365: preValueChange(MODIFIERS_PROPERTY);
366: this .modifierFlags = pmodifiers;
367: postValueChange(MODIFIERS_PROPERTY);
368: }
369:
370: /**
371: * Returns the base type declared in this variable declaration statement.
372: * <p>
373: * N.B. The individual child variable declaration fragments may specify
374: * additional array dimensions. So the type of the variable are not
375: * necessarily exactly this type.
376: * </p>
377: *
378: * @return the base type
379: */
380: public Type getType() {
381: if (this .baseType == null) {
382: // lazy init must be thread-safe for readers
383: synchronized (this ) {
384: if (this .baseType == null) {
385: preLazyInit();
386: this .baseType = this .ast
387: .newPrimitiveType(PrimitiveType.INT);
388: postLazyInit(this .baseType, TYPE_PROPERTY);
389: }
390: }
391: }
392: return this .baseType;
393: }
394:
395: /**
396: * Sets the base type declared in this variable declaration statement to
397: * the given type.
398: *
399: * @param type the new base type
400: * @exception IllegalArgumentException if:
401: * <ul>
402: * <li>the node belongs to a different AST</li>
403: * <li>the node already has a parent</li>
404: * </ul>
405: */
406: public void setType(Type type) {
407: if (type == null) {
408: throw new IllegalArgumentException();
409: }
410: ASTNode oldChild = this .baseType;
411: preReplaceChild(oldChild, type, TYPE_PROPERTY);
412: this .baseType = type;
413: postReplaceChild(oldChild, type, TYPE_PROPERTY);
414: }
415:
416: /**
417: * Returns the live list of variable declaration fragments in this statement.
418: * Adding and removing nodes from this list affects this node dynamically.
419: * All nodes in this list must be <code>VariableDeclarationFragment</code>s;
420: * attempts to add any other type of node will trigger an
421: * exception.
422: *
423: * @return the live list of variable declaration fragments in this
424: * statement (element type: <code>VariableDeclarationFragment</code>)
425: */
426: public List fragments() {
427: return this .variableDeclarationFragments;
428: }
429:
430: /* (omit javadoc for this method)
431: * Method declared on ASTNode.
432: */
433: int memSize() {
434: return super .memSize() + 4 * 4;
435: }
436:
437: /* (omit javadoc for this method)
438: * Method declared on ASTNode.
439: */
440: int treeSize() {
441: return memSize()
442: + (this .modifiers == null ? 0 : this .modifiers
443: .listSize())
444: + (this .baseType == null ? 0 : getType().treeSize())
445: + this.variableDeclarationFragments.listSize();
446: }
447: }
|