KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > javadoc > TagParser


1 ////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2005 Oliver Burn
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
14
//
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
////////////////////////////////////////////////////////////////////////////////
19
package com.puppycrawl.tools.checkstyle.checks.javadoc;
20
21 import java.util.LinkedList JavaDoc;
22 import java.util.List JavaDoc;
23
24 /**
25  * Helper class used to parse HTML tags from a single line of text.
26  * Just the beginning of the HTML tag is located. No attempt is made to
27  * parse out the complete tag, particularly since some of the tag
28  * parameters could be located on the following line of text. The
29  * <code>hasNextTag</code> and <code>nextTag</code> methods are used
30  * to iterate through the HTML tags that were found on the line of text.
31  *
32  * @author Chris Stillwell
33  */

34 class TagParser
35 {
36     /** List of HtmlTags found on the input line of text. */
37     private final List JavaDoc mTags = new LinkedList JavaDoc();
38
39     /**
40      * Constructs a TagParser and finds the first tag if any.
41      * @param aText the line of text to parse.
42      * @param aLineNo the source line number.
43      */

44     public TagParser(String JavaDoc[] aText, int aLineNo)
45     {
46         parseTags(aText, aLineNo);
47     }
48
49     /**
50      * Returns the next available HtmlTag.
51      * @return a HtmlTag or <code>null</code> if none available.
52      * @throws IndexOutOfBoundsException if there are no HtmlTags
53      * left to return.
54      */

55     public HtmlTag nextTag()
56     {
57         return (HtmlTag) mTags.remove(0);
58     }
59
60     /**
61      * Indicates if there are any more HtmlTag to retrieve.
62      * @return <code>true</code> if there are more tags.
63      */

64     public boolean hasNextTag()
65     {
66         return (mTags.size() > 0);
67     }
68
69     /**
70      * Performs lazy initialization on the internal tags List
71      * and adds the tag.
72      * @param aTag the HtmlTag to add.
73      */

74     private void add(HtmlTag aTag)
75     {
76         mTags.add(aTag);
77     }
78
79     /**
80      * Parses the text line for any HTML tags and adds them to the internal
81      * List of tags.
82      * @param aText the source line to parse.
83      * @param aLineNo the source line number.
84      */

85     private void parseTags(String JavaDoc[] aText, int aLineNo)
86     {
87         final int nLines = aText.length;
88         Point position = new Point(0, 0);
89
90         position = findChar(aText, '<', position);
91         while (position.getLineNo() < nLines) {
92             // if this is html comment then skip it
93
if (isCommentTag(aText, position)) {
94                 position = skipHtmlComment(aText, position);
95             }
96             else if (!isTag(aText, position)) {
97                 position = getNextCharPos(aText, position);
98             }
99             else {
100                 // find end of tag
101
final Point endTag = findChar(aText, '>', position);
102                 final boolean incompleteTag = (endTag.getLineNo() >= nLines);
103                 // get tag id (one word)
104
final String JavaDoc tagId =
105                     (incompleteTag ? "" : getTagId(aText, position));
106                 // is this closed tag
107
final boolean closedTag =
108                     ((endTag.getLineNo() < nLines) && (endTag.getColumnNo() > 0)
109                      && (aText[endTag.getLineNo()]
110                      .charAt(endTag.getColumnNo() - 1) == '/'));
111                 // add new tag
112
add(new HtmlTag(tagId,
113                                 position.getLineNo() + aLineNo,
114                                 position.getColumnNo(),
115                                 closedTag,
116                                 incompleteTag,
117                                 aText[position.getLineNo()]));
118                 position = endTag;
119             }
120             position = findChar(aText, '<', position);
121         }
122     }
123
124     /**
125      * Checks if the given position is start one for HTML tag.
126      * @param aText text of javadoc comments.
127      * @param aPos position to check.
128      * @return <code>true</code> some HTML tag starts from given position.
129      */

130     private boolean isTag(String JavaDoc[] aText, Point aPos)
131     {
132         final int column = aPos.getColumnNo() + 1;
133         final String JavaDoc text = aText[aPos.getLineNo()];
134
135         return (((column < text.length())
136                 && (((text.charAt(column) >= 'A')
137                      && (text.charAt(column) <= 'Z'))
138                     || ((text.charAt(column) >= 'a')
139                         && (text.charAt(column) <= 'z'))
140                     || (text.charAt(column) == '/')))
141                 || (column >= text.length()));
142     }
143
144     /**
145      * Parse tag id.
146      * @param aText text of javadoc comments.
147      * @param aTagStart start position of the tag
148      * @return id for given tag
149      */

150     private String JavaDoc getTagId(String JavaDoc[] aText, Point aTagStart)
151     {
152         int column = aTagStart.getColumnNo() + 1;
153         String JavaDoc text = aText[aTagStart.getLineNo()];
154         if (column >= text.length()) {
155             return "";
156         }
157
158         if (text.charAt(column) == '/') {
159             column++;
160         }
161
162         text = text.substring(column).trim();
163         column = 0;
164
165         while ((column < text.length())
166                && (((text.charAt(column) >= 'A')
167                     && (text.charAt(column) <= 'Z'))
168                    || ((text.charAt(column) >= 'a')
169                        && (text.charAt(column) <= 'z'))
170                    || ((text.charAt(column) >= '0')
171                        && (text.charAt(column) <= '9'))))
172         {
173             column++;
174         }
175
176         return text.substring(0, column);
177     }
178
179     /**
180      * If this is a HTML-comments.
181      * @param aText text of javadoc comments
182      * @param aPos position to check
183      * @return <code>true</code> if HTML-comments
184      * starts form given position.
185      */

186     private boolean isCommentTag(String JavaDoc[] aText, Point aPos)
187     {
188         return aText[aPos.getLineNo()].startsWith("<!--", aPos.getColumnNo());
189     }
190
191     /**
192      * Skips HTML comments.
193      * @param aText text of javadoc comments.
194      * @param aFrom start position of HTML-comments
195      * @return position after HTML-comments
196      */

197     private Point skipHtmlComment(String JavaDoc[] aText, Point aFrom)
198     {
199         Point to = aFrom;
200         to = findChar(aText, '>', to);
201         while ((to.getLineNo() < aText.length)
202                && !aText[to.getLineNo()]
203                .substring(0, to.getColumnNo()).endsWith("-->"))
204         {
205             to = findChar(aText, '>', getNextCharPos(aText, to));
206         }
207         return to;
208     }
209
210     /**
211      * Finds next occurence of given character.
212      * @param aText text to search
213      * @param aChar character to search
214      * @param aFrom position to start search
215      * @return position of next occurence of given character
216      */

217     private Point findChar(String JavaDoc[] aText, char aChar, Point aFrom)
218     {
219         Point curr = new Point(aFrom.getLineNo(), aFrom.getColumnNo());
220         while ((curr.getLineNo() < aText.length)
221                && (aText[curr.getLineNo()].charAt(curr.getColumnNo()) != aChar))
222         {
223             curr = getNextCharPos(aText, curr);
224         }
225
226         return curr;
227     }
228
229     /**
230      * Returns position of next comment character, skips
231      * whitespaces and asteriks.
232      * @param aText to search.
233      * @param aFrom location to search from
234      * @return location of the next character.
235      */

236     private Point getNextCharPos(String JavaDoc[] aText, Point aFrom)
237     {
238         int line = aFrom.getLineNo();
239         int column = aFrom.getColumnNo() + 1;
240         while ((line < aText.length) && (column >= aText[line].length())) {
241             // go to the next line
242
line++;
243             column = 0;
244             if (line < aText.length) {
245                 //skip beginning spaces and stars
246
final String JavaDoc currentLine = aText[line];
247                 while ((column < currentLine.length())
248                        && (Character.isWhitespace(currentLine.charAt(column))
249                            || (currentLine.charAt(column) == '*')))
250                 {
251                     column++;
252                     if ((column < currentLine.length())
253                         && (currentLine.charAt(column - 1) == '*')
254                         && (currentLine.charAt(column) == '/'))
255                     {
256                         // this is end of comment
257
column = currentLine.length();
258                     }
259                 }
260             }
261         }
262
263         return new Point(line, column);
264     }
265 }
266
267 /**
268  * Represents current position in the text.
269  * @author o_sukholsky
270  */

271 final class Point
272 {
273     /** line number. */
274     private final int mLine;
275     /** clumn number.*/
276     private final int mColumn;
277
278     /**
279      * Creates new <code>Point</code> instance.
280      * @param aLineNo line number
281      * @param aColumnNo column number
282      */

283     public Point(int aLineNo, int aColumnNo)
284     {
285         mLine = aLineNo;
286         mColumn = aColumnNo;
287     }
288
289     /**
290      * Getter for line number.
291      * @return line number of the position.
292      */

293     public int getLineNo()
294     {
295         return mLine;
296     }
297
298     /**
299      * Getter for column number.
300      * @return column number of the position.
301      */

302     public int getColumnNo()
303     {
304         return mColumn;
305     }
306 }
307
Popular Tags