/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.ext.java.jdt.core.dom;
import java.util.Iterator;
import java.util.List;
/**
* Abstract base class of all AST nodes that represent body declarations that may appear in the body of some kind of class or
* interface declaration, including anonymous class declarations, enumeration declarations, and enumeration constant declarations.
* <p>
* For JLS2:
* <p/>
* <pre>
* BodyDeclaration:
* ClassDeclaration
* InterfaceDeclaration
* MethodDeclaration
* ConstructorDeclaration
* FieldDeclaration
* Initializer
* </pre>
* <p/>
* For JLS3, a number of new node types were introduced:
* <p/>
* <pre>
* BodyDeclaration:
* ClassDeclaration
* InterfaceDeclaration
* EnumDeclaration
* MethodDeclaration
* ConstructorDeclaration
* FieldDeclaration
* Initializer
* EnumConstantDeclaration
* AnnotationTypeDeclaration
* AnnotationTypeMemberDeclaration
* </pre>
* <p/>
* </p>
* <p>
* All types of body declarations carry modifiers (and annotations), although they differ in which modifiers are allowed. Most
* types of body declarations can carry a doc comment; Initializer is the only ones that does not. The source range for body
* declarations always includes the doc comment if present.
* </p>
*/
public abstract class BodyDeclaration extends ASTNode {
/** The doc comment, or <code>null</code> if none. Defaults to none. */
Javadoc optionalDocComment = null;
/**
* The modifier flags; bit-wise or of Modifier flags. Defaults to none. Not used in 3.0.
*
* @since 3.0 - field was moved up from subclasses
*/
private int modifierFlags = Modifier.NONE;
/**
* The extended modifiers (element type: {@link IExtendedModifier}). Null in JLS2. Added in JLS3; defaults to an empty list
* (see constructor).
*/
ASTNode.NodeList modifiers = null;
/**
* Returns structural property descriptor for the "modifiers" property of this node as used in JLS2 (type: {@link Integer}).
*
* @return the property descriptor
*/
abstract SimplePropertyDescriptor internalModifiersProperty();
/**
* Returns structural property descriptor for the "modifiers" property of this node as used in JLS3 (element type:
* {@link IExtendedModifier}).
*
* @return the property descriptor
*/
abstract ChildListPropertyDescriptor internalModifiers2Property();
/**
* Returns structural property descriptor for the "modifiers" property of this node as used in JLS3 (element type:
* {@link IExtendedModifier}).
*
* @return the property descriptor
* @since 3.1
*/
public final ChildListPropertyDescriptor getModifiersProperty() {
// important: return property for AST.JLS3
return internalModifiers2Property();
}
/**
* Returns structural property descriptor for the "javadoc" property of this node (child type: {@link Javadoc}).
*
* @return the property descriptor
*/
abstract ChildPropertyDescriptor internalJavadocProperty();
/**
* Returns structural property descriptor for the "javadoc" property of this node (child type: {@link Javadoc}).
*
* @return the property descriptor
* @since 3.1
*/
public final ChildPropertyDescriptor getJavadocProperty() {
return internalJavadocProperty();
}
/**
* Creates and returns a structural property descriptor for the "javadoc" property declared on the given concrete node type
* (child type: {@link Javadoc}).
*
* @return the property descriptor
*/
static final ChildPropertyDescriptor internalJavadocPropertyFactory(Class<?> nodeClass) {
return new ChildPropertyDescriptor(nodeClass, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
}
/**
* Creates and returns a structural property descriptor for the "modifiers" property declared on the given concrete node type
* (type: {@link Integer}).
*
* @return the property descriptor
*/
static final SimplePropertyDescriptor internalModifiersPropertyFactory(Class<?> nodeClass) {
return new SimplePropertyDescriptor(nodeClass, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
}
/**
* Creates and returns a structural property descriptor for the "modifiers" property declared on the given concrete node type
* (element type: {@link IExtendedModifier}).
*
* @return the property descriptor
*/
static final ChildListPropertyDescriptor internalModifiers2PropertyFactory(Class<?> nodeClass) {
return new ChildListPropertyDescriptor(nodeClass, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
}
/**
* Creates a new AST node for a body declaration node owned by the given AST.
* <p>
* N.B. This constructor is package-private.
* </p>
*
* @param ast
* the AST that is to own this node
*/
BodyDeclaration(AST ast) {
super(ast);
if (ast.apiLevel >= AST.JLS3) {
this.modifiers = new ASTNode.NodeList(internalModifiers2Property());
}
}
/**
* Returns the doc comment node.
*
* @return the doc comment node, or <code>null</code> if none
*/
public Javadoc getJavadoc() {
return this.optionalDocComment;
}
/**
* Sets or clears the doc comment node.
*
* @param docComment
* the doc comment node, or <code>null</code> if none
* @throws IllegalArgumentException
* if the doc comment string is invalid
*/
public void setJavadoc(Javadoc docComment) {
ChildPropertyDescriptor p = internalJavadocProperty();
ASTNode oldChild = this.optionalDocComment;
preReplaceChild(oldChild, docComment, p);
this.optionalDocComment = docComment;
postReplaceChild(oldChild, docComment, p);
}
/**
* Returns the modifiers explicitly specified on this declaration.
* <p>
* In the JLS3 API, this method is a convenience method that computes these flags from <code>modifiers()</code>.
* </p>
*
* @return the bit-wise or of <code>Modifier</code> constants
* @see Modifier
*/
public int getModifiers() {
// more efficient than checking getAST().API_LEVEL
if (this.modifiers == null) {
// JLS2 behavior - bona fide property
return this.modifierFlags;
} else {
// JLS3 behavior - convenience method
// performance could be improved by caching computed flags
// but this would require tracking changes to this.modifiers
int computedmodifierFlags = Modifier.NONE;
for (Iterator<IExtendedModifier> it = modifiers().iterator(); it.hasNext(); ) {
IExtendedModifier x = it.next();
if (x instanceof Modifier) {
computedmodifierFlags |= ((Modifier)x).getKeyword().toFlagValue();
}
}
return computedmodifierFlags;
}
}
/**
* Sets the modifiers explicitly specified on this declaration (JLS2 API only).
*
* @param modifiers
* the given modifiers (bit-wise or of <code>Modifier</code> constants)
* @throws UnsupportedOperationException
* if this operation is used in an AST later than JLS2
* @see Modifier
* @deprecated In the JLS3 API, this method is replaced by {@link #modifiers()} which contains a list of a
* <code>Modifier</code> nodes.
*/
public void setModifiers(int modifiers) {
internalSetModifiers(modifiers);
}
/**
* Internal synonym for deprecated method. Used to avoid deprecation warnings.
*
* @since 3.1
*/
/* package */
final void internalSetModifiers(int pmodifiers) {
// more efficient than just calling supportedOnlyIn2() to check
if (this.modifiers != null) {
supportedOnlyIn2();
}
SimplePropertyDescriptor p = internalModifiersProperty();
preValueChange(p);
this.modifierFlags = pmodifiers;
postValueChange(p);
}
/**
* Returns the live ordered list of modifiers and annotations of this declaration (added in JLS3 API).
*
* @return the live list of modifiers and annotations (element type: {@link IExtendedModifier})
* @throws UnsupportedOperationException
* if this operation is used in a JLS2 AST
*/
public List<IExtendedModifier> modifiers() {
// more efficient than just calling unsupportedIn2() to check
if (this.modifiers == null) {
unsupportedIn2();
}
return this.modifiers;
}
/* (omit javadoc for this method) Method declared on ASTNode. */
int memSize() {
return BASE_NODE_SIZE + 3 * 4;
}
}