b044a0672152d9b4f772fa808ad06dc8755234f7
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / MethodRefParameter.java
1 /*******************************************************************************
2  * Copyright (c) 2004, 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
12 package net.sourceforge.phpdt.core.dom;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 /**
18  * AST node for a parameter within a method reference ({@link MethodRef}).
19  * These nodes only occur within doc comments ({@link Javadoc}).
20  * For JLS2:
21  * <pre>
22  * MethodRefParameter:
23  *              Type [ Identifier ]
24  * </pre>
25  * For JLS3, the variable arity indicator was added:
26  * <pre>
27  * MethodRefParameter:
28  *              Type [ <b>...</b> ] [ Identifier ]
29  * </pre>
30  * <p>
31  * Note: The 1.5 spec for the Javadoc tool does not mention the possibility
32  * of a variable arity indicator in method references. However, the 1.5
33  * Javadoc tool itself does indeed support it. Since it makes sense to have
34  * a way to explicitly refer to variable arity methods, it seems more likely
35  * that the Javadoc spec is wrong in this case.
36  * </p>
37  * 
38  * @see Javadoc
39  * @since 3.0
40  * @noinstantiate This class is not intended to be instantiated by clients.
41  */
42 public class MethodRefParameter extends ASTNode {
43         
44         /**
45          * The "type" structural property of this node type.
46          * @since 3.0
47          */
48         public static final ChildPropertyDescriptor TYPE_PROPERTY = 
49                 new ChildPropertyDescriptor(MethodRefParameter.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
50
51         /**
52          * The "varargs" structural property of this node type (added in JLS3 API).
53          * @since 3.1
54          */
55         public static final SimplePropertyDescriptor VARARGS_PROPERTY = 
56                 new SimplePropertyDescriptor(MethodRefParameter.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
57         
58         /**
59          * The "name" structural property of this node type.
60          * @since 3.0
61          */
62         public static final ChildPropertyDescriptor NAME_PROPERTY = 
63                 new ChildPropertyDescriptor(MethodRefParameter.class, "name", SimpleName.class, OPTIONAL, NO_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(3);
83                 createPropertyList(MethodRefParameter.class, properyList);
84                 addProperty(TYPE_PROPERTY, properyList);
85                 addProperty(NAME_PROPERTY, properyList);
86                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
87                 
88                 properyList = new ArrayList(3);
89                 createPropertyList(MethodRefParameter.class, properyList);
90                 addProperty(TYPE_PROPERTY, properyList);
91                 addProperty(VARARGS_PROPERTY, properyList);
92                 addProperty(NAME_PROPERTY, properyList);
93                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
94         }
95
96         /**
97          * Returns a list of structural property descriptors for this node type.
98          * Clients must not modify the result.
99          * 
100          * @param apiLevel the API level; one of the AST.JLS* constants
101          * @return a list of property descriptors (element type: 
102          * {@link StructuralPropertyDescriptor})
103          * @since 3.0
104          */
105         public static List propertyDescriptors(int apiLevel) {
106                 if (apiLevel == AST.JLS2_INTERNAL) {
107                         return PROPERTY_DESCRIPTORS_2_0;
108                 } else {
109                         return PROPERTY_DESCRIPTORS_3_0;
110                 }
111         }
112                         
113         /**
114          * The type; lazily initialized; defaults to a unspecified,
115          * legal type.
116          */
117         private Type type = null;
118
119         /**
120          * Indicates the last parameter of a variable arity method;
121          * defaults to false.
122          * 
123          * @since 3.1
124          */
125         private boolean variableArity = false;
126
127         /**
128          * The parameter name, or <code>null</code> if none; none by
129          * default.
130          */
131         private SimpleName optionalParameterName = null;
132
133         /**
134          * Creates a new AST node for a method referenece parameter owned by the given 
135          * AST. By default, the node has an unspecified (but legal) type, 
136          * not variable arity, and no parameter name.
137          * <p>
138          * N.B. This constructor is package-private.
139          * </p>
140          * 
141          * @param ast the AST that is to own this node
142          */
143         MethodRefParameter(AST ast) {
144                 super(ast);
145         }
146
147         /* (omit javadoc for this method)
148          * Method declared on ASTNode.
149          */
150         final List internalStructuralPropertiesForType(int apiLevel) {
151                 return propertyDescriptors(apiLevel);
152         }
153         
154         /* (omit javadoc for this method)
155          * Method declared on ASTNode.
156          */
157         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
158                 if (property == TYPE_PROPERTY) {
159                         if (get) {
160                                 return getType();
161                         } else {
162                                 setType((Type) child);
163                                 return null;
164                         }
165                 }
166                 if (property == NAME_PROPERTY) {
167                         if (get) {
168                                 return getName();
169                         } else {
170                                 setName((SimpleName) child);
171                                 return null;
172                         }
173                 }
174                 // allow default implementation to flag the error
175                 return super.internalGetSetChildProperty(property, get, child);
176         }
177         
178         /* (omit javadoc for this method)
179          * Method declared on ASTNode.
180          */
181         final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
182                 if (property == VARARGS_PROPERTY) {
183                         if (get) {
184                                 return isVarargs();
185                         } else {
186                                 setVarargs(value);
187                                 return false;
188                         }
189                 }
190                 // allow default implementation to flag the error
191                 return super.internalGetSetBooleanProperty(property, get, value);
192         }
193         
194         /* (omit javadoc for this method)
195          * Method declared on ASTNode.
196          */
197         final int getNodeType0() {
198                 return METHOD_REF_PARAMETER;
199         }
200
201         /* (omit javadoc for this method)
202          * Method declared on ASTNode.
203          */
204         ASTNode clone0(AST target) {
205                 MethodRefParameter result = new MethodRefParameter(target);
206                 result.setSourceRange(this.getStartPosition(), this.getLength());
207                 result.setType((Type) ASTNode.copySubtree(target, getType()));
208                 if (this.ast.apiLevel >= AST.JLS3) {
209                         result.setVarargs(isVarargs());
210                 }
211                 result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
212                 return result;
213         }
214
215         /* (omit javadoc for this method)
216          * Method declared on ASTNode.
217          */
218         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
219                 // dispatch to correct overloaded match method
220                 return matcher.match(this, other);
221         }
222         
223         /* (omit javadoc for this method)
224          * Method declared on ASTNode.
225          */
226         void accept0(ASTVisitor visitor) {
227                 boolean visitChildren = visitor.visit(this);
228                 if (visitChildren) {
229                         // visit children in normal left to right reading order
230                         acceptChild(visitor, getType());
231                         acceptChild(visitor, getName());
232                 }
233                 visitor.endVisit(this);
234         }
235         
236         /**
237          * Returns the paramter type.
238          * 
239          * @return the parameter type
240          */ 
241         public Type getType() {
242                 if (this.type == null) {
243                         // lazy init must be thread-safe for readers
244                         synchronized (this) {
245                                 if (this.type == null) {
246                                         preLazyInit();
247                                         this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
248                                         postLazyInit(this.type, TYPE_PROPERTY);
249                                 }
250                         }
251                 }
252                 return this.type;
253         }
254
255         /**
256          * Sets the paramter type to the given type.
257          * 
258          * @param type the new type
259          * @exception IllegalArgumentException if:
260          * <ul>
261          * <li>the type is <code>null</code></li>
262          * <li>the node belongs to a different AST</li>
263          * <li>the node already has a parent</li>
264          * </ul>
265          */ 
266         public void setType(Type type) {
267                 if (type == null) {
268                         throw new IllegalArgumentException();
269                 }
270                 ASTNode oldChild = this.type;
271                 preReplaceChild(oldChild, type, TYPE_PROPERTY);
272                 this.type = type;
273                 postReplaceChild(oldChild, type, TYPE_PROPERTY);
274         }
275
276         /**
277          * Returns whether this method reference parameter is for
278          * the last parameter of a variable arity method (added in JLS3 API).
279          * <p>
280          * Note that the binding for the type <code>Foo</code>in the vararg method
281          * reference <code>#fun(Foo...)</code> is always for the type as 
282          * written; i.e., the type binding for <code>Foo</code>. However, if you
283          * navigate from the MethodRef to its method binding to the
284          * type binding for its last parameter, the type binding for the vararg
285          * parameter is always an array type (i.e., <code>Foo[]</code>) reflecting
286          * the way vararg methods get compiled.
287          * </p>
288          * 
289          * @return <code>true</code> if this is a variable arity parameter,
290          *    and <code>false</code> otherwise
291          * @exception UnsupportedOperationException if this operation is used in
292          * a JLS2 AST
293          * @since 3.1
294          */ 
295         public boolean isVarargs() {
296                 unsupportedIn2();
297                 return this.variableArity;
298         }
299
300         /**
301          * Sets whether this method reference parameter is for the last parameter of
302          * a variable arity method (added in JLS3 API).
303          * 
304          * @param variableArity <code>true</code> if this is a variable arity
305          *    parameter, and <code>false</code> otherwise
306          * @since 3.1
307          */ 
308         public void setVarargs(boolean variableArity) {
309                 unsupportedIn2();
310                 preValueChange(VARARGS_PROPERTY);
311                 this.variableArity = variableArity;
312                 postValueChange(VARARGS_PROPERTY);
313         }
314
315         /**
316          * Returns the parameter name, or <code>null</code> if there is none.
317          * 
318          * @return the parameter name node, or <code>null</code> if there is none
319          */ 
320         public SimpleName getName() {
321                 return this.optionalParameterName;
322         }
323         
324         /**
325          * Sets or clears the parameter name.
326          * 
327          * @param name the parameter name node, or <code>null</code> if 
328          *    there is none
329          * @exception IllegalArgumentException if:
330          * <ul>
331          * <li>the node belongs to a different AST</li>
332          * <li>the node already has a parent</li>
333          * </ul>
334          */ 
335         public void setName(SimpleName name) {
336                 ASTNode oldChild = this.optionalParameterName;
337                 preReplaceChild(oldChild, name, NAME_PROPERTY);
338                 this.optionalParameterName = name;
339                 postReplaceChild(oldChild, name, NAME_PROPERTY);
340         }
341
342         /* (omit javadoc for this method)
343          * Method declared on ASTNode.
344          */
345         int memSize() {
346                 return BASE_NODE_SIZE + 2 * 5;
347         }
348         
349         /* (omit javadoc for this method)
350          * Method declared on ASTNode.
351          */
352         int treeSize() {
353                 return 
354                         memSize()
355                         + (this.type == null ? 0 : getType().treeSize())
356                         + (this.optionalParameterName == null ? 0 : getName().treeSize());
357         }
358 }