8a512518eae4a8ef71d625bb70e0eff1c913527f
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / Javadoc.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.core.dom;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
18 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
19 import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
20
21 /**
22  * AST node for a Javadoc-style doc comment.
23  * <pre>
24  * Javadoc:
25  *   <b>/** </b> { TagElement } <b>*</b><b>/</b>
26  * </pre>
27  * 
28  * @since 2.0
29  * @noinstantiate This class is not intended to be instantiated by clients.
30  */
31 public class Javadoc extends Comment {
32         
33         /**
34          * The "comment" structural property of this node type (JLS2 API only).
35          * @since 3.0
36          * @deprecated Replaced by {@link #TAGS_PROPERTY} in the JLS3 API.
37          */
38         public static final SimplePropertyDescriptor COMMENT_PROPERTY = 
39                 new SimplePropertyDescriptor(Javadoc.class, "comment", String.class, MANDATORY); //$NON-NLS-1$
40         
41         /**
42          * The "tags" structural property of this node type.
43          * @since 3.1
44          */
45         public static final ChildListPropertyDescriptor TAGS_PROPERTY = 
46                 new ChildListPropertyDescriptor(Javadoc.class, "tags", TagElement.class, CYCLE_RISK); //$NON-NLS-1$
47
48         
49         /**
50          * A list of property descriptors (element type: 
51          * {@link StructuralPropertyDescriptor}),
52          * or null if uninitialized.
53          * @since 3.0
54          */
55         private static final List PROPERTY_DESCRIPTORS_2_0;
56         
57         /**
58          * A list of property descriptors (element type: 
59          * {@link StructuralPropertyDescriptor}),
60          * or null if uninitialized.
61          * @since 3.1
62          */
63         private static final List PROPERTY_DESCRIPTORS_3_0;
64         
65         static {
66                 List properyList = new ArrayList(3);
67                 createPropertyList(Javadoc.class, properyList);
68                 addProperty(COMMENT_PROPERTY, properyList);
69                 addProperty(TAGS_PROPERTY, properyList);
70                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
71                 
72                 properyList = new ArrayList(2);
73                 createPropertyList(Javadoc.class, properyList);
74                 addProperty(TAGS_PROPERTY, properyList);
75                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
76         }
77
78         /**
79          * Returns a list of structural property descriptors for this node type.
80          * Clients must not modify the result.
81          * 
82          * @param apiLevel the API level; one of the
83          * <code>AST.JLS*</code> constants
84          * @return a list of property descriptors (element type: 
85          * {@link StructuralPropertyDescriptor})
86          * @since 3.0
87          */
88         public static List propertyDescriptors(int apiLevel) {
89                 if (apiLevel == AST.JLS2_INTERNAL) {
90                         return PROPERTY_DESCRIPTORS_2_0;
91                 } else {
92                         return PROPERTY_DESCRIPTORS_3_0;
93                 }
94         }
95         
96         /**
97          * Canonical minimal doc comment.
98      * @since 3.0
99          */
100         private static final String MINIMAL_DOC_COMMENT = "/** */";//$NON-NLS-1$
101
102         /**
103          * The doc comment string, including opening and closing comment 
104          * delimiters; defaults to a minimal Javadoc comment.
105          * @deprecated The comment string was replaced in the 3.0 release
106          * by a representation of the structure of the doc comment.
107          * For backwards compatibility, it is still funcational as before.
108          */
109         private String comment = MINIMAL_DOC_COMMENT;
110         
111         /**
112          * The list of tag elements (element type: <code>TagElement</code>). 
113          * Defaults to an empty list.
114          * @since 3.0
115          */
116         private ASTNode.NodeList tags = 
117                 new ASTNode.NodeList(TAGS_PROPERTY);
118
119         /**
120          * Creates a new AST node for a doc comment owned by the given AST.
121          * The new node has an empty list of tag elements (and, for backwards
122          * compatability, an unspecified, but legal, doc comment string).
123          * <p>
124          * N.B. This constructor is package-private; all subclasses must be 
125          * declared in the same package; clients are unable to declare 
126          * additional subclasses.
127          * </p>
128          * 
129          * @param ast the AST that is to own this node
130          */
131         Javadoc(AST ast) {
132                 super(ast);
133         }
134         
135         /* (omit javadoc for this method)
136          * Method declared on ASTNode.
137          */
138         final List internalStructuralPropertiesForType(int apiLevel) {
139                 return propertyDescriptors(apiLevel);
140         }
141         
142         /* (omit javadoc for this method)
143          * Method declared on ASTNode.
144          */
145         final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
146                 if (property == COMMENT_PROPERTY) {
147                         if (get) {
148                                 return getComment();
149                         } else {
150                                 setComment((String) value);
151                                 return null;
152                         }
153                 }
154                 // allow default implementation to flag the error
155                 return super.internalGetSetObjectProperty(property, get, value);
156         }
157
158         /* (omit javadoc for this method)
159          * Method declared on ASTNode.
160          */
161         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
162                 if (property == TAGS_PROPERTY) {
163                         return tags();
164                 }
165                 // allow default implementation to flag the error
166                 return super.internalGetChildListProperty(property);
167         }
168         
169         /* (omit javadoc for this method)
170          * Method declared on ASTNode.
171          */
172         final int getNodeType0() {
173                 return JAVADOC;
174         }
175
176         /* (omit javadoc for this method)
177          * Method declared on ASTNode.
178          */
179         ASTNode clone0(AST target) {
180                 Javadoc result = new Javadoc(target);
181                 result.setSourceRange(this.getStartPosition(), this.getLength());
182                 if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
183                         result.setComment(getComment());
184                 }
185                 result.tags().addAll(ASTNode.copySubtrees(target, tags()));
186                 return result;
187         }
188         
189         /* (omit javadoc for this method)
190          * Method declared on ASTNode.
191          */
192         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
193                 // dispatch to correct overloaded match method
194                 return matcher.match(this, other);
195         }
196
197         /* (omit javadoc for this method)
198          * Method declared on ASTNode.
199          */
200         void accept0(ASTVisitor visitor) {
201                 boolean visitChildren = visitor.visit(this);
202                 if (visitChildren) {
203                         // visit children in normal left to right reading order
204                         acceptChildren(visitor, this.tags);
205                 }
206                 visitor.endVisit(this);
207         }
208
209         /**
210          * Returns the doc comment string, including the starting
211          * and ending comment delimiters, and any embedded line breaks.
212          * 
213          * @return the doc comment string
214          * @exception UnsupportedOperationException if this operation is used in
215          * an AST later than JLS2
216          * @deprecated The comment string was replaced in the 3.0 release
217          * by a representation of the structure of the doc comment.
218          * See {@link #tags() tags}.
219          */
220         public String getComment() {
221             supportedOnlyIn2();
222                 return this.comment;
223         }
224
225         /**
226          * Sets or clears the doc comment string. The documentation
227          * string must include the starting and ending comment delimiters,
228          * and any embedded line breaks.
229          * 
230          * @param docComment the doc comment string
231          * @exception IllegalArgumentException if the Java comment string is invalid
232          * @exception UnsupportedOperationException if this operation is used in
233          * an AST later than JLS2
234          * @deprecated The comment string was replaced in the 3.0 release
235          * by a representation of the structure of the doc comment.
236          * See {@link #tags() tags}.
237          */
238         public void setComment(String docComment) {
239             supportedOnlyIn2();
240                 if (docComment == null) {
241                         throw new IllegalArgumentException();
242                 }
243                 char[] source = docComment.toCharArray();
244                 Scanner scanner = this.ast.scanner;
245                 scanner.resetTo(0, source.length);
246                 scanner.setSource(source);
247                 try {
248                         int token;
249                         boolean onlyOneComment = false;
250                         while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
251                                 switch(token) {
252                                         case TerminalTokens.TokenNameCOMMENT_JAVADOC :
253                                                 if (onlyOneComment) {
254                                                         throw new IllegalArgumentException();
255                                                 }
256                                                 onlyOneComment = true;
257                                                 break;
258                                         default:
259                                                 onlyOneComment = false;
260                                 }
261                         }
262                         if (!onlyOneComment) {
263                                 throw new IllegalArgumentException();
264                         }
265                 } catch (InvalidInputException e) {
266                         throw new IllegalArgumentException();
267                 }
268                 preValueChange(COMMENT_PROPERTY);
269                 this.comment = docComment;
270                 postValueChange(COMMENT_PROPERTY);
271         }
272                 
273         /**
274          * Returns the live list of tag elements that make up this doc 
275          * comment.
276          * <p>
277          * The tag elements cover everything except the starting and ending
278          * comment delimiters, and generally omit leading whitespace 
279          * (including a leading "*") and embedded line breaks.
280          * The first tag element of a typical doc comment represents
281          * all the material before the first explicit doc tag; this
282          * first tag element has a <code>null</code> tag name and
283          * generally contains 1 or more {@link TextElement}s,
284          * and possibly interspersed with tag elements for nested tags
285          * like "{@link String String}".
286          * Subsequent tag elements represent successive top-level doc
287          * tag (e.g., "@param", "@return", "@see").
288          * </p>
289          * <p>
290          * Adding and removing nodes from this list affects this node
291          * dynamically.
292          * </p>
293          * 
294          * @return the live list of tag elements in this doc comment
295          * (element type: <code>TagElement</code>)
296          * @since 3.0
297          */ 
298         public List tags() {
299                 return this.tags;
300         }
301         
302         /* (omit javadoc for this method)
303          * Method declared on ASTNode.
304          */
305         int memSize() {
306                 int size = super.memSize() + 2 * 4;
307                 if (this.comment != MINIMAL_DOC_COMMENT) {
308                         // anything other than the default string takes space
309                         size += stringSize(this.comment);
310                 }
311                 return size;
312         }
313         
314         /* (omit javadoc for this method)
315          * Method declared on ASTNode.
316          */
317         int treeSize() {
318                 return memSize() + this.tags.listSize();
319         }
320 }