Initial upgrade to Platform/JDT 3.4.1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / MethodDeclaration.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
12 package net.sourceforge.phpdt.core.dom;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 /**
18  * Method declaration AST node type. A method declaration
19  * is the union of a method declaration and a constructor declaration.
20  * For JLS2:
21  * <pre>
22  * MethodDeclaration:
23  *    [ Javadoc ] { Modifier } ( Type | <b>void</b> ) Identifier <b>(</b>
24  *        [ FormalParameter 
25  *                   { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
26  *        [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
27  * ConstructorDeclaration:
28  *    [ Javadoc ] { Modifier } Identifier <b>(</b>
29  *                [ FormalParameter
30  *                       { <b>,</b> FormalParameter } ] <b>)</b>
31  *        [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
32  * </pre>
33  * For JLS3, type parameters and reified modifiers
34  * (and annotations) were added:
35  * <pre>
36  * MethodDeclaration:
37  *    [ Javadoc ] { ExtendedModifier }
38  *                [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
39  *        ( Type | <b>void</b> ) Identifier <b>(</b>
40  *        [ FormalParameter 
41  *                   { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
42  *        [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
43  * ConstructorDeclaration:
44  *    [ Javadoc ] { ExtendedModifier }
45  *                [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
46  *        Identifier <b>(</b>
47  *                [ FormalParameter
48  *                       { <b>,</b> FormalParameter } ] <b>)</b>
49  *        [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
50  * </pre>
51  * <p>
52  * When a Javadoc comment is present, the source
53  * range begins with the first character of the "/**" comment delimiter.
54  * When there is no Javadoc comment, the source range begins with the first
55  * character of the first modifier keyword (if modifiers), or the
56  * first character of the "&lt;" token (method, no modifiers, type parameters), 
57  * or the first character of the return type (method, no modifiers, no type
58  * parameters), or the first character of the identifier (constructor, 
59  * no modifiers). The source range extends through the last character of the
60  * ";" token (if no body), or the last character of the block (if body).
61  * </p>
62  *
63  * @since 2.0 
64  * @noinstantiate This class is not intended to be instantiated by clients.
65  */
66 public class MethodDeclaration extends BodyDeclaration {
67         
68         /**
69          * The "javadoc" structural property of this node type.
70          * @since 3.0
71          */
72         public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
73                 internalJavadocPropertyFactory(MethodDeclaration.class);
74
75         /**
76          * The "modifiers" structural property of this node type (JLS2 API only).
77          * @since 3.0
78          */
79         public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
80                 internalModifiersPropertyFactory(MethodDeclaration.class);
81         
82         /**
83          * The "modifiers" structural property of this node type (added in JLS3 API).
84          * @since 3.1
85          */
86         public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
87                 internalModifiers2PropertyFactory(MethodDeclaration.class);
88         
89         /**
90          * The "constructor" structural property of this node type.
91          * @since 3.0
92          */
93         public static final SimplePropertyDescriptor CONSTRUCTOR_PROPERTY = 
94                 new SimplePropertyDescriptor(MethodDeclaration.class, "constructor", boolean.class, MANDATORY); //$NON-NLS-1$
95         
96         /**
97          * The "name" structural property of this node type.
98          * @since 3.0
99          */
100         public static final ChildPropertyDescriptor NAME_PROPERTY = 
101                 new ChildPropertyDescriptor(MethodDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
102
103         /**
104          * The "returnType" structural property of this node type (JLS2 API only).
105          * @since 3.0
106          */
107         public static final ChildPropertyDescriptor RETURN_TYPE_PROPERTY = 
108                 new ChildPropertyDescriptor(MethodDeclaration.class, "returnType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
109
110         /**
111          * The "returnType2" structural property of this node type (added in JLS3 API).
112          * @since 3.1
113          */
114         public static final ChildPropertyDescriptor RETURN_TYPE2_PROPERTY = 
115                 new ChildPropertyDescriptor(MethodDeclaration.class, "returnType2", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
116
117         /**
118          * The "extraDimensions" structural property of this node type.
119          * @since 3.0
120          */
121         public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY = 
122                 new SimplePropertyDescriptor(MethodDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
123         
124         /**
125          * The "typeParameters" structural property of this node type (added in JLS3 API).
126          * @since 3.1
127          */
128         public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY = 
129                 new ChildListPropertyDescriptor(MethodDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
130         
131         /**
132          * The "parameters" structural property of this node type).
133          * @since 3.0
134          */
135         public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY = 
136                 new ChildListPropertyDescriptor(MethodDeclaration.class, "parameters", SingleVariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
137         
138         /**
139          * The "thrownExceptions" structural property of this node type).
140          * @since 3.0
141          */
142         public static final ChildListPropertyDescriptor THROWN_EXCEPTIONS_PROPERTY = 
143                 new ChildListPropertyDescriptor(MethodDeclaration.class, "thrownExceptions", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
144         
145         /**
146          * The "body" structural property of this node type.
147          * @since 3.0
148          */
149         public static final ChildPropertyDescriptor BODY_PROPERTY = 
150                 new ChildPropertyDescriptor(MethodDeclaration.class, "body", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
151
152         /**
153          * A list of property descriptors (element type: 
154          * {@link StructuralPropertyDescriptor}),
155          * or null if uninitialized.
156          * @since 3.0
157          */
158         private static final List PROPERTY_DESCRIPTORS_2_0;
159         
160         /**
161          * A list of property descriptors (element type: 
162          * {@link StructuralPropertyDescriptor}),
163          * or null if uninitialized.
164          * @since 3.1
165          */
166         private static final List PROPERTY_DESCRIPTORS_3_0;
167         
168         static {
169                 List propertyList = new ArrayList(10);
170                 createPropertyList(MethodDeclaration.class, propertyList);
171                 addProperty(JAVADOC_PROPERTY, propertyList);
172                 addProperty(MODIFIERS_PROPERTY, propertyList);
173                 addProperty(CONSTRUCTOR_PROPERTY, propertyList);
174                 addProperty(RETURN_TYPE_PROPERTY, propertyList);
175                 addProperty(NAME_PROPERTY, propertyList);
176                 addProperty(PARAMETERS_PROPERTY, propertyList);
177                 addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
178                 addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
179                 addProperty(BODY_PROPERTY, propertyList);
180                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
181                 
182                 propertyList = new ArrayList(11);
183                 createPropertyList(MethodDeclaration.class, propertyList);
184                 addProperty(JAVADOC_PROPERTY, propertyList);
185                 addProperty(MODIFIERS2_PROPERTY, propertyList);
186                 addProperty(CONSTRUCTOR_PROPERTY, propertyList);
187                 addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
188                 addProperty(RETURN_TYPE2_PROPERTY, propertyList);
189                 addProperty(NAME_PROPERTY, propertyList);
190                 addProperty(PARAMETERS_PROPERTY, propertyList);
191                 addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
192                 addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
193                 addProperty(BODY_PROPERTY, propertyList);
194                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
195         }
196
197         /**
198          * Returns a list of structural property descriptors for this node type.
199          * Clients must not modify the result.
200          * 
201          * @param apiLevel the API level; one of the AST.JLS* constants
202          * @return a list of property descriptors (element type: 
203          * {@link StructuralPropertyDescriptor})
204          * @since 3.0
205          */
206         public static List propertyDescriptors(int apiLevel) {
207                 if (apiLevel == AST.JLS2_INTERNAL) {
208                         return PROPERTY_DESCRIPTORS_2_0;
209                 } else {
210                         return PROPERTY_DESCRIPTORS_3_0;
211                 }
212         }
213                         
214         /**
215          * <code>true</code> for a constructor, <code>false</code> for a method.
216          * Defaults to method.
217          */
218         private boolean isConstructor = false;
219         
220         /**
221          * The method name; lazily initialized; defaults to an unspecified,
222          * legal Java identifier.
223          */
224         private SimpleName methodName = null;
225
226         /**
227          * The parameter declarations 
228          * (element type: <code>SingleVariableDeclaration</code>).
229          * Defaults to an empty list.
230          */
231         private ASTNode.NodeList parameters =
232                 new ASTNode.NodeList(PARAMETERS_PROPERTY);
233         
234         /**
235          * The return type.
236          * JLS2 behevior: lazily initialized; defaults to void.
237          * JLS3 behavior; lazily initialized; defaults to void; null allowed.
238          * Note that this field is ignored for constructor declarations.
239          */
240         private Type returnType = null;
241         
242         /**
243          * Indicated whether the return type has been initialized.
244          * @since 3.1
245          */
246         private boolean returnType2Initialized = false;
247         
248         /**
249          * The type paramters (element type: <code>TypeParameter</code>). 
250          * Null in JLS2. Added in JLS3; defaults to an empty list
251          * (see constructor).
252          * @since 3.1
253          */
254         private ASTNode.NodeList typeParameters = null;
255
256         /**
257          * The number of array dimensions that appear after the parameters, rather
258          * than after the return type itself; defaults to 0.
259          * 
260          * @since 2.1
261          */
262         private int extraArrayDimensions = 0;
263
264         /**
265          * The list of thrown exception names (element type: <code>Name</code>).
266          * Defaults to an empty list.
267          */
268         private ASTNode.NodeList thrownExceptions =
269                 new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY);
270
271         /**
272          * The method body, or <code>null</code> if none.
273          * Defaults to none.
274          */
275         private Block optionalBody = null;
276         
277         /**
278          * Creates a new AST node for a method declaration owned 
279          * by the given AST. By default, the declaration is for a method of an
280          * unspecified, but legal, name; no modifiers; no javadoc; no type 
281          * parameters; void return type; no parameters; no array dimensions after 
282          * the parameters; no thrown exceptions; and no body (as opposed to an
283          * empty body).
284          * <p>
285          * N.B. This constructor is package-private; all subclasses must be 
286          * declared in the same package; clients are unable to declare 
287          * additional subclasses.
288          * </p>
289          * 
290          * @param ast the AST that is to own this node
291          */
292         MethodDeclaration(AST ast) {
293                 super(ast);
294                 if (ast.apiLevel >= AST.JLS3) {
295                         this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
296                 }
297         }
298
299         /* (omit javadoc for this method)
300          * Method declared on ASTNode.
301          * @since 3.0
302          */
303         final List internalStructuralPropertiesForType(int apiLevel) {
304                 return propertyDescriptors(apiLevel);
305         }
306         
307         /* (omit javadoc for this method)
308          * Method declared on ASTNode.
309          */
310         final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
311                 if (property == MODIFIERS_PROPERTY) {
312                         if (get) {
313                                 return getModifiers();
314                         } else {
315                                 internalSetModifiers(value);
316                                 return 0;
317                         }
318                 }
319                 if (property == EXTRA_DIMENSIONS_PROPERTY) {
320                         if (get) {
321                                 return getExtraDimensions();
322                         } else {
323                                 setExtraDimensions(value);
324                                 return 0;
325                         }
326                 }
327                 // allow default implementation to flag the error
328                 return super.internalGetSetIntProperty(property, get, value);
329         }
330
331         /* (omit javadoc for this method)
332          * Method declared on ASTNode.
333          */
334         final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
335                 if (property == CONSTRUCTOR_PROPERTY) {
336                         if (get) {
337                                 return isConstructor();
338                         } else {
339                                 setConstructor(value);
340                                 return false;
341                         }
342                 }
343                 // allow default implementation to flag the error
344                 return super.internalGetSetBooleanProperty(property, get, value);
345         }
346         
347         /* (omit javadoc for this method)
348          * Method declared on ASTNode.
349          */
350         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
351                 if (property == JAVADOC_PROPERTY) {
352                         if (get) {
353                                 return getJavadoc();
354                         } else {
355                                 setJavadoc((Javadoc) child);
356                                 return null;
357                         }
358                 }
359                 if (property == NAME_PROPERTY) {
360                         if (get) {
361                                 return getName();
362                         } else {
363                                 setName((SimpleName) child);
364                                 return null;
365                         }
366                 }
367                 if (property == RETURN_TYPE_PROPERTY) {
368                         if (get) {
369                                 return getReturnType();
370                         } else {
371                                 setReturnType((Type) child);
372                                 return null;
373                         }
374                 }
375                 if (property == RETURN_TYPE2_PROPERTY) {
376                         if (get) {
377                                 return getReturnType2();
378                         } else {
379                                 setReturnType2((Type) child);
380                                 return null;
381                         }
382                 }
383                 if (property == BODY_PROPERTY) {
384                         if (get) {
385                                 return getBody();
386                         } else {
387                                 setBody((Block) child);
388                                 return null;
389                         }
390                 }
391                 // allow default implementation to flag the error
392                 return super.internalGetSetChildProperty(property, get, child);
393         }
394         
395         /* (omit javadoc for this method)
396          * Method declared on ASTNode.
397          */
398         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
399                 if (property == MODIFIERS2_PROPERTY) {
400                         return modifiers();
401                 }
402                 if (property == TYPE_PARAMETERS_PROPERTY) {
403                         return typeParameters();
404                 }
405                 if (property == PARAMETERS_PROPERTY) {
406                         return parameters();
407                 }
408                 if (property == THROWN_EXCEPTIONS_PROPERTY) {
409                         return thrownExceptions();
410                 }
411                 // allow default implementation to flag the error
412                 return super.internalGetChildListProperty(property);
413         }
414         
415         /* (omit javadoc for this method)
416          * Method declared on BodyDeclaration.
417          */
418         final ChildPropertyDescriptor internalJavadocProperty() {
419                 return JAVADOC_PROPERTY;
420         }
421
422         /* (omit javadoc for this method)
423          * Method declared on BodyDeclaration.
424          */
425         final ChildListPropertyDescriptor internalModifiers2Property() {
426                 return MODIFIERS2_PROPERTY;
427         }
428
429         /* (omit javadoc for this method)
430          * Method declared on BodyDeclaration.
431          */
432         final SimplePropertyDescriptor internalModifiersProperty() {
433                 return MODIFIERS_PROPERTY;
434         }
435
436         /* (omit javadoc for this method)
437          * Method declared on ASTNode.
438          */
439         final int getNodeType0() {
440                 return METHOD_DECLARATION;
441         }
442
443         /* (omit javadoc for this method)
444          * Method declared on ASTNode.
445          */
446         ASTNode clone0(AST target) {
447                 MethodDeclaration result = new MethodDeclaration(target);
448                 result.setSourceRange(this.getStartPosition(), this.getLength());
449                 result.setJavadoc(
450                         (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
451                 if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
452                         result.internalSetModifiers(getModifiers());
453                         result.setReturnType(
454                                         (Type) ASTNode.copySubtree(target, getReturnType()));
455                 }
456                 if (this.ast.apiLevel >= AST.JLS3) {
457                         result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
458                         result.typeParameters().addAll(
459                                         ASTNode.copySubtrees(target, typeParameters()));
460                         result.setReturnType2(
461                                         (Type) ASTNode.copySubtree(target, getReturnType2()));
462                 }
463                 result.setConstructor(isConstructor());
464                 result.setExtraDimensions(getExtraDimensions());
465                 result.setName((SimpleName) getName().clone(target));
466                 result.parameters().addAll(
467                         ASTNode.copySubtrees(target, parameters()));
468                 result.thrownExceptions().addAll(
469                         ASTNode.copySubtrees(target, thrownExceptions()));
470                 result.setBody(
471                         (Block) ASTNode.copySubtree(target, getBody()));
472                 return result;
473         }
474
475         /* (omit javadoc for this method)
476          * Method declared on ASTNode.
477          */
478         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
479                 // dispatch to correct overloaded match method
480                 return matcher.match(this, other);
481         }
482         
483         /* (omit javadoc for this method)
484          * Method declared on ASTNode.
485          */
486         void accept0(ASTVisitor visitor) {
487                 boolean visitChildren = visitor.visit(this);
488                 if (visitChildren) {
489                         // visit children in normal left to right reading order
490                         acceptChild(visitor, getJavadoc());
491                         if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
492                                 acceptChild(visitor, getReturnType());
493                         } else {
494                                 acceptChildren(visitor, this.modifiers);
495                                 acceptChildren(visitor, this.typeParameters);
496                                 acceptChild(visitor, getReturnType2());
497                         }
498                         // n.b. visit return type even for constructors
499                         acceptChild(visitor, getName());
500                         acceptChildren(visitor, this.parameters);
501                         acceptChildren(visitor, this.thrownExceptions);
502                         acceptChild(visitor, getBody());
503                 }
504                 visitor.endVisit(this);
505         }
506         
507         /**
508          * Returns whether this declaration declares a constructor or a method.
509          * 
510          * @return <code>true</code> if this is a constructor declaration,
511          *    and <code>false</code> if this is a method declaration
512          */ 
513         public boolean isConstructor() {
514                 return this.isConstructor;
515         }
516         
517         /**
518          * Sets whether this declaration declares a constructor or a method.
519          * 
520          * @param isConstructor <code>true</code> for a constructor declaration,
521          *    and <code>false</code> for a method declaration
522          */ 
523         public void setConstructor(boolean isConstructor) {
524                 preValueChange(CONSTRUCTOR_PROPERTY);
525                 this.isConstructor = isConstructor;
526                 postValueChange(CONSTRUCTOR_PROPERTY);
527         }
528
529         /**
530          * Returns the live ordered list of type parameters of this method
531          * declaration (added in JLS3 API). This list is non-empty for parameterized methods.
532          * 
533          * @return the live list of type parameters
534          *    (element type: <code>TypeParameter</code>)
535          * @exception UnsupportedOperationException if this operation is used in
536          * a JLS2 AST
537          * @since 3.1
538          */ 
539         public List typeParameters() {
540                 // more efficient than just calling unsupportedIn2() to check
541                 if (this.typeParameters == null) {
542                         unsupportedIn2();
543                 }
544                 return this.typeParameters;
545         }
546         
547         /**
548          * Returns the name of the method declared in this method declaration.
549          * For a constructor declaration, this should be the same as the name 
550          * of the class.
551          * 
552          * @return the method name node
553          */ 
554         public SimpleName getName() {
555                 if (this.methodName == null) {
556                         // lazy init must be thread-safe for readers
557                         synchronized (this) {
558                                 if (this.methodName == null) {
559                                         preLazyInit();
560                                         this.methodName = new SimpleName(this.ast);
561                                         postLazyInit(this.methodName, NAME_PROPERTY);
562                                 }
563                         }
564                 }
565                 return this.methodName;
566         }
567         
568         /**
569          * Sets the name of the method declared in this method declaration to the
570          * given name. For a constructor declaration, this should be the same as 
571          * the name of the class.
572          * 
573          * @param methodName the new method name
574          * @exception IllegalArgumentException if:
575          * <ul>
576          * <li>the node belongs to a different AST</li>
577          * <li>the node already has a parent</li>
578          * </ul>
579          */ 
580         public void setName(SimpleName methodName) {
581                 if (methodName == null) {
582                         throw new IllegalArgumentException();
583                 }
584                 ASTNode oldChild = this.methodName;
585                 preReplaceChild(oldChild, methodName, NAME_PROPERTY);
586                 this.methodName = methodName;
587                 postReplaceChild(oldChild, methodName, NAME_PROPERTY);
588         }
589
590         /**
591          * Returns the live ordered list of method parameter declarations for this
592          * method declaration.
593          * 
594          * @return the live list of method parameter declarations
595          *    (element type: <code>SingleVariableDeclaration</code>)
596          */ 
597         public List parameters() {
598                 return this.parameters;
599         }
600         
601         /**
602          * Returns whether this method declaration declares a
603          * variable arity method (added in JLS3 API). The convenience method checks
604          * whether the last parameter is so marked.
605          * 
606          * @return <code>true</code> if this is a variable arity method declaration,
607          *    and <code>false</code> otherwise
608          * @exception UnsupportedOperationException if this operation is used in
609          * a JLS2 AST
610          * @see SingleVariableDeclaration#isVarargs()
611          * @since 3.1
612          */ 
613         public boolean isVarargs() {
614                 // more efficient than just calling unsupportedIn2() to check
615                 if (this.modifiers == null) {
616                         unsupportedIn2();
617                 }
618                 if (parameters().isEmpty()) {
619                         return false;
620                 } else {
621                         SingleVariableDeclaration v = (SingleVariableDeclaration) parameters().get(parameters().size() - 1);
622                         return v.isVarargs();
623                 }
624         }
625         
626         /**
627          * Returns the live ordered list of thrown exception names in this method 
628          * declaration.
629          * 
630          * @return the live list of exception names
631          *    (element type: <code>Name</code>)
632          */ 
633         public List thrownExceptions() {
634                 return this.thrownExceptions;
635         }
636         
637         /**
638          * Returns the return type of the method declared in this method 
639          * declaration, exclusive of any extra array dimensions (JLS2 API only). 
640          * This is one of the few places where the void type is meaningful.
641          * <p>
642          * Note that this child is not relevant for constructor declarations
643          * (although, it does still figure in subtree equality comparisons
644          * and visits), and is devoid of the binding information ordinarily
645          * available.
646          * </p>
647          * 
648          * @return the return type, possibly the void primitive type
649          * @exception UnsupportedOperationException if this operation is used in
650          * an AST later than JLS2
651          * @deprecated In the JLS3 API, this method is replaced by {@link #getReturnType2()},
652          * which may return <code>null</code>.
653          */ 
654         public Type getReturnType() {
655                 return internalGetReturnType();
656         }
657         
658         /**
659          * Internal synonym for deprecated method. Used to avoid
660          * deprecation warnings.
661          * @since 3.1
662          */
663         /*package*/ final Type internalGetReturnType() {
664                 supportedOnlyIn2();
665                 if (this.returnType == null) {
666                         // lazy init must be thread-safe for readers
667                         synchronized (this) {
668                                 if (this.returnType == null) {
669                                         preLazyInit();
670                                         this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
671                                         postLazyInit(this.returnType, RETURN_TYPE_PROPERTY);
672                                 }
673                         }
674                 }
675                 return this.returnType;
676         }
677
678         /**
679          * Sets the return type of the method declared in this method declaration
680          * to the given type, exclusive of any extra array dimensions (JLS2 API only). This is one
681          * of the few places where the void type is meaningful.
682          * <p>
683          * Note that this child is not relevant for constructor declarations
684          * (although it does still figure in subtree equality comparisons and visits).
685          * </p>
686          * 
687          * @param type the new return type, possibly the void primitive type
688          * @exception IllegalArgumentException if:
689          * <ul>
690          * <li>the node belongs to a different AST</li>
691          * <li>the node already has a parent</li>
692          * </ul>
693          * @exception UnsupportedOperationException if this operation is used in
694          * an AST later than JLS2
695          * @deprecated In the JLS3 API, this method is replaced by 
696          * {@link #setReturnType2(Type)}, which accepts <code>null</code>.
697          */ 
698         public void setReturnType(Type type) {
699                 internalSetReturnType(type);
700         }
701         
702         /**
703          * Internal synonym for deprecated method. Used to avoid
704          * deprecation warnings.
705          * @since 3.1
706          */
707         /*package*/ void internalSetReturnType(Type type) {
708             supportedOnlyIn2();
709                 if (type == null) {
710                         throw new IllegalArgumentException();
711                 }
712                 ASTNode oldChild = this.returnType;
713                 preReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
714                 this.returnType = type;
715                 postReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
716         }
717
718         /**
719          * Returns the return type of the method declared in this method 
720          * declaration, exclusive of any extra array dimensions (added in JLS3 API). 
721          * This is one of the few places where the void type is meaningful.
722          * <p>
723          * Note that this child is not relevant for constructor declarations
724          * (although, if present, it does still figure in subtree equality comparisons
725          * and visits), and is devoid of the binding information ordinarily
726          * available. In the JLS2 API, the return type is mandatory. 
727          * In the JLS3 API, the return type is optional.
728          * </p>
729          * 
730          * @return the return type, possibly the void primitive type,
731          * or <code>null</code> if none
732          * @exception UnsupportedOperationException if this operation is used in
733          * a JLS2 AST
734          * @since 3.1
735          */ 
736         public Type getReturnType2() {
737             unsupportedIn2();
738                 if (this.returnType == null && !this.returnType2Initialized) {
739                         // lazy init must be thread-safe for readers
740                         synchronized (this) {
741                                 if (this.returnType == null && !this.returnType2Initialized) {
742                                         preLazyInit();
743                                         this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
744                                         this.returnType2Initialized = true;
745                                         postLazyInit(this.returnType, RETURN_TYPE2_PROPERTY);
746                                 }
747                         }
748                 }
749                 return this.returnType;
750         }
751
752         /**
753          * Sets the return type of the method declared in this method declaration
754          * to the given type, exclusive of any extra array dimensions (added in JLS3 API).
755          * This is one of the few places where the void type is meaningful.
756          * <p>
757          * Note that this child is not relevant for constructor declarations
758          * (although it does still figure in subtree equality comparisons and visits).
759          * In the JLS2 API, the return type is mandatory. 
760          * In the JLS3 API, the return type is optional.
761          * </p>
762          * 
763          * @param type the new return type, possibly the void primitive type,
764          * or <code>null</code> if none
765          * @exception UnsupportedOperationException if this operation is used in
766          * a JLS2 AST
767          * @exception IllegalArgumentException if:
768          * <ul>
769          * <li>the node belongs to a different AST</li>
770          * <li>the node already has a parent</li>
771          * </ul>
772          * @since 3.1
773          */ 
774         public void setReturnType2(Type type) {
775             unsupportedIn2();
776                 this.returnType2Initialized = true;
777                 ASTNode oldChild = this.returnType;
778                 preReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
779                 this.returnType = type;
780                 postReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
781         }
782
783         /**
784          * Returns the number of extra array dimensions over and above the 
785          * explicitly-specified return type.
786          * <p>
787          * For example, <code>int foo()[][]</code> has a return type of 
788          * <code>int</code> and two extra array dimensions; 
789          * <code>int[][] foo()</code> has a return type of <code>int[][]</code>
790          * and zero extra array dimensions. The two constructs have different
791          * ASTs, even though there are really syntactic variants of the same
792          * method declaration.
793          * </p>
794          * 
795          * @return the number of extra array dimensions
796          * @since 2.1
797          */ 
798         public int getExtraDimensions() {
799                 return this.extraArrayDimensions;
800         }
801
802         /**
803          * Sets the number of extra array dimensions over and above the 
804          * explicitly-specified return type.
805          * <p>
806          * For example, <code>int foo()[][]</code> is rendered as a return
807          * type of <code>int</code> with two extra array dimensions; 
808          * <code>int[][] foo()</code> is rendered as a return type of 
809          * <code>int[][]</code> with zero extra array dimensions. The two
810          * constructs have different ASTs, even though there are really syntactic
811          * variants of the same method declaration.
812          * </p>
813          * 
814          * @param dimensions the number of array dimensions
815          * @exception IllegalArgumentException if the number of dimensions is
816          *    negative
817          * @since 2.1
818          */ 
819         public void setExtraDimensions(int dimensions) {
820                 if (dimensions < 0) {
821                         throw new IllegalArgumentException();
822                 }
823                 preValueChange(EXTRA_DIMENSIONS_PROPERTY);
824                 this.extraArrayDimensions = dimensions;
825                 postValueChange(EXTRA_DIMENSIONS_PROPERTY);
826         }
827
828         /**
829          * Returns the body of this method declaration, or <code>null</code> if 
830          * this method has <b>no</b> body.
831          * <p>
832          * Note that there is a subtle difference between having no body and having
833          * an empty body ("{}").
834          * </p>
835          * 
836          * @return the method body, or <code>null</code> if this method has no
837          *    body
838          */ 
839         public Block getBody() {
840                 return this.optionalBody;
841         }
842
843         /**
844          * Sets or clears the body of this method declaration.
845          * <p>
846          * Note that there is a subtle difference between having no body 
847          * (as in <code>"void foo();"</code>) and having an empty body (as in
848          * "void foo() {}"). Abstract methods, and methods declared in interfaces,
849          * have no body. Non-abstract methods, and all constructors, have a body.
850          * </p>
851          * 
852          * @param body the block node, or <code>null</code> if 
853          *    there is none
854          * @exception IllegalArgumentException if:
855          * <ul>
856          * <li>the node belongs to a different AST</li>
857          * <li>the node already has a parent</li>
858          * <li>a cycle in would be created</li>
859          * </ul>
860          */ 
861         public void setBody(Block body) {
862                 // a MethodDeclaration may occur in a Block - must check cycles
863                 ASTNode oldChild = this.optionalBody;
864                 preReplaceChild(oldChild, body, BODY_PROPERTY);
865                 this.optionalBody = body;
866                 postReplaceChild(oldChild, body, BODY_PROPERTY);
867         }
868
869         /**
870          * Resolves and returns the binding for the method or constructor declared
871          * in this method or constructor declaration.
872          * <p>
873          * Note that bindings are generally unavailable unless requested when the
874          * AST is being built.
875          * </p>
876          * 
877          * @return the binding, or <code>null</code> if the binding cannot be 
878          *    resolved
879          */     
880         public IMethodBinding resolveBinding() {
881                 return this.ast.getBindingResolver().resolveMethod(this);
882         }
883
884         /* (omit javadoc for this method)
885          * Method declared on ASTNode.
886          */
887         int memSize() {
888                 return super.memSize() + 9 * 4;
889         }
890         
891         /* (omit javadoc for this method)
892          * Method declared on ASTNode.
893          */
894         int treeSize() {
895                 return
896                         memSize()
897                         + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
898                         + (this.modifiers == null ? 0 : this.modifiers.listSize())
899                         + (this.typeParameters == null ? 0 : this.typeParameters.listSize())
900                         + (this.methodName == null ? 0 : getName().treeSize())
901                         + (this.returnType == null ? 0 : this.returnType.treeSize())
902                         + this.parameters.listSize()
903                         + this.thrownExceptions.listSize()
904                         + (this.optionalBody == null ? 0 : getBody().treeSize());
905         }
906 }
907