Source code: com/puppycrawl/tools/checkstyle/api/FileContents.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 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 org.apache.regexp.RE;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.HashMap;
28
29 /**
30 * Represents the contents of a file.
31 *
32 * @author Oliver Burn
33 * @version 1.0
34 */
35 public final class FileContents
36 {
37 /**
38 * the pattern to match a single line comment containing only the comment
39 * itself -- no code.
40 */
41 private static final String MATCH_SINGLELINE_COMMENT_PAT =
42 "^\\s*//.*$";
43 /** compiled regexp to match a single-line comment line */
44 private static final RE MATCH_SINGLELINE_COMMENT =
45 Utils.createRE(MATCH_SINGLELINE_COMMENT_PAT);
46
47 /** the file name */
48 private final String mFilename;
49
50 /** the lines */
51 private final String[] mLines;
52
53 /** map of the Javadoc comments indexed on the last line of the comment.
54 * The hack is it assumes that there is only one Javadoc comment per line.
55 */
56 private final Map mJavadocComments = new HashMap();
57
58 /** map of the C++ comments indexed on the first line of the comment. */
59 private final Map mCPlusPlusComments = new HashMap();
60 /**
61 * map of the C comments indexed on the first line of the comment to a
62 * list of comments on that line
63 */
64 private final Map mCComments = new HashMap();
65
66 /**
67 * Creates a new <code>FileContents</code> instance.
68 *
69 * @param aFilename name of the file
70 * @param aLines the contents of the file
71 */
72 public FileContents(String aFilename, String[] aLines)
73 {
74 mFilename = aFilename;
75 mLines = aLines;
76 }
77
78 /**
79 * Report the location of a C++ style comment.
80 * @param aStartLineNo the starting line number
81 * @param aStartColNo the starting column number
82 **/
83 public void reportCppComment(int aStartLineNo, int aStartColNo)
84 {
85 final String cmt = mLines[aStartLineNo - 1].substring(aStartColNo);
86 mCPlusPlusComments.put(new Integer(aStartLineNo), cmt);
87 }
88
89 /**
90 * Returns a map of all the C++ style comments. The key is a line number,
91 * the value is the comment at the line.
92 * @return the Map of comments
93 */
94 public Map getCppComments()
95 {
96 return Collections.unmodifiableMap(mCPlusPlusComments);
97 }
98
99 /**
100 * Report the location of a C-style comment.
101 * @param aStartLineNo the starting line number
102 * @param aStartColNo the starting column number
103 * @param aEndLineNo the ending line number
104 * @param aEndColNo the ending column number
105 **/
106 public void reportCComment(int aStartLineNo, int aStartColNo,
107 int aEndLineNo, int aEndColNo)
108 {
109 final String[] cc = extractCComment(aStartLineNo, aStartColNo,
110 aEndLineNo, aEndColNo);
111
112 // save the comment
113 final Integer key = new Integer(aStartLineNo);
114 if (mCComments.containsKey(key)) {
115 final List entries = (List) mCComments.get(key);
116 entries.add(cc);
117 }
118 else {
119 final List entries = new ArrayList();
120 entries.add(cc);
121 mCComments.put(key, entries);
122 }
123
124 // Remember if possible Javadoc comment
125 if (mLines[aStartLineNo - 1].indexOf("/**", aStartColNo) != -1) {
126 mJavadocComments.put(new Integer(aEndLineNo - 1), cc);
127 }
128 }
129
130 /**
131 * Returns a map of all C style comments. The key is the line number, the
132 * value is a list of C style comments at the line.
133 * @return the map of comments
134 */
135 public Map getCComments()
136 {
137 return Collections.unmodifiableMap(mCComments);
138 }
139
140 /**
141 * Returns the specified C comment as a String array.
142 * @return C comment as a array
143 * @param aStartLineNo the starting line number
144 * @param aStartColNo the starting column number
145 * @param aEndLineNo the ending line number
146 * @param aEndColNo the ending column number
147 **/
148 private String[] extractCComment(int aStartLineNo, int aStartColNo,
149 int aEndLineNo, int aEndColNo)
150 {
151 String[] retVal;
152 if (aStartLineNo == aEndLineNo) {
153 retVal = new String[1];
154 retVal[0] = mLines[aStartLineNo - 1].substring(aStartColNo,
155 aEndColNo + 1);
156 }
157 else {
158 retVal = new String[aEndLineNo - aStartLineNo + 1];
159 retVal[0] = mLines[aStartLineNo - 1].substring(aStartColNo);
160 for (int i = aStartLineNo; i < aEndLineNo; i++) {
161 retVal[i - aStartLineNo + 1] = mLines[i];
162 }
163 retVal[retVal.length - 1] =
164 mLines[aEndLineNo - 1].substring(0, aEndColNo + 1);
165 }
166 return retVal;
167 }
168
169 /**
170 * Returns the Javadoc comment before the specified line.
171 * A return value of <code>null</code> means there is no such comment.
172 * @return the Javadoc comment, or <code>null</code> if none
173 * @param aLineNo the line number to check before
174 **/
175 public String[] getJavadocBefore(int aLineNo)
176 {
177 // Lines start at 1 to the callers perspective, so need to take off 2
178 int lineNo = aLineNo - 2;
179
180 // skip blank lines
181 while ((lineNo > 0) && (lineIsBlank(lineNo) || lineIsComment(lineNo))) {
182 lineNo--;
183 }
184
185 return (String[]) mJavadocComments.get(new Integer(lineNo));
186 }
187
188 /** @return the lines in the file */
189 public String[] getLines()
190 {
191 return mLines;
192 }
193
194 /** @return the name of the file */
195 public String getFilename()
196 {
197 return mFilename;
198 }
199
200 /**
201 * Checks if the specified line is blank.
202 * @param aLineNo the line number to check
203 * @return if the specified line consists only of tabs and spaces.
204 **/
205 public boolean lineIsBlank(int aLineNo)
206 {
207 // possible improvement: avoid garbage creation in trim()
208 return "".equals(mLines[aLineNo].trim());
209 }
210
211 /**
212 * Checks if the specified line is a single-line comment without code.
213 * @param aLineNo the line number to check
214 * @return if the specified line consists of only a single line comment
215 * without code.
216 **/
217 public boolean lineIsComment(int aLineNo)
218 {
219 return MATCH_SINGLELINE_COMMENT.match(mLines[aLineNo]);
220 }
221
222 }