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