1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.puppycrawl.tools.checkstyle.api;
20
21 import com.google.common.collect.ImmutableMap;
22
23 import com.google.common.collect.Lists;
24 import com.google.common.collect.Maps;
25 import com.puppycrawl.tools.checkstyle.grammars.CommentListener;
26 import java.io.File;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.regex.Pattern;
32
33
34
35
36
37
38
39 public final class FileContents implements CommentListener
40 {
41
42
43
44
45 private static final String MATCH_SINGLELINE_COMMENT_PAT = "^\\s*//.*$";
46
47 private static final Pattern MATCH_SINGLELINE_COMMENT = Pattern
48 .compile(MATCH_SINGLELINE_COMMENT_PAT);
49
50
51 private final String filename;
52
53
54 private final FileText text;
55
56
57
58
59 private final Map<Integer, TextBlock> javadocComments = Maps.newHashMap();
60
61 private final Map<Integer, TextBlock> cppComments =
62 Maps.newHashMap();
63
64
65
66
67
68 private final Map<Integer, List<TextBlock>> clangComments = Maps.newHashMap();
69
70
71
72
73
74
75
76
77
78 @Deprecated public FileContents(String filename, String[] lines)
79 {
80 this.filename = filename;
81 text = FileText.fromLines(new File(filename), Arrays.asList(lines));
82 }
83
84
85
86
87
88
89 public FileContents(FileText text)
90 {
91 filename = text.getFile().toString();
92 this.text = text;
93 }
94
95
96 @Override
97 public void reportSingleLineComment(String type, int startLineNo,
98 int startColNo)
99 {
100 reportCppComment(startLineNo, startColNo);
101 }
102
103
104 @Override
105 public void reportBlockComment(String type, int startLineNo,
106 int startColNo, int endLineNo, int endColNo)
107 {
108 reportCComment(startLineNo, startColNo, endLineNo, endColNo);
109 }
110
111
112
113
114
115
116 public void reportCppComment(int startLineNo, int startColNo)
117 {
118 final String line = line(startLineNo - 1);
119 final String[] txt = new String[] {line.substring(startColNo)};
120 final Comment comment = new Comment(txt, startColNo, startLineNo,
121 line.length() - 1);
122 cppComments.put(startLineNo, comment);
123 }
124
125
126
127
128
129
130 public ImmutableMap<Integer, TextBlock> getCppComments()
131 {
132 return ImmutableMap.copyOf(cppComments);
133 }
134
135
136
137
138
139
140
141
142 public void reportCComment(int startLineNo, int startColNo,
143 int endLineNo, int endColNo)
144 {
145 final String[] cc = extractCComment(startLineNo, startColNo,
146 endLineNo, endColNo);
147 final Comment comment = new Comment(cc, startColNo, endLineNo,
148 endColNo);
149
150
151 if (clangComments.containsKey(startLineNo)) {
152 final List<TextBlock> entries = clangComments.get(startLineNo);
153 entries.add(comment);
154 }
155 else {
156 final List<TextBlock> entries = Lists.newArrayList();
157 entries.add(comment);
158 clangComments.put(startLineNo, entries);
159 }
160
161
162 if (line(startLineNo - 1).indexOf("/**", startColNo) != -1) {
163 javadocComments.put(endLineNo - 1, comment);
164 }
165 }
166
167
168
169
170
171
172
173 public ImmutableMap<Integer, List<TextBlock>> getCComments()
174 {
175 return ImmutableMap.copyOf(clangComments);
176 }
177
178
179
180
181
182
183
184
185
186 private String[] extractCComment(int startLineNo, int startColNo,
187 int endLineNo, int endColNo)
188 {
189 String[] retVal;
190 if (startLineNo == endLineNo) {
191 retVal = new String[1];
192 retVal[0] = line(startLineNo - 1).substring(startColNo,
193 endColNo + 1);
194 }
195 else {
196 retVal = new String[endLineNo - startLineNo + 1];
197 retVal[0] = line(startLineNo - 1).substring(startColNo);
198 for (int i = startLineNo; i < endLineNo; i++) {
199 retVal[i - startLineNo + 1] = line(i);
200 }
201 retVal[retVal.length - 1] = line(endLineNo - 1).substring(0,
202 endColNo + 1);
203 }
204 return retVal;
205 }
206
207
208
209
210
211
212
213 public TextBlock getJavadocBefore(int lineNoBefore)
214 {
215
216 int lineNo = lineNoBefore - 2;
217
218
219 while ((lineNo > 0) && (lineIsBlank(lineNo) || lineIsComment(lineNo))) {
220 lineNo--;
221 }
222
223 return javadocComments.get(lineNo);
224 }
225
226
227
228
229
230
231
232
233
234 private String line(int lineNo)
235 {
236 return text.get(lineNo);
237 }
238
239
240
241
242
243 public FileText getText()
244 {
245 return text;
246 }
247
248
249 public String[] getLines()
250 {
251 return text.toLinesArray();
252 }
253
254
255
256
257
258
259 public String getLine(int index)
260 {
261 return text.get(index);
262 }
263
264
265 public String getFilename()
266 {
267 return filename;
268 }
269
270
271
272
273
274
275 public boolean lineIsBlank(int lineNo)
276 {
277
278 return "".equals(line(lineNo).trim());
279 }
280
281
282
283
284
285
286
287 public boolean lineIsComment(int lineNo)
288 {
289 return MATCH_SINGLELINE_COMMENT.matcher(line(lineNo)).matches();
290 }
291
292
293
294
295
296
297
298
299
300 public boolean hasIntersectionWithComment(int startLineNo,
301 int startColNo, int endLineNo, int endColNo)
302 {
303
304 final Collection<List<TextBlock>> values = clangComments.values();
305 for (final List<TextBlock> row : values) {
306 for (final TextBlock comment : row) {
307 if (comment.intersects(startLineNo, startColNo, endLineNo,
308 endColNo))
309 {
310 return true;
311 }
312 }
313 }
314
315
316 for (int lineNumber = startLineNo; lineNumber <= endLineNo;
317 lineNumber++)
318 {
319 final TextBlock comment = cppComments.get(lineNumber);
320 if ((comment != null)
321 && comment.intersects(startLineNo, startColNo,
322 endLineNo, endColNo))
323 {
324 return true;
325 }
326 }
327 return false;
328 }
329
330
331
332
333
334 public boolean inPackageInfo()
335 {
336 return this.getFilename().endsWith("package-info.java");
337 }
338 }