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