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