KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > api > FileContents


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.api;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.Iterator JavaDoc;
28
29 import java.util.regex.Pattern JavaDoc;
30
31 import com.puppycrawl.tools.checkstyle.grammars.CommentListener;
32
33 /**
34  * Represents the contents of a file.
35  *
36  * @author Oliver Burn
37  * @version 1.0
38  */

39 public final class FileContents implements CommentListener
40 {
41     /**
42      * the pattern to match a single line comment containing only the comment
43      * itself -- no code.
44      */

45     private static final String JavaDoc MATCH_SINGLELINE_COMMENT_PAT =
46         "^\\s*//.*$";
47     /** compiled regexp to match a single-line comment line */
48     private static final Pattern JavaDoc MATCH_SINGLELINE_COMMENT =
49         Pattern.compile(MATCH_SINGLELINE_COMMENT_PAT);
50
51     /** the file name */
52     private final String JavaDoc mFilename;
53
54     /** the lines */
55     private final String JavaDoc[] mLines;
56
57     /** map of the Javadoc comments indexed on the last line of the comment.
58      * The hack is it assumes that there is only one Javadoc comment per line.
59      */

60     private final Map JavaDoc mJavadocComments = new HashMap JavaDoc();
61
62     /** map of the C++ comments indexed on the first line of the comment. */
63     private final Map JavaDoc mCPlusPlusComments = new HashMap JavaDoc();
64     /**
65      * map of the C comments indexed on the first line of the comment to a
66      * list of comments on that line
67      */

68     private final Map JavaDoc mCComments = new HashMap JavaDoc();
69
70     /**
71      * Creates a new <code>FileContents</code> instance.
72      *
73      * @param aFilename name of the file
74      * @param aLines the contents of the file
75      */

76     public FileContents(String JavaDoc aFilename, String JavaDoc[] aLines)
77     {
78         mFilename = aFilename;
79         mLines = aLines;
80     }
81
82     /** {@inheritDoc} */
83     public void reportSingleLineComment(String JavaDoc aType,
84                                         int aStartLineNo, int aStartColNo)
85     {
86         reportCppComment(aStartLineNo, aStartColNo);
87     }
88
89     /** {@inheritDoc} */
90     public void reportBlockComment(String JavaDoc aType,
91                                    int aStartLineNo, int aStartColNo,
92                                    int aEndLineNo, int aEndColNo)
93     {
94         reportCComment(aStartLineNo, aStartColNo, aEndLineNo, aEndColNo);
95     }
96
97     /**
98      * Report the location of a C++ style comment.
99      * @param aStartLineNo the starting line number
100      * @param aStartColNo the starting column number
101      **/

102     public void reportCppComment(int aStartLineNo, int aStartColNo)
103     {
104         final String JavaDoc line = mLines[aStartLineNo - 1];
105         final String JavaDoc[] txt = new String JavaDoc[] {line.substring(aStartColNo)};
106         final Comment comment =
107             new Comment(txt, aStartColNo, aStartLineNo, line.length() - 1);
108         mCPlusPlusComments.put(new Integer JavaDoc(aStartLineNo), comment);
109     }
110
111     /**
112      * Returns a map of all the C++ style comments. The key is a line number,
113      * the value is the comment {@link TextBlock} at the line.
114      * @return the Map of comments
115      */

116     public Map JavaDoc getCppComments()
117     {
118         return Collections.unmodifiableMap(mCPlusPlusComments);
119     }
120
121     /**
122      * Report the location of a C-style comment.
123      * @param aStartLineNo the starting line number
124      * @param aStartColNo the starting column number
125      * @param aEndLineNo the ending line number
126      * @param aEndColNo the ending column number
127      **/

128     public void reportCComment(int aStartLineNo, int aStartColNo,
129                                int aEndLineNo, int aEndColNo)
130     {
131         final String JavaDoc[] cc = extractCComment(aStartLineNo, aStartColNo,
132                                             aEndLineNo, aEndColNo);
133         final Comment comment = new Comment(cc, aStartColNo, aEndLineNo,
134                                             aEndColNo);
135
136         // save the comment
137
final Integer JavaDoc key = new Integer JavaDoc(aStartLineNo);
138         if (mCComments.containsKey(key)) {
139             final List JavaDoc entries = (List JavaDoc) mCComments.get(key);
140             entries.add(comment);
141         }
142         else {
143             final List JavaDoc entries = new ArrayList JavaDoc();
144             entries.add(comment);
145             mCComments.put(key, entries);
146         }
147
148         // Remember if possible Javadoc comment
149
if (mLines[aStartLineNo - 1].indexOf("/**", aStartColNo) != -1) {
150             mJavadocComments.put(new Integer JavaDoc(aEndLineNo - 1), comment);
151         }
152     }
153
154     /**
155      * Returns a map of all C style comments. The key is the line number, the
156      * value is a {@link List} of C style comment {@link TextBlock}s
157      * that start at that line.
158      * @return the map of comments
159      */

160     public Map JavaDoc getCComments()
161     {
162         return Collections.unmodifiableMap(mCComments);
163     }
164
165     /**
166      * Returns the specified C comment as a String array.
167      * @return C comment as a array
168      * @param aStartLineNo the starting line number
169      * @param aStartColNo the starting column number
170      * @param aEndLineNo the ending line number
171      * @param aEndColNo the ending column number
172      **/

173     private String JavaDoc[] extractCComment(int aStartLineNo, int aStartColNo,
174                                      int aEndLineNo, int aEndColNo)
175     {
176         String JavaDoc[] retVal;
177         if (aStartLineNo == aEndLineNo) {
178             retVal = new String JavaDoc[1];
179             retVal[0] = mLines[aStartLineNo - 1].substring(aStartColNo,
180                                                            aEndColNo + 1);
181         }
182         else {
183             retVal = new String JavaDoc[aEndLineNo - aStartLineNo + 1];
184             retVal[0] = mLines[aStartLineNo - 1].substring(aStartColNo);
185             for (int i = aStartLineNo; i < aEndLineNo; i++) {
186                 retVal[i - aStartLineNo + 1] = mLines[i];
187             }
188             retVal[retVal.length - 1] =
189                 mLines[aEndLineNo - 1].substring(0, aEndColNo + 1);
190         }
191         return retVal;
192     }
193
194     /**
195      * Returns the Javadoc comment before the specified line.
196      * A return value of <code>null</code> means there is no such comment.
197      * @return the Javadoc comment, or <code>null</code> if none
198      * @param aLineNo the line number to check before
199      **/

200     public TextBlock getJavadocBefore(int aLineNo)
201     {
202         // Lines start at 1 to the callers perspective, so need to take off 2
203
int lineNo = aLineNo - 2;
204
205         // skip blank lines
206
while ((lineNo > 0) && (lineIsBlank(lineNo) || lineIsComment(lineNo))) {
207             lineNo--;
208         }
209
210         return (TextBlock) mJavadocComments.get(new Integer JavaDoc(lineNo));
211     }
212
213     /** @return the lines in the file */
214     public String JavaDoc[] getLines()
215     {
216         return mLines;
217     }
218
219     /** @return the name of the file */
220     public String JavaDoc getFilename()
221     {
222         return mFilename;
223     }
224
225     /**
226      * Checks if the specified line is blank.
227      * @param aLineNo the line number to check
228      * @return if the specified line consists only of tabs and spaces.
229      **/

230     public boolean lineIsBlank(int aLineNo)
231     {
232         // possible improvement: avoid garbage creation in trim()
233
return "".equals(mLines[aLineNo].trim());
234     }
235
236     /**
237      * Checks if the specified line is a single-line comment without code.
238      * @param aLineNo the line number to check
239      * @return if the specified line consists of only a single line comment
240      * without code.
241      **/

242     public boolean lineIsComment(int aLineNo)
243     {
244         return MATCH_SINGLELINE_COMMENT.matcher(mLines[aLineNo]).matches();
245     }
246
247     /**
248      * Checks if the specified position intersects with a comment.
249      * @param aStartLineNo the starting line number
250      * @param aStartColNo the starting column number
251      * @param aEndLineNo the ending line number
252      * @param aEndColNo the ending column number
253      * @return true if the positions intersects with a comment.
254      **/

255     public boolean hasIntersectionWithComment(
256             int aStartLineNo, int aStartColNo, int aEndLineNo, int aEndColNo)
257     {
258         // Check C comments (all comments should be checked)
259
final Collection JavaDoc values = mCComments.values();
260
261         final Iterator JavaDoc it = values.iterator();
262         while (it.hasNext()) {
263             final List JavaDoc row = (List JavaDoc) it.next();
264             final Iterator JavaDoc rowIterator = row.iterator();
265             while (rowIterator.hasNext()) {
266                 final TextBlock comment = (TextBlock) rowIterator.next();
267                 if (comment.intersects(
268                         aStartLineNo, aStartColNo, aEndLineNo, aEndColNo))
269                 {
270                     return true;
271                 }
272             }
273         }
274
275         // Check CPP comments (line searching is possible)
276
for (int lineNumber = aStartLineNo; lineNumber <= aEndLineNo;
277             lineNumber++)
278         {
279             final TextBlock comment =
280                 (TextBlock) mCPlusPlusComments.get(new Integer JavaDoc(lineNumber));
281             if ((comment != null)
282                 && comment.intersects(aStartLineNo, aStartColNo,
283                                       aEndLineNo, aEndColNo))
284             {
285                 return true;
286             }
287         }
288         return false;
289     }
290
291 }
292
Popular Tags