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