ed730ca0a1ba9f68fd471856359e9ab377fbbfdf
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / MethodInvocation.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 package net.sourceforge.phpdt.core.dom;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17  * Method invocation expression AST node type.
18  * For JLS2:
19  * <pre>
20  * MethodInvocation:
21  *     [ Expression <b>.</b> ] Identifier
22  *         <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
23  * </pre>
24  * For JLS3, type arguments are added:
25  * <pre>
26  * MethodInvocation:
27  *     [ Expression <b>.</b> ]
28  *         [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
29  *         Identifier <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
30  * </pre>
31  *
32  * @since 2.0
33  * @noinstantiate This class is not intended to be instantiated by clients.
34  */
35 public class MethodInvocation extends Expression {
36
37         /**
38          * The "expression" structural property of this node type.
39          * @since 3.0
40          */
41         public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
42                 new ChildPropertyDescriptor(MethodInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
43
44         /**
45          * The "typeArguments" structural property of this node type (added in JLS3 API).
46          * @since 3.1
47          */
48         public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
49                 new ChildListPropertyDescriptor(MethodInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
50
51         /**
52          * The "name" structural property of this node type.
53          * @since 3.0
54          */
55         public static final ChildPropertyDescriptor NAME_PROPERTY =
56                 new ChildPropertyDescriptor(MethodInvocation.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
57
58         /**
59          * The "arguments" structural property of this node type.
60          * @since 3.0
61          */
62         public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
63                 new ChildListPropertyDescriptor(MethodInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
64
65         /**
66          * A list of property descriptors (element type:
67          * {@link StructuralPropertyDescriptor}),
68          * or null if uninitialized.
69          * @since 3.0
70          */
71         private static final List PROPERTY_DESCRIPTORS_2_0;
72
73         /**
74          * A list of property descriptors (element type:
75          * {@link StructuralPropertyDescriptor}),
76          * or null if uninitialized.
77          * @since 3.1
78          */
79         private static final List PROPERTY_DESCRIPTORS_3_0;
80
81         static {
82                 List properyList = new ArrayList(4);
83                 createPropertyList(MethodInvocation.class, properyList);
84                 addProperty(EXPRESSION_PROPERTY, properyList);
85                 addProperty(NAME_PROPERTY, properyList);
86                 addProperty(ARGUMENTS_PROPERTY, properyList);
87                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
88
89                 properyList = new ArrayList(5);
90                 createPropertyList(MethodInvocation.class, properyList);
91                 addProperty(EXPRESSION_PROPERTY, properyList);
92                 addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
93                 addProperty(NAME_PROPERTY, properyList);
94                 addProperty(ARGUMENTS_PROPERTY, properyList);
95                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
96         }
97
98         /**
99          * Returns a list of structural property descriptors for this node type.
100          * Clients must not modify the result.
101          *
102          * @param apiLevel the API level; one of the
103          * <code>AST.JLS*</code> constants
104
105          * @return a list of property descriptors (element type:
106          * {@link StructuralPropertyDescriptor})
107          * @since 3.0
108          */
109         public static List propertyDescriptors(int apiLevel) {
110                 if (apiLevel == AST.JLS2_INTERNAL) {
111                         return PROPERTY_DESCRIPTORS_2_0;
112                 } else {
113                         return PROPERTY_DESCRIPTORS_3_0;
114                 }
115         }
116
117         /**
118          * The expression; <code>null</code> for none; defaults to none.
119          */
120         private Expression optionalExpression = null;
121
122         /**
123          * The type arguments (element type: <code>Type</code>).
124          * Null in JLS2. Added in JLS3; defaults to an empty list
125          * (see constructor).
126          * @since 3.1
127          */
128         private ASTNode.NodeList typeArguments = null;
129
130         /**
131          * The method name; lazily initialized; defaults to a unspecified,
132          * legal Java method name.
133          */
134         private SimpleName methodName = null;
135
136         /**
137          * The list of argument expressions (element type:
138          * <code>Expression</code>). Defaults to an empty list.
139          */
140         private ASTNode.NodeList arguments =
141                 new ASTNode.NodeList(ARGUMENTS_PROPERTY);
142
143         /**
144          * Creates a new AST node for a method invocation expression owned by the
145          * given AST. By default, no expression, no type arguments,
146          * an unspecified, but legal, method name, and an empty list of arguments.
147          *
148          * @param ast the AST that is to own this node
149          */
150         MethodInvocation(AST ast) {
151                 super(ast);
152                 if (ast.apiLevel >= AST.JLS3) {
153                         this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
154                 }
155         }
156
157         /* (omit javadoc for this method)
158          * Method declared on ASTNode.
159          */
160         final List internalStructuralPropertiesForType(int apiLevel) {
161                 return propertyDescriptors(apiLevel);
162         }
163
164         /* (omit javadoc for this method)
165          * Method declared on ASTNode.
166          */
167         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
168                 if (property == NAME_PROPERTY) {
169                         if (get) {
170                                 return getName();
171                         } else {
172                                 setName((SimpleName) child);
173                                 return null;
174                         }
175                 }
176                 if (property == EXPRESSION_PROPERTY) {
177                         if (get) {
178                                 return getExpression();
179                         } else {
180                                 setExpression((Expression) child);
181                                 return null;
182                         }
183                 }
184                 // allow default implementation to flag the error
185                 return super.internalGetSetChildProperty(property, get, child);
186         }
187
188         /* (omit javadoc for this method)
189          * Method declared on ASTNode.
190          */
191         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
192                 if (property == ARGUMENTS_PROPERTY) {
193                         return arguments();
194                 }
195                 if (property == TYPE_ARGUMENTS_PROPERTY) {
196                         return typeArguments();
197                 }
198                 // allow default implementation to flag the error
199                 return super.internalGetChildListProperty(property);
200         }
201
202         /* (omit javadoc for this method)
203          * Method declared on ASTNode.
204          */
205         final int getNodeType0() {
206                 return METHOD_INVOCATION;
207         }
208
209         /* (omit javadoc for this method)
210          * Method declared on ASTNode.
211          */
212         ASTNode clone0(AST target) {
213                 MethodInvocation result = new MethodInvocation(target);
214                 result.setSourceRange(this.getStartPosition(), this.getLength());
215                 result.setName((SimpleName) getName().clone(target));
216                 result.setExpression(
217                         (Expression) ASTNode.copySubtree(target, getExpression()));
218                 if (this.ast.apiLevel >= AST.JLS3) {
219                         result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
220                 }
221                 result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
222                 return result;
223         }
224
225         /* (omit javadoc for this method)
226          * Method declared on ASTNode.
227          */
228         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
229                 // dispatch to correct overloaded match method
230                 return matcher.match(this, other);
231         }
232
233         /* (omit javadoc for this method)
234          * Method declared on ASTNode.
235          */
236         void accept0(ASTVisitor visitor) {
237                 boolean visitChildren = visitor.visit(this);
238                 if (visitChildren) {
239                         // visit children in normal left to right reading order
240                         acceptChild(visitor, getExpression());
241                         if (this.ast.apiLevel >= AST.JLS3) {
242                                 acceptChildren(visitor, this.typeArguments);
243                         }
244                         acceptChild(visitor, getName());
245                         acceptChildren(visitor, this.arguments);
246                 }
247                 visitor.endVisit(this);
248         }
249
250         /**
251          * Returns the expression of this method invocation expression, or
252          * <code>null</code> if there is none.
253          *
254          * @return the expression node, or <code>null</code> if there is none
255          */
256         public Expression getExpression() {
257                 return this.optionalExpression;
258         }
259
260         /**
261          * Returns <code>true</code> if the resolved return type has been inferred
262          * from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise.
263          * <p>
264          * This information is available only when bindings are requested when the AST is being built
265          * </p>.
266          *
267          * @return <code>true</code> if the resolved return type has been inferred
268          *      from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise
269          * @since 3.3
270          */
271         public boolean isResolvedTypeInferredFromExpectedType() {
272                 return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
273         }
274
275         /**
276          * Sets or clears the expression of this method invocation expression.
277          *
278          * @param expression the expression node, or <code>null</code> if
279          *    there is none
280          * @exception IllegalArgumentException if:
281          * <ul>
282          * <li>the node belongs to a different AST</li>
283          * <li>the node already has a parent</li>
284          * <li>a cycle in would be created</li>
285          * </ul>
286          */
287         public void setExpression(Expression expression) {
288                 ASTNode oldChild = this.optionalExpression;
289                 preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
290                 this.optionalExpression = expression;
291                 postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
292         }
293
294         /**
295          * Returns the live ordered list of type arguments of this method
296          * invocation (added in JLS3 API).
297          *
298          * @return the live list of type arguments
299          *    (element type: <code>Type</code>)
300          * @exception UnsupportedOperationException if this operation is used in
301          * a JLS2 AST
302          * @since 3.1
303          */
304         public List typeArguments() {
305                 // more efficient than just calling unsupportedIn2() to check
306                 if (this.typeArguments == null) {
307                         unsupportedIn2();
308                 }
309                 return this.typeArguments;
310         }
311
312         /**
313          * Returns the name of the method invoked in this expression.
314          *
315          * @return the method name node
316          */
317         public SimpleName getName() {
318                 if (this.methodName == null) {
319                         // lazy init must be thread-safe for readers
320                         synchronized (this) {
321                                 if (this.methodName == null) {
322                                         preLazyInit();
323                                         this.methodName = new SimpleName(this.ast);
324                                         postLazyInit(this.methodName, NAME_PROPERTY);
325                                 }
326                         }
327                 }
328                 return this.methodName;
329         }
330
331         /**
332          * Sets the name of the method invoked in this expression to the
333          * given name.
334          *
335          * @param name the new method name
336          * @exception IllegalArgumentException if:
337          * <ul>
338          * <li>the node belongs to a different AST</li>
339          * <li>the node already has a parent</li>
340          * </ul>
341          */
342         public void setName(SimpleName name) {
343                 if (name == null) {
344                         throw new IllegalArgumentException();
345                 }
346                 ASTNode oldChild = this.methodName;
347                 preReplaceChild(oldChild, name, NAME_PROPERTY);
348                 this.methodName = name;
349                 postReplaceChild(oldChild, name, NAME_PROPERTY);
350         }
351
352         /**
353          * Returns the live ordered list of argument expressions in this method
354          * invocation expression.
355          *
356          * @return the live list of argument expressions
357          *    (element type: <code>Expression</code>)
358          */
359         public List arguments() {
360                 return this.arguments;
361         }
362
363         /**
364          * Resolves and returns the binding for the method invoked by this
365          * expression.
366          * <p>
367          * Note that bindings are generally unavailable unless requested when the
368          * AST is being built.
369          * </p>
370          *
371          * @return the method binding, or <code>null</code> if the binding cannot
372          * be resolved
373          * @since 2.1
374          */
375         public IMethodBinding resolveMethodBinding() {
376                 return this.ast.getBindingResolver().resolveMethod(this);
377         }
378
379         /* (omit javadoc for this method)
380          * Method declared on ASTNode.
381          */
382         int memSize() {
383                 // treat Code as free
384                 return BASE_NODE_SIZE + 4 * 4;
385         }
386
387         /* (omit javadoc for this method)
388          * Method declared on ASTNode.
389          */
390         int treeSize() {
391                 return
392                         memSize()
393                         + (this.optionalExpression == null ? 0 : getExpression().treeSize())
394                         + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
395                         + (this.methodName == null ? 0 : getName().treeSize())
396                         + (this.arguments == null ? 0 : this.arguments.listSize());
397         }
398 }
399