/*******************************************************************************
* Copyright (c) 2004, 2008 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.jdt.core.dom;
import java.util.ArrayList;
import java.util.List;
/**
* AST node for a tag within a doc comment. Tag elements nested within another tag element are
* called inline doc tags.
*
* <pre>
* TagElement:
* [ <b>@</b> Identifier ] { DocElement }
* DocElement:
* TextElement
* Name
* MethodRef
* MemberRef
* <b>{</b> TagElement <b>}</b>
* </pre>
*
* @see Javadoc
* @since 3.0
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public final class TagElement extends ASTNode implements IDocElement {
/**
* The "tagName" structural property of this node type.
*
* @since 3.0
*/
public static final SimplePropertyDescriptor TAG_NAME_PROPERTY=
new SimplePropertyDescriptor(TagElement.class, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
/**
* The "fragments" structural property of this node type.
*
* @since 3.0
*/
public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY=
new ChildListPropertyDescriptor(TagElement.class, "fragments", IDocElement.class, CYCLE_RISK); //$NON-NLS-1$
/**
* A list of property descriptors (element type: {@link StructuralPropertyDescriptor}), or null
* if uninitialized.
*
* @since 3.0
*/
private static final List PROPERTY_DESCRIPTORS;
static {
List propertyList= new ArrayList(3);
createPropertyList(TagElement.class, propertyList);
addProperty(TAG_NAME_PROPERTY, propertyList);
addProperty(FRAGMENTS_PROPERTY, propertyList);
PROPERTY_DESCRIPTORS= reapPropertyList(propertyList);
}
/**
* Returns a list of structural property descriptors for this node type. Clients must not modify
* the result.
*
* @param apiLevel the API level; one of the <code>AST.JLS*</code> constants
* @return a list of property descriptors (element type: {@link StructuralPropertyDescriptor})
* @since 3.0
*/
public static List propertyDescriptors(int apiLevel) {
return PROPERTY_DESCRIPTORS;
}
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_AUTHOR= "@author"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
* <p>
* Note that this tag first appeared in J2SE 5.
* </p>
*
* @since 3.1
*/
public static final String TAG_CODE= "@code"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_DEPRECATED= "@deprecated"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
*/
public static final String TAG_DOCROOT= "@docRoot"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_EXCEPTION= "@exception"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
*/
public static final String TAG_INHERITDOC= "@inheritDoc"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
*/
public static final String TAG_LINK= "@link"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
*/
public static final String TAG_LINKPLAIN= "@linkplain"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
* <p>
* Note that this tag first appeared in J2SE 5.
* </p>
*
* @since 3.1
*/
public static final String TAG_LITERAL= "@literal"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_PARAM= "@param"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_RETURN= "@return"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_SEE= "@see"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_SERIAL= "@serial"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_SERIALDATA= "@serialData"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_SERIALFIELD= "@serialField"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_SINCE= "@since"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_THROWS= "@throws"; //$NON-NLS-1$
/**
* Standard inline doc tag name (value {@value}).
*/
public static final String TAG_VALUE= "@value"; //$NON-NLS-1$
/**
* Standard doc tag name (value {@value}).
*/
public static final String TAG_VERSION= "@version"; //$NON-NLS-1$
/**
* The tag name, or null if none; defaults to null.
*/
private String optionalTagName= null;
/**
* The list of doc elements (element type: <code>IDocElement</code>). Defaults to an empty list.
*/
private ASTNode.NodeList fragments=
new ASTNode.NodeList(FRAGMENTS_PROPERTY);
/**
* Creates a new AST node for a tag element owned by the given AST. The new node has no name and
* an empty list of fragments.
* <p>
* N.B. This constructor is package-private; all subclasses must be declared in the same
* package; clients are unable to declare additional subclasses.
* </p>
*
* @param ast the AST that is to own this node
*/
TagElement(AST ast) {
super(ast);
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
final List internalStructuralPropertiesForType(int apiLevel) {
return propertyDescriptors(apiLevel);
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
if (property == TAG_NAME_PROPERTY) {
if (get) {
return getTagName();
} else {
setTagName((String)value);
return null;
}
}
// allow default implementation to flag the error
return super.internalGetSetObjectProperty(property, get, value);
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
if (property == FRAGMENTS_PROPERTY) {
return fragments();
}
// allow default implementation to flag the error
return super.internalGetChildListProperty(property);
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
final int getNodeType0() {
return TAG_ELEMENT;
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
ASTNode clone0(AST target) {
TagElement result= new TagElement(target);
result.setSourceRange(getStartPosition(), getLength());
result.setTagName(getTagName());
result.fragments().addAll(ASTNode.copySubtrees(target, fragments()));
return result;
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
// dispatch to correct overloaded match method
return matcher.match(this, other);
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
void accept0(ASTVisitor visitor) {
boolean visitChildren= visitor.visit(this);
if (visitChildren) {
acceptChildren(visitor, this.fragments);
}
visitor.endVisit(this);
}
/**
* Returns this node's tag name, or <code>null</code> if none. For top level doc tags such as
* parameter tags, the tag name includes the "@" character ("@param"). For inline doc tags such
* as link tags, the tag name includes the "@" character ("@link"). The tag name may also be
* <code>null</code>; this is used to represent the material at the start of a doc comment
* preceding the first explicit tag.
*
* @return the tag name, or <code>null</code> if none
*/
public String getTagName() {
return this.optionalTagName;
}
/**
* Sets the tag name of this node to the given value. For top level doc tags such as parameter
* tags, the tag name includes the "@" character ("@param"). For inline doc tags such as link
* tags, the tag name includes the "@" character ("@link"). The tag name may also be
* <code>null</code>; this is used to represent the material at the start of a doc comment
* preceding the first explicit tag.
*
* @param tagName the tag name, or <code>null</code> if none
*/
public void setTagName(String tagName) {
preValueChange(TAG_NAME_PROPERTY);
this.optionalTagName= tagName;
postValueChange(TAG_NAME_PROPERTY);
}
/**
* Returns the live list of fragments in this tag element.
* <p>
* The fragments cover everything following the tag name (or everything if there is no tag
* name), and generally omit embedded line breaks (and leading whitespace on new lines,
* including any leading "*"). {@link org.eclipse.jdt.core.dom.TagElement} nodes are used to
* represent tag elements (e.g., "@link") nested within this tag element.
* </p>
* <p>
* Here are some typical examples:
* <ul>
* <li>"@see Foo#bar()" - TagElement with tag name "@see"; fragments() contains a single
* MethodRef node</li>
* <li>"@param args the program arguments" - TagElement with tag name "@param"; 2 fragments:
* SimpleName ("args"), TextElement (" the program arguments")</li>
* <li>"@return See {@link #foo foo} instead." - TagElement with tag name "@return"; 3
* fragments: TextElement ("See "), TagElement (for "@link #foo foo"), TextElement
* (" instead.")</li>
* </ul>
* The use of Name, MethodRef, and MemberRef nodes within tag elements allows these fragments to
* be queried for binding information.
* </p>
* <p>
* Adding and removing nodes from this list affects this node dynamically. The nodes in this
* list may be of various types, including {@link TextElement},
* {@link org.eclipse.jdt.core.dom.TagElement}, {@link Name}, {@link MemberRef}, and
* {@link MethodRef}. Clients should assume that the list of types may grow in the future, and
* write their code to deal with unexpected nodes types. However, attempts to add a
* non-proscribed type of node will trigger an exception.
*
* @return the live list of doc elements in this tag element (element type: <code>ASTNode</code>
* )
*/
public List fragments() {
return this.fragments;
}
/**
* Returns whether this tag element is nested within another tag element. Nested tag elements
* appears enclosed in "{" and "}"; certain doc tags, including "@link" and "@linkplain" are
* only meaningful as nested tags. Top-level (i.e., non-nested) doc tags begin on a new line;
* certain doc tags, including "@param" and "@see" are only meaningful as top-level tags.
* <p>
* This convenience methods checks to see whether the parent of this node is of type
* {@link org.eclipse.jdt.core.dom.TagElement}.
* </p>
*
* @return <code>true</code> if this node is a nested tag element, and false if this node is
* either parented by a doc comment node ({@link Javadoc}), or is unparented
*/
public boolean isNested() {
return (getParent() instanceof TagElement);
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
int memSize() {
int size= BASE_NODE_SIZE + 2 * 4 + stringSize(this.optionalTagName);
return size;
}
/* (omit javadoc for this method)
* Method declared on ASTNode.
*/
int treeSize() {
return memSize() + this.fragments.listSize();
}
}