001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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.List;
014:
015: /**
016: * Method invocation expression AST node type.
017: * For JLS2:
018: * <pre>
019: * MethodInvocation:
020: * [ Expression <b>.</b> ] Identifier
021: * <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
022: * </pre>
023: * For JLS3, type arguments are added:
024: * <pre>
025: * MethodInvocation:
026: * [ Expression <b>.</b> ]
027: * [ <b><</b> Type { <b>,</b> Type } <b>></b> ]
028: * Identifier <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
029: * </pre>
030: *
031: * @since 2.0
032: */
033: public class MethodInvocation extends Expression {
034:
035: /**
036: * The "expression" structural property of this node type.
037: * @since 3.0
038: */
039: public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = new ChildPropertyDescriptor(
040: MethodInvocation.class,
041: "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
042:
043: /**
044: * The "typeArguments" structural property of this node type (added in JLS3 API).
045: * @since 3.1
046: */
047: public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = new ChildListPropertyDescriptor(
048: MethodInvocation.class,
049: "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
050:
051: /**
052: * The "name" structural property of this node type.
053: * @since 3.0
054: */
055: public static final ChildPropertyDescriptor NAME_PROPERTY = new ChildPropertyDescriptor(
056: MethodInvocation.class,
057: "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
058:
059: /**
060: * The "arguments" structural property of this node type.
061: * @since 3.0
062: */
063: public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY = new ChildListPropertyDescriptor(
064: MethodInvocation.class,
065: "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
066:
067: /**
068: * A list of property descriptors (element type:
069: * {@link StructuralPropertyDescriptor}),
070: * or null if uninitialized.
071: * @since 3.0
072: */
073: private static final List PROPERTY_DESCRIPTORS_2_0;
074:
075: /**
076: * A list of property descriptors (element type:
077: * {@link StructuralPropertyDescriptor}),
078: * or null if uninitialized.
079: * @since 3.1
080: */
081: private static final List PROPERTY_DESCRIPTORS_3_0;
082:
083: static {
084: List properyList = new ArrayList(4);
085: createPropertyList(MethodInvocation.class, properyList);
086: addProperty(EXPRESSION_PROPERTY, properyList);
087: addProperty(NAME_PROPERTY, properyList);
088: addProperty(ARGUMENTS_PROPERTY, properyList);
089: PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
090:
091: properyList = new ArrayList(5);
092: createPropertyList(MethodInvocation.class, properyList);
093: addProperty(EXPRESSION_PROPERTY, properyList);
094: addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
095: addProperty(NAME_PROPERTY, properyList);
096: addProperty(ARGUMENTS_PROPERTY, properyList);
097: PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
098: }
099:
100: /**
101: * Returns a list of structural property descriptors for this node type.
102: * Clients must not modify the result.
103: *
104: * @param apiLevel the API level; one of the
105: * <code>AST.JLS*</code> constants
106:
107: * @return a list of property descriptors (element type:
108: * {@link StructuralPropertyDescriptor})
109: * @since 3.0
110: */
111: public static List propertyDescriptors(int apiLevel) {
112: if (apiLevel == AST.JLS2_INTERNAL) {
113: return PROPERTY_DESCRIPTORS_2_0;
114: } else {
115: return PROPERTY_DESCRIPTORS_3_0;
116: }
117: }
118:
119: /**
120: * The expression; <code>null</code> for none; defaults to none.
121: */
122: private Expression optionalExpression = null;
123:
124: /**
125: * The type arguments (element type: <code>Type</code>).
126: * Null in JLS2. Added in JLS3; defaults to an empty list
127: * (see constructor).
128: * @since 3.1
129: */
130: private ASTNode.NodeList typeArguments = null;
131:
132: /**
133: * The method name; lazily initialized; defaults to a unspecified,
134: * legal Java method name.
135: */
136: private SimpleName methodName = null;
137:
138: /**
139: * The list of argument expressions (element type:
140: * <code>Expression</code>). Defaults to an empty list.
141: */
142: private ASTNode.NodeList arguments = new ASTNode.NodeList(
143: ARGUMENTS_PROPERTY);
144:
145: /**
146: * Creates a new AST node for a method invocation expression owned by the
147: * given AST. By default, no expression, no type arguments,
148: * an unspecified, but legal, method name, and an empty list of arguments.
149: *
150: * @param ast the AST that is to own this node
151: */
152: MethodInvocation(AST ast) {
153: super (ast);
154: if (ast.apiLevel >= AST.JLS3) {
155: this .typeArguments = new ASTNode.NodeList(
156: TYPE_ARGUMENTS_PROPERTY);
157: }
158: }
159:
160: /* (omit javadoc for this method)
161: * Method declared on ASTNode.
162: */
163: final List internalStructuralPropertiesForType(int apiLevel) {
164: return propertyDescriptors(apiLevel);
165: }
166:
167: /* (omit javadoc for this method)
168: * Method declared on ASTNode.
169: */
170: final ASTNode internalGetSetChildProperty(
171: ChildPropertyDescriptor property, boolean get, ASTNode child) {
172: if (property == NAME_PROPERTY) {
173: if (get) {
174: return getName();
175: } else {
176: setName((SimpleName) child);
177: return null;
178: }
179: }
180: if (property == EXPRESSION_PROPERTY) {
181: if (get) {
182: return getExpression();
183: } else {
184: setExpression((Expression) child);
185: return null;
186: }
187: }
188: // allow default implementation to flag the error
189: return super .internalGetSetChildProperty(property, get, child);
190: }
191:
192: /* (omit javadoc for this method)
193: * Method declared on ASTNode.
194: */
195: final List internalGetChildListProperty(
196: ChildListPropertyDescriptor property) {
197: if (property == ARGUMENTS_PROPERTY) {
198: return arguments();
199: }
200: if (property == TYPE_ARGUMENTS_PROPERTY) {
201: return typeArguments();
202: }
203: // allow default implementation to flag the error
204: return super .internalGetChildListProperty(property);
205: }
206:
207: /* (omit javadoc for this method)
208: * Method declared on ASTNode.
209: */
210: final int getNodeType0() {
211: return METHOD_INVOCATION;
212: }
213:
214: /* (omit javadoc for this method)
215: * Method declared on ASTNode.
216: */
217: ASTNode clone0(AST target) {
218: MethodInvocation result = new MethodInvocation(target);
219: result
220: .setSourceRange(this .getStartPosition(), this
221: .getLength());
222: result.setName((SimpleName) getName().clone(target));
223: result.setExpression((Expression) ASTNode.copySubtree(target,
224: getExpression()));
225: if (this .ast.apiLevel >= AST.JLS3) {
226: result.typeArguments().addAll(
227: ASTNode.copySubtrees(target, typeArguments()));
228: }
229: result.arguments().addAll(
230: ASTNode.copySubtrees(target, arguments()));
231: return result;
232: }
233:
234: /* (omit javadoc for this method)
235: * Method declared on ASTNode.
236: */
237: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
238: // dispatch to correct overloaded match method
239: return matcher.match(this , other);
240: }
241:
242: /* (omit javadoc for this method)
243: * Method declared on ASTNode.
244: */
245: void accept0(ASTVisitor visitor) {
246: boolean visitChildren = visitor.visit(this );
247: if (visitChildren) {
248: // visit children in normal left to right reading order
249: acceptChild(visitor, getExpression());
250: if (this .ast.apiLevel >= AST.JLS3) {
251: acceptChildren(visitor, this .typeArguments);
252: }
253: acceptChild(visitor, getName());
254: acceptChildren(visitor, this .arguments);
255: }
256: visitor.endVisit(this );
257: }
258:
259: /**
260: * Returns the expression of this method invocation expression, or
261: * <code>null</code> if there is none.
262: *
263: * @return the expression node, or <code>null</code> if there is none
264: */
265: public Expression getExpression() {
266: return this .optionalExpression;
267: }
268:
269: /**
270: * Returns <code>true</code> if the resolved return type has been inferred
271: * from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise.
272: * <p>
273: * This information is available only when bindings are requested when the AST is being built
274: * </p>.
275: *
276: * @return <code>true</code> if the resolved return type has been inferred
277: * from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise
278: * @since 3.3
279: */
280: public boolean isResolvedTypeInferredFromExpectedType() {
281: return this .ast.getBindingResolver()
282: .isResolvedTypeInferredFromExpectedType(this );
283: }
284:
285: /**
286: * Sets or clears the expression of this method invocation expression.
287: *
288: * @param expression the expression node, or <code>null</code> if
289: * there is none
290: * @exception IllegalArgumentException if:
291: * <ul>
292: * <li>the node belongs to a different AST</li>
293: * <li>the node already has a parent</li>
294: * <li>a cycle in would be created</li>
295: * </ul>
296: */
297: public void setExpression(Expression expression) {
298: ASTNode oldChild = this .optionalExpression;
299: preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
300: this .optionalExpression = expression;
301: postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
302: }
303:
304: /**
305: * Returns the live ordered list of type arguments of this method
306: * invocation (added in JLS3 API).
307: *
308: * @return the live list of type arguments
309: * (element type: <code>Type</code>)
310: * @exception UnsupportedOperationException if this operation is used in
311: * a JLS2 AST
312: * @since 3.1
313: */
314: public List typeArguments() {
315: // more efficient than just calling unsupportedIn2() to check
316: if (this .typeArguments == null) {
317: unsupportedIn2();
318: }
319: return this .typeArguments;
320: }
321:
322: /**
323: * Returns the name of the method invoked in this expression.
324: *
325: * @return the method name node
326: */
327: public SimpleName getName() {
328: if (this .methodName == null) {
329: // lazy init must be thread-safe for readers
330: synchronized (this ) {
331: if (this .methodName == null) {
332: preLazyInit();
333: this .methodName = new SimpleName(this .ast);
334: postLazyInit(this .methodName, NAME_PROPERTY);
335: }
336: }
337: }
338: return this .methodName;
339: }
340:
341: /**
342: * Sets the name of the method invoked in this expression to the
343: * given name.
344: *
345: * @param name the new method name
346: * @exception IllegalArgumentException if:
347: * <ul>
348: * <li>the node belongs to a different AST</li>
349: * <li>the node already has a parent</li>
350: * </ul>
351: */
352: public void setName(SimpleName name) {
353: if (name == null) {
354: throw new IllegalArgumentException();
355: }
356: ASTNode oldChild = this .methodName;
357: preReplaceChild(oldChild, name, NAME_PROPERTY);
358: this .methodName = name;
359: postReplaceChild(oldChild, name, NAME_PROPERTY);
360: }
361:
362: /**
363: * Returns the live ordered list of argument expressions in this method
364: * invocation expression.
365: *
366: * @return the live list of argument expressions
367: * (element type: <code>Expression</code>)
368: */
369: public List arguments() {
370: return this .arguments;
371: }
372:
373: /**
374: * Resolves and returns the binding for the method invoked by this
375: * expression.
376: * <p>
377: * Note that bindings are generally unavailable unless requested when the
378: * AST is being built.
379: * </p>
380: *
381: * @return the method binding, or <code>null</code> if the binding cannot
382: * be resolved
383: * @since 2.1
384: */
385: public IMethodBinding resolveMethodBinding() {
386: return this .ast.getBindingResolver().resolveMethod(this );
387: }
388:
389: /* (omit javadoc for this method)
390: * Method declared on ASTNode.
391: */
392: int memSize() {
393: // treat Code as free
394: return BASE_NODE_SIZE + 4 * 4;
395: }
396:
397: /* (omit javadoc for this method)
398: * Method declared on ASTNode.
399: */
400: int treeSize() {
401: return memSize()
402: + (this .optionalExpression == null ? 0
403: : getExpression().treeSize())
404: + (this .typeArguments == null ? 0 : this .typeArguments
405: .listSize())
406: + (this .methodName == null ? 0 : getName().treeSize())
407: + (this .arguments == null ? 0 : this.arguments
408: .listSize());
409: }
410: }
|