001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 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: * AST node for a tag within a doc comment.
017: * Tag elements nested within another tag element are called
018: * inline doc tags.
019: * <pre>
020: * TagElement:
021: * [ <b>@</b> Identifier ] { DocElement }
022: * DocElement:
023: * TextElement
024: * Name
025: * MethodRef
026: * MemberRef
027: * <b>{</b> TagElement <b>}</b>
028: * </pre>
029: *
030: * @see Javadoc
031: * @since 3.0
032: */
033: public final class TagElement extends ASTNode implements IDocElement {
034:
035: /**
036: * The "tagName" structural property of this node type.
037: *
038: * @since 3.0
039: */
040: public static final SimplePropertyDescriptor TAG_NAME_PROPERTY = new SimplePropertyDescriptor(
041: TagElement.class, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
042:
043: /**
044: * The "fragments" structural property of this node type.
045: * @since 3.0
046: */
047: public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = new ChildListPropertyDescriptor(
048: TagElement.class,
049: "fragments", IDocElement.class, CYCLE_RISK); //$NON-NLS-1$
050:
051: /**
052: * A list of property descriptors (element type:
053: * {@link StructuralPropertyDescriptor}),
054: * or null if uninitialized.
055: * @since 3.0
056: */
057: private static final List PROPERTY_DESCRIPTORS;
058:
059: static {
060: List propertyList = new ArrayList(3);
061: createPropertyList(TagElement.class, propertyList);
062: addProperty(TAG_NAME_PROPERTY, propertyList);
063: addProperty(FRAGMENTS_PROPERTY, propertyList);
064: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
065: }
066:
067: /**
068: * Returns a list of structural property descriptors for this node type.
069: * Clients must not modify the result.
070: *
071: * @param apiLevel the API level; one of the
072: * <code>AST.JLS*</code> constants
073: * @return a list of property descriptors (element type:
074: * {@link StructuralPropertyDescriptor})
075: * @since 3.0
076: */
077: public static List propertyDescriptors(int apiLevel) {
078: return PROPERTY_DESCRIPTORS;
079: }
080:
081: /**
082: * Standard doc tag name (value {@value}).
083: */
084: public static final String TAG_AUTHOR = "@author"; //$NON-NLS-1$
085:
086: /**
087: * Standard inline doc tag name (value {@value}).
088: * <p>
089: * Note that this tag first appeared in J2SE 5.
090: * </p>
091: * @since 3.1
092: */
093: public static final String TAG_CODE = "@code"; //$NON-NLS-1$
094:
095: /**
096: * Standard doc tag name (value {@value}).
097: */
098: public static final String TAG_DEPRECATED = "@deprecated"; //$NON-NLS-1$
099:
100: /**
101: * Standard inline doc tag name (value {@value}).
102: */
103: public static final String TAG_DOCROOT = "@docRoot"; //$NON-NLS-1$
104:
105: /**
106: * Standard doc tag name (value {@value}).
107: */
108: public static final String TAG_EXCEPTION = "@exception"; //$NON-NLS-1$
109:
110: /**
111: * Standard inline doc tag name (value {@value}).
112: */
113: public static final String TAG_INHERITDOC = "@inheritDoc"; //$NON-NLS-1$
114:
115: /**
116: * Standard inline doc tag name (value {@value}).
117: */
118: public static final String TAG_LINK = "@link"; //$NON-NLS-1$
119:
120: /**
121: * Standard inline doc tag name (value {@value}).
122: */
123: public static final String TAG_LINKPLAIN = "@linkplain"; //$NON-NLS-1$
124:
125: /**
126: * Standard inline doc tag name (value {@value}).
127: * <p>
128: * Note that this tag first appeared in J2SE 5.
129: * </p>
130: * @since 3.1
131: */
132: public static final String TAG_LITERAL = "@literal"; //$NON-NLS-1$
133:
134: /**
135: * Standard doc tag name (value {@value}).
136: */
137: public static final String TAG_PARAM = "@param"; //$NON-NLS-1$
138:
139: /**
140: * Standard doc tag name (value {@value}).
141: */
142: public static final String TAG_RETURN = "@return"; //$NON-NLS-1$
143:
144: /**
145: * Standard doc tag name (value {@value}).
146: */
147: public static final String TAG_SEE = "@see"; //$NON-NLS-1$
148:
149: /**
150: * Standard doc tag name (value {@value}).
151: */
152: public static final String TAG_SERIAL = "@serial"; //$NON-NLS-1$
153:
154: /**
155: * Standard doc tag name (value {@value}).
156: */
157: public static final String TAG_SERIALDATA = "@serialData"; //$NON-NLS-1$
158:
159: /**
160: * Standard doc tag name (value {@value}).
161: */
162: public static final String TAG_SERIALFIELD = "@serialField"; //$NON-NLS-1$
163:
164: /**
165: * Standard doc tag name (value {@value}).
166: */
167: public static final String TAG_SINCE = "@since"; //$NON-NLS-1$
168:
169: /**
170: * Standard doc tag name (value {@value}).
171: */
172: public static final String TAG_THROWS = "@throws"; //$NON-NLS-1$
173:
174: /**
175: * Standard inline doc tag name (value {@value}).
176: */
177: public static final String TAG_VALUE = "@value"; //$NON-NLS-1$
178:
179: /**
180: * Standard doc tag name (value {@value}).
181: */
182: public static final String TAG_VERSION = "@version"; //$NON-NLS-1$
183:
184: /**
185: * The tag name, or null if none; defaults to null.
186: */
187: private String optionalTagName = null;
188:
189: /**
190: * The list of doc elements (element type: <code>IDocElement</code>).
191: * Defaults to an empty list.
192: */
193: private ASTNode.NodeList fragments = new ASTNode.NodeList(
194: FRAGMENTS_PROPERTY);
195:
196: /**
197: * Creates a new AST node for a tag element owned by the given AST.
198: * The new node has no name and an empty list of fragments.
199: * <p>
200: * N.B. This constructor is package-private; all subclasses must be
201: * declared in the same package; clients are unable to declare
202: * additional subclasses.
203: * </p>
204: *
205: * @param ast the AST that is to own this node
206: */
207: TagElement(AST ast) {
208: super (ast);
209: }
210:
211: /* (omit javadoc for this method)
212: * Method declared on ASTNode.
213: */
214: final List internalStructuralPropertiesForType(int apiLevel) {
215: return propertyDescriptors(apiLevel);
216: }
217:
218: /* (omit javadoc for this method)
219: * Method declared on ASTNode.
220: */
221: final Object internalGetSetObjectProperty(
222: SimplePropertyDescriptor property, boolean get, Object value) {
223: if (property == TAG_NAME_PROPERTY) {
224: if (get) {
225: return getTagName();
226: } else {
227: setTagName((String) value);
228: return null;
229: }
230: }
231: // allow default implementation to flag the error
232: return super .internalGetSetObjectProperty(property, get, value);
233: }
234:
235: /* (omit javadoc for this method)
236: * Method declared on ASTNode.
237: */
238: final List internalGetChildListProperty(
239: ChildListPropertyDescriptor property) {
240: if (property == FRAGMENTS_PROPERTY) {
241: return fragments();
242: }
243: // allow default implementation to flag the error
244: return super .internalGetChildListProperty(property);
245: }
246:
247: /* (omit javadoc for this method)
248: * Method declared on ASTNode.
249: */
250: final int getNodeType0() {
251: return TAG_ELEMENT;
252: }
253:
254: /* (omit javadoc for this method)
255: * Method declared on ASTNode.
256: */
257: ASTNode clone0(AST target) {
258: TagElement result = new TagElement(target);
259: result
260: .setSourceRange(this .getStartPosition(), this
261: .getLength());
262: result.setTagName(getTagName());
263: result.fragments().addAll(
264: ASTNode.copySubtrees(target, fragments()));
265: return result;
266: }
267:
268: /* (omit javadoc for this method)
269: * Method declared on ASTNode.
270: */
271: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
272: // dispatch to correct overloaded match method
273: return matcher.match(this , other);
274: }
275:
276: /* (omit javadoc for this method)
277: * Method declared on ASTNode.
278: */
279: void accept0(ASTVisitor visitor) {
280: boolean visitChildren = visitor.visit(this );
281: if (visitChildren) {
282: acceptChildren(visitor, this .fragments);
283: }
284: visitor.endVisit(this );
285: }
286:
287: /**
288: * Returns this node's tag name, or <code>null</code> if none.
289: * For top level doc tags such as parameter tags, the tag name
290: * includes the "@" character ("@param").
291: * For inline doc tags such as link tags, the tag name
292: * includes the "@" character ("@link").
293: * The tag name may also be <code>null</code>; this is used to
294: * represent the material at the start of a doc comment preceding
295: * the first explicit tag.
296: *
297: * @return the tag name, or <code>null</code> if none
298: */
299: public String getTagName() {
300: return this .optionalTagName;
301: }
302:
303: /**
304: * Sets the tag name of this node to the given value.
305: * For top level doc tags such as parameter tags, the tag name
306: * includes the "@" character ("@param").
307: * For inline doc tags such as link tags, the tag name
308: * includes the "@" character ("@link").
309: * The tag name may also be <code>null</code>; this is used to
310: * represent the material at the start of a doc comment preceding
311: * the first explicit tag.
312: *
313: * @param tagName the tag name, or <code>null</code> if none
314: */
315: public void setTagName(String tagName) {
316: preValueChange(TAG_NAME_PROPERTY);
317: this .optionalTagName = tagName;
318: postValueChange(TAG_NAME_PROPERTY);
319: }
320:
321: /**
322: * Returns the live list of fragments in this tag element.
323: * <p>
324: * The fragments cover everything following the tag name
325: * (or everything if there is no tag name), and generally omit
326: * embedded line breaks (and leading whitespace on new lines,
327: * including any leading "*"). {@link org.eclipse.jdt.core.dom.TagElement}
328: * nodes are used to represent tag elements (e.g., "@link")
329: * nested within this tag element.
330: * </p>
331: * <p>
332: * Here are some typical examples:
333: * <ul>
334: * <li>"@see Foo#bar()" - TagElement with tag name "@see";
335: * fragments() contains a single MethodRef node</li>
336: * <li>"@param args the program arguments" -
337: * TagElement with tag name "@param";
338: * 2 fragments: SimpleName ("args"), TextElement
339: * (" the program arguments")</li>
340: * <li>"@return See {@link #foo foo} instead." -
341: * TagElement with tag name "@return";
342: * 3 fragments: TextElement ("See "),
343: * TagElement (for "@link #foo foo"),
344: * TextElement (" instead.")</li>
345: * </ul>
346: * The use of Name, MethodRef, and MemberRef nodes within
347: * tag elements allows these fragments to be queried for
348: * binding information.
349: * </p>
350: * <p>
351: * Adding and removing nodes from this list affects this node
352: * dynamically. The nodes in this list may be of various
353: * types, including {@link TextElement},
354: * {@link org.eclipse.jdt.core.dom.TagElement}, {@link Name},
355: * {@link MemberRef}, and {@link MethodRef}.
356: * Clients should assume that the list of types may grow in
357: * the future, and write their code to deal with unexpected
358: * nodes types. However, attempts to add a non-proscribed type
359: * of node will trigger an exception.
360: *
361: * @return the live list of doc elements in this tag element
362: * (element type: <code>ASTNode</code>)
363: */
364: public List fragments() {
365: return this .fragments;
366: }
367:
368: /**
369: * Returns whether this tag element is nested within another
370: * tag element. Nested tag elements appears enclosed in
371: * "{" and "}"; certain doc tags, including "@link" and
372: * "@linkplain" are only meaningful as nested tags.
373: * Top-level (i.e., non-nested) doc tags begin on a new line;
374: * certain doc tags, including "@param" and
375: * "@see" are only meaningful as top-level tags.
376: * <p>
377: * This convenience methods checks to see whether the parent
378: * of this node is of type {@link org.eclipse.jdt.core.dom.TagElement}.
379: * </p>
380: *
381: * @return <code>true</code> if this node is a nested tag element,
382: * and false if this node is either parented by a doc comment node
383: * ({@link Javadoc}), or is unparented
384: */
385: public boolean isNested() {
386: return (getParent() instanceof TagElement);
387: }
388:
389: /* (omit javadoc for this method)
390: * Method declared on ASTNode.
391: */
392: int memSize() {
393: int size = BASE_NODE_SIZE + 2 * 4
394: + stringSize(this .optionalTagName);
395: return size;
396: }
397:
398: /* (omit javadoc for this method)
399: * Method declared on ASTNode.
400: */
401: int treeSize() {
402: return memSize() + this.fragments.listSize();
403: }
404: }
|