1 /*******************************************************************************
2  * Copyright (c) 2000, 2020 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 
15 package org.eclipse.jdt.core.dom;
16 
17 import java.util.ArrayList;
18 import java.util.List;
19 
20 import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil;
21 
22 /**
23  * Method declaration AST node type. A method declaration
24  * is the union of a method declaration and a constructor declaration.
25  *
26  * <pre>
27  * MethodDeclaration:
28  *    [ Javadoc ] { ExtendedModifier } [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ] ( Type | <b>void</b> )
29  *        Identifier <b>(</b>
30  *            [ ReceiverParameter <b>,</b> ] [ FormalParameter { <b>,</b> FormalParameter } ]
31  *        <b>)</b> { Dimension }
32  *        [ <b>throws</b> Type { <b>,</b> Type } ]
33  *        ( Block | <b>;</b> )
34  * ConstructorDeclaration:
35  *    [ Javadoc ] { ExtendedModifier } [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
36  *        Identifier <b>(</b>
37  *            [ ReceiverParameter <b>,</b> ] [ FormalParameter { <b>,</b> FormalParameter } ]
38  *        <b>)</b> { Dimension }
39  *        [ <b>throws</b> Type { <b>,</b> Type } ]
40  *        ( Block | <b>;</b> )
41  * CompactConstructorDeclaration:
42  *    [ Javadoc ] ExtendedModifier { ExtendedModifier}
43  *        Identifier
44  *        ( Block | <b>;</b> )
45  * </pre>
46  * <p>
47  * The ReceiverParameter is represented as: <code>Type [ SimpleName <b>.</b> ] <b>this</b></code><br>
48  * The FormalParameter is represented by a {@link SingleVariableDeclaration}.
49  * </p>
50  * <p>
51  * When a Javadoc comment is present, the source
52  * range begins with the first character of the "/**" comment delimiter.
53  * When there is no Javadoc comment, the source range begins with the first
54  * character of the first modifier keyword (if modifiers), or the
55  * first character of the "&lt;" token (method, no modifiers, type parameters),
56  * or the first character of the return type (method, no modifiers, no type
57  * parameters), or the first character of the identifier (constructor,
58  * no modifiers). The source range extends through the last character of the
59  * ";" token (if no body), or the last character of the block (if body).
60  * The compact constructor must be declared public. (jls-8.10.5)
61  * </p>
62  *
63  * @since 2.0
64  * @noinstantiate This class is not intended to be instantiated by clients.
65  */
66 @SuppressWarnings({"rawtypes", "unchecked"})
67 public class MethodDeclaration extends BodyDeclaration {
68 
69 	/**
70 	 * The "javadoc" structural property of this node type (child type: {@link Javadoc}).
71 	 * @since 3.0
72 	 */
73 	public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
74 		internalJavadocPropertyFactory(MethodDeclaration.class);
75 
76 	/**
77 	 * The "modifiers" structural property of this node type (type: {@link Integer}) (JLS2 API only).
78 	 * @since 3.0
79 	 * @deprecated In the JLS3 API, this property is replaced by {@link #MODIFIERS2_PROPERTY}.
80 	 */
81 	public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
82 		internalModifiersPropertyFactory(MethodDeclaration.class);
83 
84 	/**
85 	 * The "modifiers" structural property of this node type (element type: {@link IExtendedModifier}) (added in JLS3 API).
86 	 * @since 3.1
87 	 */
88 	public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
89 		internalModifiers2PropertyFactory(MethodDeclaration.class);
90 
91 	/**
92 	 * The "constructor" structural property of this node type (type: {@link Boolean}).
93 	 * @since 3.0
94 	 */
95 	public static final SimplePropertyDescriptor CONSTRUCTOR_PROPERTY =
96 		new SimplePropertyDescriptor(MethodDeclaration.class, "constructor", boolean.class, MANDATORY); //$NON-NLS-1$
97 
98 	/**
99 	 * The "compact constructor" structural property of record node type (type: {@link Boolean}).
100 	 * @since 3.22
101 	 */
102 	public static final SimplePropertyDescriptor COMPACT_CONSTRUCTOR_PROPERTY =
103 		new SimplePropertyDescriptor(MethodDeclaration.class, "compactConstructor", boolean.class, OPTIONAL); //$NON-NLS-1$
104 
105 	/**
106 	 * The "name" structural property of this node type (child type: {@link SimpleName}).
107 	 * @since 3.0
108 	 */
109 	public static final ChildPropertyDescriptor NAME_PROPERTY =
110 		new ChildPropertyDescriptor(MethodDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
111 
112 	/**
113 	 * The "returnType" structural property of this node type (child type: {@link Type}) (JLS2 API only).
114 	 * @since 3.0
115 	 * @deprecated In the JLS3 API, this property is replaced by {@link #RETURN_TYPE2_PROPERTY}.
116 	 */
117 	public static final ChildPropertyDescriptor RETURN_TYPE_PROPERTY =
118 		new ChildPropertyDescriptor(MethodDeclaration.class, "returnType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
119 
120 	/**
121 	 * The "returnType2" structural property of this node type (child type: {@link Type}) (added in JLS3 API).
122 	 * @since 3.1
123 	 */
124 	public static final ChildPropertyDescriptor RETURN_TYPE2_PROPERTY =
125 		new ChildPropertyDescriptor(MethodDeclaration.class, "returnType2", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
126 
127 	/**
128 	 * The "extraDimensions" structural property of this node type (type: {@link Integer}) (below JLS8 only).
129 	 *
130 	 * @since 3.0
131 	 * @deprecated In JLS8 and later, use {@link MethodDeclaration#EXTRA_DIMENSIONS2_PROPERTY} instead.
132 	 */
133 	public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
134 		new SimplePropertyDescriptor(MethodDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
135 
136 	/**
137 	 * The "extraDimensions2" structural property of this node type (element type: {@link Dimension}) (added in JLS8 API).
138 	 * @since 3.10
139 	 */
140 	public static final ChildListPropertyDescriptor EXTRA_DIMENSIONS2_PROPERTY =
141 			new ChildListPropertyDescriptor(MethodDeclaration.class, "extraDimensions2", Dimension.class, NO_CYCLE_RISK); //$NON-NLS-1$
142 
143 	/**
144 	 * The "typeParameters" structural property of this node type (element type: {@link TypeParameter}) (added in JLS3 API).
145 	 * @since 3.1
146 	 */
147 	public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY =
148 		new ChildListPropertyDescriptor(MethodDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
149 
150 	/**
151 	 * The "parameters" structural property of this node type (element type: {@link SingleVariableDeclaration}).
152 	 * @since 3.0
153 	 */
154 	public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
155 		new ChildListPropertyDescriptor(MethodDeclaration.class, "parameters", SingleVariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
156 
157 	/**
158 	 * The "receiverType" structural property of this node type (child type: {@link Type}) (added in JLS8 API).
159 	 * @since 3.10
160 	 */
161 	public static final ChildPropertyDescriptor RECEIVER_TYPE_PROPERTY =
162 			new ChildPropertyDescriptor(MethodDeclaration.class, "receiverType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
163 
164 	/**
165 	 * The "receiverQualifier" structural property of this node type (child type: {@link SimpleName}) (added in JLS8 API).
166 	 * @since 3.10
167 	 */
168 	public static final ChildPropertyDescriptor RECEIVER_QUALIFIER_PROPERTY =
169 			new ChildPropertyDescriptor(MethodDeclaration.class, "receiverQualifier", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
170 
171 	/**
172 	 * The "thrownExceptions" structural property of this node type (element type: {@link Name}) (before JLS8 only).
173 	 * @deprecated In JLS8 and later, use {@link MethodDeclaration#THROWN_EXCEPTION_TYPES_PROPERTY} instead.
174 	 * @since 3.0
175 	 */
176 	public static final ChildListPropertyDescriptor THROWN_EXCEPTIONS_PROPERTY =
177 		new ChildListPropertyDescriptor(MethodDeclaration.class, "thrownExceptions", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
178 
179 	/**
180 	 * The "thrownExceptionTypes" structural property of this node type (element type: {@link Type}) (added in JLS8 API).
181 	 * @since 3.10
182 	 */
183 	public static final ChildListPropertyDescriptor THROWN_EXCEPTION_TYPES_PROPERTY =
184 		new ChildListPropertyDescriptor(MethodDeclaration.class, "thrownExceptionTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
185 
186 	/**
187 	 * The "body" structural property of this node type (child type: {@link Block}).
188 	 * @since 3.0
189 	 */
190 	public static final ChildPropertyDescriptor BODY_PROPERTY =
191 		new ChildPropertyDescriptor(MethodDeclaration.class, "body", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
192 
193 	/**
194 	 * A list of property descriptors (element type:
195 	 * {@link StructuralPropertyDescriptor}),
196 	 * or null if uninitialized.
197 	 * @since 3.0
198 	 */
199 	private static final List PROPERTY_DESCRIPTORS_2_0;
200 
201 	/**
202 	 * A list of property descriptors (element type:
203 	 * {@link StructuralPropertyDescriptor}),
204 	 * or null if uninitialized.
205 	 * @since 3.1
206 	 */
207 	private static final List PROPERTY_DESCRIPTORS_3_0;
208 
209 	/**
210 	 * A list of property descriptors (element type:
211 	 * {@link StructuralPropertyDescriptor}),
212 	 * or null if uninitialized.
213 	 * @since 3.10
214 	 */
215 	private static final List PROPERTY_DESCRIPTORS_8_0;
216 
217 	/**
218 	 * A list of property descriptors (element type:
219 	 * {@link StructuralPropertyDescriptor}),
220 	 * or null if uninitialized.
221 	 * @since 3.22
222 	 */
223 	private static final List PROPERTY_DESCRIPTORS_9_0;
224 
225 	static {
226 		List propertyList = new ArrayList(10);
createPropertyList(MethodDeclaration.class, propertyList)227 		createPropertyList(MethodDeclaration.class, propertyList);
addProperty(JAVADOC_PROPERTY, propertyList)228 		addProperty(JAVADOC_PROPERTY, propertyList);
addProperty(MODIFIERS_PROPERTY, propertyList)229 		addProperty(MODIFIERS_PROPERTY, propertyList);
addProperty(CONSTRUCTOR_PROPERTY, propertyList)230 		addProperty(CONSTRUCTOR_PROPERTY, propertyList);
addProperty(RETURN_TYPE_PROPERTY, propertyList)231 		addProperty(RETURN_TYPE_PROPERTY, propertyList);
addProperty(NAME_PROPERTY, propertyList)232 		addProperty(NAME_PROPERTY, propertyList);
addProperty(PARAMETERS_PROPERTY, propertyList)233 		addProperty(PARAMETERS_PROPERTY, propertyList);
addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList)234 		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList)235 		addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
addProperty(BODY_PROPERTY, propertyList)236 		addProperty(BODY_PROPERTY, propertyList);
237 		PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
238 
239 		propertyList = new ArrayList(11);
createPropertyList(MethodDeclaration.class, propertyList)240 		createPropertyList(MethodDeclaration.class, propertyList);
addProperty(JAVADOC_PROPERTY, propertyList)241 		addProperty(JAVADOC_PROPERTY, propertyList);
addProperty(MODIFIERS2_PROPERTY, propertyList)242 		addProperty(MODIFIERS2_PROPERTY, propertyList);
addProperty(CONSTRUCTOR_PROPERTY, propertyList)243 		addProperty(CONSTRUCTOR_PROPERTY, propertyList);
addProperty(TYPE_PARAMETERS_PROPERTY, propertyList)244 		addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
addProperty(RETURN_TYPE2_PROPERTY, propertyList)245 		addProperty(RETURN_TYPE2_PROPERTY, propertyList);
addProperty(NAME_PROPERTY, propertyList)246 		addProperty(NAME_PROPERTY, propertyList);
addProperty(PARAMETERS_PROPERTY, propertyList)247 		addProperty(PARAMETERS_PROPERTY, propertyList);
addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList)248 		addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList)249 		addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
addProperty(BODY_PROPERTY, propertyList)250 		addProperty(BODY_PROPERTY, propertyList);
251 		PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
252 
253 		propertyList = new ArrayList(13);
createPropertyList(MethodDeclaration.class, propertyList)254 		createPropertyList(MethodDeclaration.class, propertyList);
addProperty(JAVADOC_PROPERTY, propertyList)255 		addProperty(JAVADOC_PROPERTY, propertyList);
addProperty(MODIFIERS2_PROPERTY, propertyList)256 		addProperty(MODIFIERS2_PROPERTY, propertyList);
addProperty(CONSTRUCTOR_PROPERTY, propertyList)257 		addProperty(CONSTRUCTOR_PROPERTY, propertyList);
addProperty(TYPE_PARAMETERS_PROPERTY, propertyList)258 		addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
addProperty(RETURN_TYPE2_PROPERTY, propertyList)259 		addProperty(RETURN_TYPE2_PROPERTY, propertyList);
addProperty(NAME_PROPERTY, propertyList)260 		addProperty(NAME_PROPERTY, propertyList);
addProperty(RECEIVER_TYPE_PROPERTY, propertyList)261 		addProperty(RECEIVER_TYPE_PROPERTY, propertyList);
addProperty(RECEIVER_QUALIFIER_PROPERTY, propertyList)262 		addProperty(RECEIVER_QUALIFIER_PROPERTY, propertyList);
addProperty(PARAMETERS_PROPERTY, propertyList)263 		addProperty(PARAMETERS_PROPERTY, propertyList);
addProperty(EXTRA_DIMENSIONS2_PROPERTY, propertyList)264 		addProperty(EXTRA_DIMENSIONS2_PROPERTY, propertyList);
addProperty(THROWN_EXCEPTION_TYPES_PROPERTY, propertyList)265 		addProperty(THROWN_EXCEPTION_TYPES_PROPERTY, propertyList);
addProperty(BODY_PROPERTY, propertyList)266 		addProperty(BODY_PROPERTY, propertyList);
267 		PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList);
268 
269 		propertyList = new ArrayList(14);
createPropertyList(MethodDeclaration.class, propertyList)270 		createPropertyList(MethodDeclaration.class, propertyList);
addProperty(JAVADOC_PROPERTY, propertyList)271 		addProperty(JAVADOC_PROPERTY, propertyList);
addProperty(MODIFIERS2_PROPERTY, propertyList)272 		addProperty(MODIFIERS2_PROPERTY, propertyList);
addProperty(CONSTRUCTOR_PROPERTY, propertyList)273 		addProperty(CONSTRUCTOR_PROPERTY, propertyList);
addProperty(TYPE_PARAMETERS_PROPERTY, propertyList)274 		addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
addProperty(RETURN_TYPE2_PROPERTY, propertyList)275 		addProperty(RETURN_TYPE2_PROPERTY, propertyList);
addProperty(NAME_PROPERTY, propertyList)276 		addProperty(NAME_PROPERTY, propertyList);
addProperty(RECEIVER_TYPE_PROPERTY, propertyList)277 		addProperty(RECEIVER_TYPE_PROPERTY, propertyList);
addProperty(RECEIVER_QUALIFIER_PROPERTY, propertyList)278 		addProperty(RECEIVER_QUALIFIER_PROPERTY, propertyList);
addProperty(PARAMETERS_PROPERTY, propertyList)279 		addProperty(PARAMETERS_PROPERTY, propertyList);
addProperty(EXTRA_DIMENSIONS2_PROPERTY, propertyList)280 		addProperty(EXTRA_DIMENSIONS2_PROPERTY, propertyList);
addProperty(THROWN_EXCEPTION_TYPES_PROPERTY, propertyList)281 		addProperty(THROWN_EXCEPTION_TYPES_PROPERTY, propertyList);
addProperty(BODY_PROPERTY, propertyList)282 		addProperty(BODY_PROPERTY, propertyList);
addProperty(COMPACT_CONSTRUCTOR_PROPERTY, propertyList)283 		addProperty(COMPACT_CONSTRUCTOR_PROPERTY, propertyList);
284 		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(propertyList);
285 	}
286 
287 	/**
288 	 * Returns a list of structural property descriptors for this node type.
289 	 * Clients must not modify the result.
290 	 *
291 	 * @param apiLevel the API level; one of the AST.JLS* constants
292 	 * @return a list of property descriptors (element type:
293 	 * {@link StructuralPropertyDescriptor})
294 	 * @since 3.0
295 	 */
propertyDescriptors(int apiLevel)296 	public static List propertyDescriptors(int apiLevel) {
297 		return propertyDescriptors(apiLevel, false);
298 	}
299 
300 	/**
301 	 * Returns a list of structural property descriptors for this node type.
302 	 * Clients must not modify the result.
303 	 *
304 	 * @param apiLevel the API level; one of the
305 	 * <code>AST.JLS*</code> constants
306 	 * @param previewEnabled the previewEnabled flag
307 	 * @return a list of property descriptors (element type:
308 	 * {@link StructuralPropertyDescriptor})
309 	 * @noreference This method is not intended to be referenced by clients.
310 	 * @since 3.22
311 	 */
propertyDescriptors(int apiLevel, boolean previewEnabled)312 	public static List propertyDescriptors(int apiLevel, boolean previewEnabled) {
313 		if (apiLevel == AST.JLS2_INTERNAL) {
314 			return PROPERTY_DESCRIPTORS_2_0;
315 		} else if (apiLevel < AST.JLS8_INTERNAL) {
316 			return PROPERTY_DESCRIPTORS_3_0;
317 		} else if (DOMASTUtil.isRecordDeclarationSupported(apiLevel, previewEnabled)) {
318 			return PROPERTY_DESCRIPTORS_9_0;
319 		} else {
320 			return PROPERTY_DESCRIPTORS_8_0;
321 		}
322 	}
323 
324 	/**
325 	 * <code>true</code> for a constructor, <code>false</code> for a method.
326 	 * Defaults to method.
327 	 */
328 	private boolean isConstructor = false;
329 
330 
331 	/**
332 	 * <code>true</code> for a compact constructor in a record, <code>false</code> for a method.
333 	 * Defaults to method.
334 	 */
335 	private boolean isCompactConstructor = false;
336 
337 	/**
338 	 * The method name; lazily initialized; defaults to an unspecified,
339 	 * legal Java identifier.
340 	 */
341 	private SimpleName methodName = null;
342 
343 	/**
344 	 * The explicit receiver type, or <code>null</code> if none.
345 	 * Defaults to none.
346 	 * @since 3.10
347 	 */
348 	private Type optionalReceiverType = null;
349 
350 	/**
351 	 * Qualifying name of the explicit </code>this</code> parameter, or <code>null</code> if none.
352 	 * Defaults to none.
353 	 * @since 3.10
354 	 */
355 	private SimpleName optionalReceiverQualifier = null;
356 
357 	/**
358 	 * The parameter declarations
359 	 * (element type: {@link SingleVariableDeclaration}).
360 	 * Defaults to an empty list.
361 	 */
362 	private ASTNode.NodeList parameters =
363 		new ASTNode.NodeList(PARAMETERS_PROPERTY);
364 
365 	/**
366 	 * The return type.
367 	 * JLS2 behavior: lazily initialized; defaults to void.
368 	 * JLS3 and later: lazily initialized; defaults to void; null allowed.
369 	 * Note that this field is ignored for constructor declarations.
370 	 */
371 	private Type returnType = null;
372 
373 	/**
374 	 * Indicated whether the return type has been initialized.
375 	 * @since 3.1
376 	 */
377 	private boolean returnType2Initialized = false;
378 
379 	/**
380 	 * The type paramters (element type: {@link TypeParameter}).
381 	 * Null in JLS2. Added in JLS3; defaults to an empty list
382 	 * (see constructor).
383 	 * @since 3.1
384 	 */
385 	private ASTNode.NodeList typeParameters = null;
386 
387 	/**
388 	 * The number of array dimensions that appear after the parameters, rather
389 	 * than after the return type itself; defaults to 0. Not used in JLS8 and later.
390 	 *
391 	 * @since 2.1
392 	 * @deprecated In JLS8 and later, use {@link #extraDimensions} instead.
393 	 */
394 	private int extraArrayDimensions = 0;
395 
396 	/**
397 	 * List of extra dimensions this node has with optional annotations
398 	 * (element type: {@link Dimension}).
399 	 * Null before JLS8. Added in JLS8; defaults to an empty list
400 	 * (see constructor).
401 	 *
402 	 * @since 3.10
403 	 */
404 	private ASTNode.NodeList extraDimensions = null;
405 
406 	/**
407 	 * The list of thrown exception names (element type: {@link Name}).
408 	 * Before JLS8: defaults to an empty list (see constructor).
409 	 * JLS8 and later: null.
410 	 * @deprecated In JLS8 and later, use {@link #thrownExceptionTypes} instead.
411 	 */
412 	private ASTNode.NodeList thrownExceptions = null;
413 
414 	/**
415 	 * The list of thrown exception Types (element type: {@link Type}).
416 	 * Null before JLS8. Added in JLS8; defaults to an empty list
417 	 * (see constructor).
418 	 *
419 	 * @since 3.10
420 	 */
421 	private ASTNode.NodeList thrownExceptionTypes = null;
422 
423 	/**
424 	 * The method body, or <code>null</code> if none.
425 	 * Defaults to none.
426 	 */
427 	private Block optionalBody = null;
428 
429 	/**
430 	 * Creates a new AST node for a method declaration owned
431 	 * by the given AST. By default, the declaration is for a method of an
432 	 * unspecified, but legal, name; no modifiers; no javadoc; no type
433 	 * parameters; void return type; no parameters; no array dimensions after
434 	 * the parameters; no thrown exceptions; and no body (as opposed to an
435 	 * empty body).
436 	 * <p>
437 	 * N.B. This constructor is package-private; all subclasses must be
438 	 * declared in the same package; clients are unable to declare
439 	 * additional subclasses.
440 	 * </p>
441 	 *
442 	 * @param ast the AST that is to own this node
443 	 */
MethodDeclaration(AST ast)444 	MethodDeclaration(AST ast) {
445 		super(ast);
446 		if (ast.apiLevel >= AST.JLS3_INTERNAL) {
447 			this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
448 		}
449 		if (ast.apiLevel < AST.JLS8_INTERNAL) {
450 			this.thrownExceptions = new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY);
451 		} else {
452 			this.extraDimensions = new ASTNode.NodeList(EXTRA_DIMENSIONS2_PROPERTY);
453 			this.thrownExceptionTypes = new ASTNode.NodeList(THROWN_EXCEPTION_TYPES_PROPERTY);
454 		}
455 	}
456 
457 	/* (omit javadoc for this method)
458 	 * Method declared on ASTNode.
459 	 * @since 3.0
460 	 */
461 	@Override
internalStructuralPropertiesForType(int apiLevel)462 	final List internalStructuralPropertiesForType(int apiLevel) {
463 		return propertyDescriptors(apiLevel);
464 	}
465 
466 	@Override
internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled)467 	final List internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled) {
468 		return propertyDescriptors(apiLevel, previewEnabled);
469 	}
470 
471 	@Override
internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value)472 	final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
473 		if (property == MODIFIERS_PROPERTY) {
474 			if (get) {
475 				return getModifiers();
476 			} else {
477 				internalSetModifiers(value);
478 				return 0;
479 			}
480 		}
481 		if (property == EXTRA_DIMENSIONS_PROPERTY) {
482 			if (get) {
483 				return getExtraDimensions();
484 			} else {
485 				setExtraDimensions(value);
486 				return 0;
487 			}
488 		}
489 		// allow default implementation to flag the error
490 		return super.internalGetSetIntProperty(property, get, value);
491 	}
492 
493 	@Override
internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value)494 	final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
495 		if (property == CONSTRUCTOR_PROPERTY) {
496 			if (get) {
497 				return isConstructor();
498 			} else {
499 				setConstructor(value);
500 				return false;
501 			}
502 		} else if (property == COMPACT_CONSTRUCTOR_PROPERTY) {
503 			if (get) {
504 				return isCompactConstructor();
505 			} else {
506 				setCompactConstructor(value);
507 				return false;
508 			}
509 		}
510 		// allow default implementation to flag the error
511 		return super.internalGetSetBooleanProperty(property, get, value);
512 	}
513 
514 
515 
516 	@Override
internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child)517 	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
518 		if (property == JAVADOC_PROPERTY) {
519 			if (get) {
520 				return getJavadoc();
521 			} else {
522 				setJavadoc((Javadoc) child);
523 				return null;
524 			}
525 		}
526 		if (property == NAME_PROPERTY) {
527 			if (get) {
528 				return getName();
529 			} else {
530 				setName((SimpleName) child);
531 				return null;
532 			}
533 		}
534 		if (property == RETURN_TYPE_PROPERTY) {
535 			if (get) {
536 				return getReturnType();
537 			} else {
538 				setReturnType((Type) child);
539 				return null;
540 			}
541 		}
542 		if (property == RETURN_TYPE2_PROPERTY) {
543 			if (get) {
544 				return getReturnType2();
545 			} else {
546 				setReturnType2((Type) child);
547 				return null;
548 			}
549 		}
550 		if (property == RECEIVER_TYPE_PROPERTY) {
551 			if (get) {
552 				return getReceiverType();
553 			} else {
554 				setReceiverType((Type) child);
555 				return null;
556 			}
557 		}
558 		if (property == RECEIVER_QUALIFIER_PROPERTY) {
559 			if (get) {
560 				return getReceiverQualifier();
561 			} else {
562 				setReceiverQualifier((SimpleName) child);
563 				return null;
564 			}
565 		}
566 		if (property == BODY_PROPERTY) {
567 			if (get) {
568 				return getBody();
569 			} else {
570 				setBody((Block) child);
571 				return null;
572 			}
573 		}
574 		// allow default implementation to flag the error
575 		return super.internalGetSetChildProperty(property, get, child);
576 	}
577 
578 	@Override
internalGetChildListProperty(ChildListPropertyDescriptor property)579 	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
580 		if (property == MODIFIERS2_PROPERTY) {
581 			return modifiers();
582 		}
583 		if (property == TYPE_PARAMETERS_PROPERTY) {
584 			return typeParameters();
585 		}
586 		if (property == PARAMETERS_PROPERTY) {
587 			return parameters();
588 		}
589 		if (property == THROWN_EXCEPTIONS_PROPERTY) {
590 			return thrownExceptions();
591 		}
592 		if (property == THROWN_EXCEPTION_TYPES_PROPERTY) {
593 			return thrownExceptionTypes();
594 		}
595 		if (property == EXTRA_DIMENSIONS2_PROPERTY) {
596 			return extraDimensions();
597 		}
598 		// allow default implementation to flag the error
599 		return super.internalGetChildListProperty(property);
600 	}
601 
602 	@Override
internalJavadocProperty()603 	final ChildPropertyDescriptor internalJavadocProperty() {
604 		return JAVADOC_PROPERTY;
605 	}
606 
607 	@Override
internalModifiers2Property()608 	final ChildListPropertyDescriptor internalModifiers2Property() {
609 		return MODIFIERS2_PROPERTY;
610 	}
611 
612 	@Override
internalModifiersProperty()613 	final SimplePropertyDescriptor internalModifiersProperty() {
614 		return MODIFIERS_PROPERTY;
615 	}
616 
617 	@Override
getNodeType0()618 	final int getNodeType0() {
619 		return METHOD_DECLARATION;
620 	}
621 
622 	@Override
clone0(AST target)623 	ASTNode clone0(AST target) {
624 		MethodDeclaration result = new MethodDeclaration(target);
625 		result.setSourceRange(getStartPosition(), getLength());
626 		result.setJavadoc(
627 			(Javadoc) ASTNode.copySubtree(target, getJavadoc()));
628 		if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
629 			result.internalSetModifiers(getModifiers());
630 			result.setReturnType(
631 					(Type) ASTNode.copySubtree(target, getReturnType()));
632 		}
633 		if (this.ast.apiLevel >= AST.JLS3_INTERNAL) {
634 			result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
635 			result.typeParameters().addAll(
636 					ASTNode.copySubtrees(target, typeParameters()));
637 			result.setReturnType2(
638 					(Type) ASTNode.copySubtree(target, getReturnType2()));
639 		}
640 		result.setConstructor(isConstructor());
641 		result.setName((SimpleName) getName().clone(target));
642 		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
643 			result.setReceiverType((Type) ASTNode.copySubtree(target, getReceiverType()));
644 			result.setReceiverQualifier((SimpleName) ASTNode.copySubtree(target, getReceiverQualifier()));
645 		}
646 		result.parameters().addAll(
647 			ASTNode.copySubtrees(target, parameters()));
648 		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
649 			result.extraDimensions().addAll(ASTNode.copySubtrees(target, extraDimensions()));
650 		} else {
651 			result.setExtraDimensions(getExtraDimensions());
652 		}
653 		if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
654 			result.thrownExceptionTypes().addAll(ASTNode.copySubtrees(target, thrownExceptionTypes()));
655 		} else {
656 			result.thrownExceptions().addAll(ASTNode.copySubtrees(target, thrownExceptions()));
657 		}
658 		if (DOMASTUtil.isRecordDeclarationSupported(this.ast)) {
659 			result.setCompactConstructor(isCompactConstructor());
660 		}
661 		result.setBody(
662 			(Block) ASTNode.copySubtree(target, getBody()));
663 		return result;
664 	}
665 
666 	@Override
subtreeMatch0(ASTMatcher matcher, Object other)667 	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
668 		// dispatch to correct overloaded match method
669 		return matcher.match(this, other);
670 	}
671 
672 	@Override
accept0(ASTVisitor visitor)673 	void accept0(ASTVisitor visitor) {
674 		boolean visitChildren = visitor.visit(this);
675 		if (visitChildren) {
676 			// visit children in normal left to right reading order
677 			acceptChild(visitor, getJavadoc());
678 			if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
679 				acceptChild(visitor, getReturnType());
680 			} else {
681 				acceptChildren(visitor, this.modifiers);
682 				acceptChildren(visitor, this.typeParameters);
683 				acceptChild(visitor, getReturnType2());
684 			}
685 			// n.b. visit return type even for constructors
686 			acceptChild(visitor, getName());
687 			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
688 				acceptChild(visitor, this.optionalReceiverType);
689 				acceptChild(visitor, this.optionalReceiverQualifier);
690 			}
691 			acceptChildren(visitor, this.parameters);
692 			if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
693 				acceptChildren(visitor, this.extraDimensions);
694 				acceptChildren(visitor, this.thrownExceptionTypes);
695 			} else {
696 				acceptChildren(visitor, this.thrownExceptions);
697 			}
698 			acceptChild(visitor, getBody());
699 		}
700 		visitor.endVisit(this);
701 	}
702 
703 	/**
704 	 * Returns whether this declaration declares a constructor or a method.
705 	 *
706 	 * @return <code>true</code> if this is a constructor declaration,
707 	 *    and <code>false</code> if this is a method declaration
708 	 */
isConstructor()709 	public boolean isConstructor() {
710 		return this.isConstructor;
711 	}
712 
713 	/**
714 	 * Sets whether this declaration declares a constructor or a method.
715 	 *
716 	 * @param isConstructor <code>true</code> for a constructor declaration,
717 	 *    and <code>false</code> for a method declaration
718 	 */
setConstructor(boolean isConstructor)719 	public void setConstructor(boolean isConstructor) {
720 		preValueChange(CONSTRUCTOR_PROPERTY);
721 		this.isConstructor = isConstructor;
722 		postValueChange(CONSTRUCTOR_PROPERTY);
723 	}
724 
725 	/**
726 	 * Returns whether this declaration declares a constructor or a method.
727 	 *
728 	 * @return <code>true</code> if this is a compact constructor declaration in a record,
729 	 *    and <code>false</code> if this is a method declaration
730 	 * @since 3.22
731 	 * @noreference This method is not intended to be referenced by clients.
732 	 * @exception UnsupportedOperationException if this operation is not used in JLS14
733 	 * @exception UnsupportedOperationException if this operation is used with previewEnabled flag as false
734 	 */
735 
isCompactConstructor()736 	public boolean isCompactConstructor() {
737 		supportedOnlyIn14();
738 		unsupportedWithoutPreviewError();
739 		return this.isCompactConstructor;
740 	}
741 
742 	/**
743 	 * Sets whether this declaration declares a compact constructor in a record or a method.
744 	 *
745 	 * @param isCompactConstructor <code>true</code> for a constructor declaration,
746 	 *    and <code>false</code> for a method declaration
747 	 * @since 3.22
748 	 * @noreference This method is not intended to be referenced by clients.
749 	 * @exception UnsupportedOperationException if this operation is not used in JLS14
750 	 * @exception UnsupportedOperationException if this operation is used with previewEnabled flag as false
751 	 */
752 
setCompactConstructor(boolean isCompactConstructor)753 	public void setCompactConstructor(boolean isCompactConstructor) {
754 		preValueChange(COMPACT_CONSTRUCTOR_PROPERTY);
755 		this.isCompactConstructor = isCompactConstructor;
756 		postValueChange(COMPACT_CONSTRUCTOR_PROPERTY);
757 	}
758 
759 	/**
760 	 * Returns the live ordered list of type parameters of this method
761 	 * declaration (added in JLS3 API). This list is non-empty for parameterized methods.
762 	 *
763 	 * @return the live list of type parameters
764 	 *    (element type: {@link TypeParameter})
765 	 * @exception UnsupportedOperationException if this operation is used in
766 	 * a JLS2 AST
767 	 * @since 3.1
768 	 */
typeParameters()769 	public List typeParameters() {
770 		// more efficient than just calling unsupportedIn2() to check
771 		if (this.typeParameters == null) {
772 			unsupportedIn2();
773 		}
774 		return this.typeParameters;
775 	}
776 
777 	/**
778 	 * Returns the name of the method declared in this method declaration.
779 	 * For a constructor declaration, this should be the same as the name
780 	 * of the class.
781 	 *
782 	 * @return the method name node
783 	 */
getName()784 	public SimpleName getName() {
785 		if (this.methodName == null) {
786 			// lazy init must be thread-safe for readers
787 			synchronized (this) {
788 				if (this.methodName == null) {
789 					preLazyInit();
790 					this.methodName = new SimpleName(this.ast);
791 					postLazyInit(this.methodName, NAME_PROPERTY);
792 				}
793 			}
794 		}
795 		return this.methodName;
796 	}
797 
798 	/**
799 	 * Sets the name of the method declared in this method declaration to the
800 	 * given name. For a constructor declaration, this should be the same as
801 	 * the name of the class.
802 	 *
803 	 * @param methodName the new method name
804 	 * @exception IllegalArgumentException if:
805 	 * <ul>
806 	 * <li>the node belongs to a different AST</li>
807 	 * <li>the node already has a parent</li>
808 	 * </ul>
809 	 */
setName(SimpleName methodName)810 	public void setName(SimpleName methodName) {
811 		if (methodName == null) {
812 			throw new IllegalArgumentException();
813 		}
814 		ASTNode oldChild = this.methodName;
815 		preReplaceChild(oldChild, methodName, NAME_PROPERTY);
816 		this.methodName = methodName;
817 		postReplaceChild(oldChild, methodName, NAME_PROPERTY);
818 	}
819 
820 	/**
821 	 * Returns the receiver type explicitly declared in the method or constructor
822 	 * declaration (added in JLS8 API).
823 	 *
824 	 * If the receiver is not explicitly declared in the method or constructor
825 	 * declaration, <code>null</code> is returned.
826 	 *
827 	 * @return the receiver type or <code>null</code> if receiver is not declared explicitly
828 	 * @exception UnsupportedOperationException if this operation is used below JLS8
829 	 * @since 3.10
830 	 */
getReceiverType()831 	public Type getReceiverType() {
832 		unsupportedIn2_3_4();
833 		return this.optionalReceiverType;
834 	}
835 
836 	/**
837 	 * Sets or clears the given type as the type of explicit receiver parameter (added in JLS8 API).
838 	 * <p>
839 	 * A receiver type is only legal in Java code if it appears on an instance method or on a constructor of an inner class.
840 	 * </p>
841 	 *
842 	 * @param receiverType type of the explicit receiver parameter, or <code>null</code> if there is none
843 	 * @exception UnsupportedOperationException if this operation is used below JLS8
844 	 * @since 3.10
845 	 */
setReceiverType(Type receiverType)846 	public void setReceiverType(Type receiverType) {
847 		unsupportedIn2_3_4();
848 		ASTNode oldChild = this.optionalReceiverType;
849 		preReplaceChild(oldChild, receiverType, RECEIVER_TYPE_PROPERTY);
850 		this.optionalReceiverType = receiverType;
851 		postReplaceChild(oldChild, receiverType, RECEIVER_TYPE_PROPERTY);
852 	}
853 
854 	/**
855 	 * Returns the qualifying name, if any, for the explicit receiver or <code>null</code> if not used (added in JLS8 API).
856 	 * <p>
857 	 * A receiver qualifier is only legal in Java code if it appears on a constructor of an inner class.
858 	 * </p>
859 	 *
860 	 * @return the qualifying name or <code>null</code> if a qualifier was not specified
861 	 * @exception UnsupportedOperationException if this operation is used below JLS8
862 	 * @since 3.10
863 	 */
getReceiverQualifier()864 	public SimpleName getReceiverQualifier() {
865 		unsupportedIn2_3_4();
866 		return this.optionalReceiverQualifier;
867 	}
868 
869 	/**
870 	 * Sets the given simple name as the qualifier for the receiver (added in JLS8 API).
871 	 *
872 	 * @param receiverQualifier explicit receiver parameter to be added to the method declaration
873 	 * @exception UnsupportedOperationException if this operation is used below JLS8
874 	 * @since 3.10
875 	 */
setReceiverQualifier(SimpleName receiverQualifier)876 	public void setReceiverQualifier(SimpleName receiverQualifier) {
877 		unsupportedIn2_3_4();
878 		ASTNode oldChild = this.optionalReceiverQualifier;
879 		preReplaceChild(oldChild, receiverQualifier, RECEIVER_QUALIFIER_PROPERTY);
880 		this.optionalReceiverQualifier = receiverQualifier;
881 		postReplaceChild(oldChild, receiverQualifier, RECEIVER_QUALIFIER_PROPERTY);
882 	}
883 
884 	/**
885 	 * Returns the live ordered list of method parameter declarations for this
886 	 * method declaration.
887 	 *
888 	 * @return the live list of method parameter declarations
889 	 *    (element type: {@link SingleVariableDeclaration})
890 	 */
parameters()891 	public List parameters() {
892 		return this.parameters;
893 	}
894 
895 	/**
896 	 * Returns whether this method declaration declares a
897 	 * variable arity method (added in JLS3 API). The convenience method checks
898 	 * whether the last parameter is so marked.
899 	 *
900 	 * @return <code>true</code> if this is a variable arity method declaration,
901 	 *    and <code>false</code> otherwise
902 	 * @exception UnsupportedOperationException if this operation is used in
903 	 * a JLS2 AST
904 	 * @see SingleVariableDeclaration#isVarargs()
905 	 * @since 3.1
906 	 */
isVarargs()907 	public boolean isVarargs() {
908 		// more efficient than just calling unsupportedIn2() to check
909 		if (this.modifiers == null) {
910 			unsupportedIn2();
911 		}
912 		if (parameters().isEmpty()) {
913 			return false;
914 		} else {
915 			SingleVariableDeclaration v = (SingleVariableDeclaration) parameters().get(parameters().size() - 1);
916 			return v.isVarargs();
917 		}
918 	}
919 
920 	/**
921 	 * Returns the live ordered list of thrown exception names in this method
922 	 * declaration (below JLS8 API only).
923 	 *
924 	 * @return the live list of exception names
925 	 *    (element type: {@link Name})
926 	 * @exception UnsupportedOperationException if this operation is used in
927 	 *    a JLS8 or later AST
928 	 * @deprecated In the JLS8 API, this method is replaced by {@link #thrownExceptionTypes()}.
929 	 */
thrownExceptions()930 	public List thrownExceptions() {
931 		return internalThrownExceptions();
932 	}
933 
934 	/**
935 	 * Internal synonym for deprecated method. Used to avoid
936 	 * deprecation warnings.
937 	 * @exception UnsupportedOperationException if this operation is used in
938 	 *    a JLS8 or later AST
939 	 * @since 3.10
940 	 */
internalThrownExceptions()941 	/*package*/	List internalThrownExceptions() {
942 		// more efficient than just calling supportedOnlyIn2_3_4() to check
943 		if (this.thrownExceptions == null) {
944 			supportedOnlyIn2_3_4();
945 		}
946 		return this.thrownExceptions;
947 	}
948 
949 	/**
950 	 * Returns the live ordered list of thrown exception types in this method
951 	 * declaration.
952 	 *
953 	 * @return the live list of exception types
954 	 *    (element type: {@link Type})
955 	 * @exception UnsupportedOperationException if this operation is used
956 	 *            in a JLS2, JLS3 or JLS4 AST
957 	 * @since 3.10
958 	 */
thrownExceptionTypes()959 	public List thrownExceptionTypes()  {
960 		if (this.thrownExceptionTypes == null) {
961 			unsupportedIn2_3_4();
962 		}
963 		return this.thrownExceptionTypes;
964 	}
965 
966 	/**
967 	 * Returns the return type of the method declared in this method
968 	 * declaration, exclusive of any extra array dimensions (JLS2 API only).
969 	 * This is one of the few places where the void type is meaningful.
970 	 * <p>
971 	 * Note that this child is not relevant for constructor declarations
972 	 * (although, it does still figure in subtree equality comparisons
973 	 * and visits), and is devoid of the binding information ordinarily
974 	 * available.
975 	 * </p>
976 	 *
977 	 * @return the return type, possibly the void primitive type
978 	 * @exception UnsupportedOperationException if this operation is used in
979 	 * an AST later than JLS2
980 	 * @deprecated In the JLS3 API, this method is replaced by {@link #getReturnType2()},
981 	 * which may return <code>null</code>.
982 	 */
getReturnType()983 	public Type getReturnType() {
984 		return internalGetReturnType();
985 	}
986 
987 	/**
988 	 * Internal synonym for deprecated method. Used to avoid
989 	 * deprecation warnings.
990 	 * @exception UnsupportedOperationException if this operation is used in
991 	 * an AST later than JLS2
992 	 * @since 3.1
993 	 */
internalGetReturnType()994 	/*package*/ final Type internalGetReturnType() {
995 		supportedOnlyIn2();
996 		if (this.returnType == null) {
997 			// lazy init must be thread-safe for readers
998 			synchronized (this) {
999 				if (this.returnType == null) {
1000 					preLazyInit();
1001 					this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
1002 					postLazyInit(this.returnType, RETURN_TYPE_PROPERTY);
1003 				}
1004 			}
1005 		}
1006 		return this.returnType;
1007 	}
1008 
1009 	/**
1010 	 * Sets the return type of the method declared in this method declaration
1011 	 * to the given type, exclusive of any extra array dimensions (JLS2 API only). This is one
1012 	 * of the few places where the void type is meaningful.
1013 	 * <p>
1014 	 * Note that this child is not relevant for constructor declarations
1015 	 * (although it does still figure in subtree equality comparisons and visits).
1016 	 * </p>
1017 	 *
1018 	 * @param type the new return type, possibly the void primitive type
1019 	 * @exception IllegalArgumentException if:
1020 	 * <ul>
1021 	 * <li>the node belongs to a different AST</li>
1022 	 * <li>the node already has a parent</li>
1023 	 * </ul>
1024 	 * @exception UnsupportedOperationException if this operation is used in
1025 	 * an AST later than JLS2
1026 	 * @deprecated In the JLS3 API, this method is replaced by
1027 	 * {@link #setReturnType2(Type)}, which accepts <code>null</code>.
1028 	 */
setReturnType(Type type)1029 	public void setReturnType(Type type) {
1030 		internalSetReturnType(type);
1031 	}
1032 
1033 	/**
1034 	 * Internal synonym for deprecated method. Used to avoid
1035 	 * deprecation warnings.
1036 	 * @since 3.1
1037 	 */
internalSetReturnType(Type type)1038 	/*package*/ void internalSetReturnType(Type type) {
1039 	    supportedOnlyIn2();
1040 		if (type == null) {
1041 			throw new IllegalArgumentException();
1042 		}
1043 		ASTNode oldChild = this.returnType;
1044 		preReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
1045 		this.returnType = type;
1046 		postReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
1047 	}
1048 
1049 	/**
1050 	 * Returns the return type of the method declared in this method
1051 	 * declaration, exclusive of any extra array dimensions (added in JLS3 API).
1052 	 * This is one of the few places where the void type is meaningful.
1053 	 * <p>
1054 	 * Note that this child is not relevant for constructor declarations
1055 	 * (although, if present, it does still figure in subtree equality comparisons
1056 	 * and visits), and is devoid of the binding information ordinarily
1057 	 * available. In the JLS2 API, the return type is mandatory.
1058 	 * In the JLS3 API, the return type is optional.
1059 	 * </p>
1060 	 *
1061 	 * @return the return type, possibly the void primitive type,
1062 	 * or <code>null</code> if none
1063 	 * @exception UnsupportedOperationException if this operation is used in
1064 	 * a JLS2 AST
1065 	 * @since 3.1
1066 	 */
getReturnType2()1067 	public Type getReturnType2() {
1068 	    unsupportedIn2();
1069 		if (this.returnType == null && !this.returnType2Initialized) {
1070 			// lazy init must be thread-safe for readers
1071 			synchronized (this) {
1072 				if (this.returnType == null && !this.returnType2Initialized) {
1073 					preLazyInit();
1074 					this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
1075 					this.returnType2Initialized = true;
1076 					postLazyInit(this.returnType, RETURN_TYPE2_PROPERTY);
1077 				}
1078 			}
1079 		}
1080 		return this.returnType;
1081 	}
1082 
1083 	/**
1084 	 * Sets the return type of the method declared in this method declaration
1085 	 * to the given type, exclusive of any extra array dimensions (added in JLS3 API).
1086 	 * This is one of the few places where the void type is meaningful.
1087 	 * <p>
1088 	 * Note that this child is not relevant for constructor declarations
1089 	 * (although it does still figure in subtree equality comparisons and visits).
1090 	 * In the JLS2 API, the return type is mandatory.
1091 	 * In the JLS3 API, the return type is optional.
1092 	 * </p>
1093 	 *
1094 	 * @param type the new return type, possibly the void primitive type,
1095 	 * or <code>null</code> if none
1096 	 * @exception UnsupportedOperationException if this operation is used in
1097 	 * a JLS2 AST
1098 	 * @exception IllegalArgumentException if:
1099 	 * <ul>
1100 	 * <li>the node belongs to a different AST</li>
1101 	 * <li>the node already has a parent</li>
1102 	 * </ul>
1103 	 * @since 3.1
1104 	 */
setReturnType2(Type type)1105 	public void setReturnType2(Type type) {
1106 	    unsupportedIn2();
1107 		this.returnType2Initialized = true;
1108 		ASTNode oldChild = this.returnType;
1109 		preReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
1110 		this.returnType = type;
1111 		postReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
1112 	}
1113 
1114 	/**
1115 	 * Returns the number of extra array dimensions over and above the
1116 	 * explicitly-specified return type.
1117 	 * <p>
1118 	 * For example, <code>int foo()[][]</code> has a return type of
1119 	 * <code>int</code> and two extra array dimensions;
1120 	 * <code>int[][] foo()</code> has a return type of <code>int[][]</code>
1121 	 * and zero extra array dimensions. The two constructs have different
1122 	 * ASTs, even though there are really syntactic variants of the same
1123 	 * method declaration.
1124 	 * </p>
1125 	 * <p>
1126 	 * In the JLS8 API, this method is a convenience method that
1127 	 * counts {@link #extraDimensions()}.
1128 	 * </p>
1129 	 *
1130 	 * @return the number of extra array dimensions
1131 	 * @since 2.1
1132 	 */
getExtraDimensions()1133 	public int getExtraDimensions() {
1134 		// more efficient than checking getAST().API_LEVEL
1135 		if (this.extraDimensions == null) {
1136 			// JLS2,3,4 behavior - bona fide property
1137 			return this.extraArrayDimensions;
1138 		} else {
1139 			return this.extraDimensions.size();
1140 		}
1141 	}
1142 
1143 	/**
1144 	 * Sets the number of extra array dimensions over and above the
1145 	 * explicitly-specified return type.
1146 	 * <p>
1147 	 * For example, <code>int foo()[][]</code> is rendered as a return
1148 	 * type of <code>int</code> with two extra array dimensions;
1149 	 * <code>int[][] foo()</code> is rendered as a return type of
1150 	 * <code>int[][]</code> with zero extra array dimensions. The two
1151 	 * constructs have different ASTs, even though there are really syntactic
1152 	 * variants of the same method declaration.
1153 	 * </p>
1154 	 *
1155 	 * @param dimensions the number of array dimensions
1156 	 * @exception IllegalArgumentException if the number of dimensions is
1157 	 *    negative
1158 	 * @exception UnsupportedOperationException if this operation is used in
1159 	 * a JLS8 or later AST
1160 	 * @since 2.1
1161 	 * @deprecated In the JLS8 API, this method is replaced by
1162 	 * {@link #extraDimensions()} which contains a list of {@link Dimension} nodes.
1163 	 */
setExtraDimensions(int dimensions)1164 	public void setExtraDimensions(int dimensions) {
1165 		// more efficient than just calling supportedOnlyIn2_3_4() to check
1166 		if (this.extraDimensions != null) {
1167 			supportedOnlyIn2_3_4();
1168 		}
1169 		if (dimensions < 0) {
1170 			throw new IllegalArgumentException();
1171 		}
1172 		preValueChange(EXTRA_DIMENSIONS_PROPERTY);
1173 		this.extraArrayDimensions = dimensions;
1174 		postValueChange(EXTRA_DIMENSIONS_PROPERTY);
1175 	}
1176 
1177 	/**
1178 	 * Returns the live ordered list of extra dimensions with optional annotations (added in JLS8 API).
1179 	 *
1180 	 * @return the live list of extra dimensions with optional annotations (element type: {@link Dimension})
1181 	 * @exception UnsupportedOperationException if this operation is used below JLS8
1182 	 * @since 3.10
1183 	 */
extraDimensions()1184 	public List extraDimensions() {
1185 		// more efficient than just calling unsupportedIn2_3_4() to check
1186 		if (this.extraDimensions == null) {
1187 			unsupportedIn2_3_4();
1188 		}
1189 		return this.extraDimensions;
1190 	}
1191 
1192 	/**
1193 	 * Returns the body of this method declaration, or <code>null</code> if
1194 	 * this method has <b>no</b> body.
1195 	 * <p>
1196 	 * Note that there is a subtle difference between having no body and having
1197 	 * an empty body ("{}").
1198 	 * </p>
1199 	 *
1200 	 * @return the method body, or <code>null</code> if this method has no
1201 	 *    body
1202 	 */
getBody()1203 	public Block getBody() {
1204 		return this.optionalBody;
1205 	}
1206 
1207 	/**
1208 	 * Sets or clears the body of this method declaration.
1209 	 * <p>
1210 	 * Note that there is a subtle difference between having no body
1211 	 * (as in <code>"void foo();"</code>) and having an empty body (as in
1212 	 * "void foo() {}"). Abstract methods, and methods declared in interfaces,
1213 	 * have no body. Non-abstract methods, and all constructors, have a body.
1214 	 * </p>
1215 	 *
1216 	 * @param body the block node, or <code>null</code> if
1217 	 *    there is none
1218 	 * @exception IllegalArgumentException if:
1219 	 * <ul>
1220 	 * <li>the node belongs to a different AST</li>
1221 	 * <li>the node already has a parent</li>
1222 	 * <li>a cycle in would be created</li>
1223 	 * </ul>
1224 	 */
setBody(Block body)1225 	public void setBody(Block body) {
1226 		// a MethodDeclaration may occur in a Block - must check cycles
1227 		ASTNode oldChild = this.optionalBody;
1228 		preReplaceChild(oldChild, body, BODY_PROPERTY);
1229 		this.optionalBody = body;
1230 		postReplaceChild(oldChild, body, BODY_PROPERTY);
1231 	}
1232 
1233 	/**
1234 	 * Resolves and returns the binding for the method or constructor declared
1235 	 * in this method or constructor declaration.
1236 	 * <p>
1237 	 * Note that bindings are generally unavailable unless requested when the
1238 	 * AST is being built.
1239 	 * </p>
1240 	 *
1241 	 * @return the binding, or <code>null</code> if the binding cannot be
1242 	 *    resolved
1243 	 */
resolveBinding()1244 	public IMethodBinding resolveBinding() {
1245 		return this.ast.getBindingResolver().resolveMethod(this);
1246 	}
1247 
1248 	@Override
memSize()1249 	int memSize() {
1250 		return super.memSize() + 13 * 4;
1251 	}
1252 
1253 	@Override
treeSize()1254 	int treeSize() {
1255 		return
1256 			memSize()
1257 			+ (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
1258 			+ (this.modifiers == null ? 0 : this.modifiers.listSize())
1259 			+ (this.typeParameters == null ? 0 : this.typeParameters.listSize())
1260 			+ (this.methodName == null ? 0 : getName().treeSize())
1261 			+ (this.optionalReceiverType == null ? 0 : this.optionalReceiverType.treeSize())
1262 			+ (this.optionalReceiverQualifier == null ? 0 : this.optionalReceiverQualifier.treeSize())
1263 			+ (this.returnType == null ? 0 : this.returnType.treeSize())
1264 			+ this.parameters.listSize()
1265 			+ (this.ast.apiLevel < AST.JLS8_INTERNAL
1266 					? this.thrownExceptions.listSize()
1267 					: this.extraDimensions.listSize() + this.thrownExceptionTypes.listSize())
1268 			+ (this.optionalBody == null ? 0 : getBody().treeSize());
1269 	}
1270 }
1271 
1272