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;
21
22 import java.util.BitSet;
23 import java.util.List;
24
25 import org.antlr.v4.runtime.Token;
26
27 import com.puppycrawl.tools.checkstyle.api.DetailAST;
28 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
29 import com.puppycrawl.tools.checkstyle.utils.UnmodifiableCollectionUtil;
30
31
32
33
34
35
36
37
38
39 public final class DetailAstImpl implements DetailAST {
40
41
42 private static final int NOT_INITIALIZED = Integer.MIN_VALUE;
43
44
45 private int lineNo = NOT_INITIALIZED;
46
47 private int columnNo = NOT_INITIALIZED;
48
49
50 private int childCount;
51
52 private DetailAstImpl parent;
53
54 private DetailAstImpl previousSibling;
55
56
57 private DetailAstImpl firstChild;
58
59
60 private DetailAstImpl nextSibling;
61
62
63 private String text;
64
65
66 private int type;
67
68
69
70
71
72 private List<Token> hiddenBefore;
73
74
75
76
77
78 private List<Token> hiddenAfter;
79
80
81
82
83
84
85 private BitSet branchTokenTypes;
86
87
88
89
90
91
92
93 public void initialize(int tokenType, String tokenText) {
94 type = tokenType;
95 text = tokenText;
96 }
97
98
99
100
101
102
103 public void initialize(Token token) {
104 text = token.getText();
105 type = token.getType();
106 lineNo = token.getLine();
107 columnNo = token.getCharPositionInLine();
108 }
109
110
111
112
113
114
115
116 public void addPreviousSibling(DetailAST ast) {
117 clearBranchTokenTypes();
118 clearChildCountCache(parent);
119 if (ast != null) {
120
121 final DetailAstImpl previousSiblingNode = previousSibling;
122 final DetailAstImpl astImpl = (DetailAstImpl) ast;
123
124 if (previousSiblingNode != null) {
125 previousSiblingNode.setNextSibling(astImpl);
126 }
127 else if (parent != null) {
128 parent.setFirstChild(astImpl);
129 }
130
131 astImpl.setNextSibling(this);
132 }
133 }
134
135
136
137
138
139
140 public void addNextSibling(DetailAST ast) {
141 clearBranchTokenTypes();
142 clearChildCountCache(parent);
143 if (ast != null) {
144
145 final DetailAstImpl sibling = nextSibling;
146 final DetailAstImpl astImpl = (DetailAstImpl) ast;
147 astImpl.setNextSibling(sibling);
148
149 setNextSibling(astImpl);
150 }
151 }
152
153
154
155
156
157
158 public void addChild(DetailAST child) {
159 clearBranchTokenTypes();
160 clearChildCountCache(this);
161 if (child != null) {
162 final DetailAstImpl astImpl = (DetailAstImpl) child;
163 astImpl.setParent(this);
164 }
165 DetailAST temp = firstChild;
166 if (temp == null) {
167 firstChild = (DetailAstImpl) child;
168 }
169 else {
170 while (temp.getNextSibling() != null) {
171 temp = temp.getNextSibling();
172 }
173
174 ((DetailAstImpl) temp).setNextSibling(child);
175 }
176 }
177
178 @Override
179 public int getChildCount() {
180
181 if (childCount == NOT_INITIALIZED) {
182 childCount = 0;
183 DetailAST child = firstChild;
184
185 while (child != null) {
186 childCount += 1;
187 child = child.getNextSibling();
188 }
189 }
190 return childCount;
191 }
192
193 @Override
194 public int getChildCount(int tokenType) {
195 int count = 0;
196 for (DetailAST ast = firstChild; ast != null; ast = ast.getNextSibling()) {
197 if (ast.getType() == tokenType) {
198 count++;
199 }
200 }
201 return count;
202 }
203
204
205
206
207
208
209 private void setParent(DetailAstImpl parent) {
210 DetailAstImpl instance = this;
211 do {
212 instance.clearBranchTokenTypes();
213 instance.parent = parent;
214 instance = instance.nextSibling;
215 } while (instance != null);
216 }
217
218 @Override
219 public DetailAST getParent() {
220 return parent;
221 }
222
223 @Override
224 public String getText() {
225 return text;
226 }
227
228
229
230
231
232
233 public void setText(String text) {
234 this.text = text;
235 }
236
237 @Override
238 public int getType() {
239 return type;
240 }
241
242
243
244
245
246
247 public void setType(int type) {
248 this.type = type;
249 }
250
251 @Override
252 public int getLineNo() {
253 int resultNo = -1;
254
255 if (lineNo == NOT_INITIALIZED) {
256
257
258 resultNo = findLineNo(firstChild);
259
260 if (resultNo == -1) {
261 resultNo = findLineNo(nextSibling);
262 }
263 }
264 if (resultNo == -1) {
265 resultNo = lineNo;
266 }
267 return resultNo;
268 }
269
270
271
272
273
274
275
276 public void setLineNo(int lineNo) {
277 this.lineNo = lineNo;
278 }
279
280 @Override
281 public int getColumnNo() {
282 int resultNo = -1;
283
284 if (columnNo == NOT_INITIALIZED) {
285
286
287 resultNo = findColumnNo(firstChild);
288
289 if (resultNo == -1) {
290 resultNo = findColumnNo(nextSibling);
291 }
292 }
293 if (resultNo == -1) {
294 resultNo = columnNo;
295 }
296 return resultNo;
297 }
298
299
300
301
302
303
304
305 public void setColumnNo(int columnNo) {
306 this.columnNo = columnNo;
307 }
308
309 @Override
310 public DetailAST getLastChild() {
311 DetailAstImpl ast = firstChild;
312 while (ast != null && ast.nextSibling != null) {
313 ast = ast.nextSibling;
314 }
315 return ast;
316 }
317
318
319
320
321
322
323
324 private static int findColumnNo(DetailAST ast) {
325 int resultNo = -1;
326 DetailAST node = ast;
327 while (node != null) {
328
329 if (TokenUtil.isCommentType(node.getType())) {
330 node = node.getNextSibling();
331 }
332 else {
333 resultNo = node.getColumnNo();
334 break;
335 }
336 }
337 return resultNo;
338 }
339
340
341
342
343
344
345
346 private static int findLineNo(DetailAST ast) {
347 int resultNo = -1;
348 DetailAST node = ast;
349 while (node != null) {
350
351 if (TokenUtil.isCommentType(node.getType())) {
352 node = node.getNextSibling();
353 }
354 else {
355 resultNo = node.getLineNo();
356 break;
357 }
358 }
359 return resultNo;
360 }
361
362
363
364
365
366
367 private BitSet getBranchTokenTypes() {
368
369 if (branchTokenTypes == null) {
370 branchTokenTypes = new BitSet();
371 branchTokenTypes.set(type);
372
373
374 DetailAstImpl child = firstChild;
375 while (child != null) {
376 final BitSet childTypes = child.getBranchTokenTypes();
377 branchTokenTypes.or(childTypes);
378
379 child = child.nextSibling;
380 }
381 }
382 return branchTokenTypes;
383 }
384
385 @Override
386 public boolean branchContains(int tokenType) {
387 return getBranchTokenTypes().get(tokenType);
388 }
389
390 @Override
391 public DetailAST getPreviousSibling() {
392 return previousSibling;
393 }
394
395 @Override
396 public DetailAST findFirstToken(int tokenType) {
397 DetailAST returnValue = null;
398 for (DetailAST ast = firstChild; ast != null; ast = ast.getNextSibling()) {
399 if (ast.getType() == tokenType) {
400 returnValue = ast;
401 break;
402 }
403 }
404 return returnValue;
405 }
406
407 @Override
408 public String toString() {
409 return text + "[" + getLineNo() + "x" + getColumnNo() + "]";
410 }
411
412 @Override
413 public DetailAstImpl getNextSibling() {
414 return nextSibling;
415 }
416
417 @Override
418 public DetailAstImpl getFirstChild() {
419 return firstChild;
420 }
421
422 @Override
423 public int getNumberOfChildren() {
424 return getChildCount();
425 }
426
427 @Override
428 public boolean hasChildren() {
429 return firstChild != null;
430 }
431
432
433
434
435
436
437 private static void clearChildCountCache(DetailAstImpl ast) {
438 if (ast != null) {
439 ast.childCount = NOT_INITIALIZED;
440 }
441 }
442
443
444
445
446
447 private void clearBranchTokenTypes() {
448 DetailAstImpl prevParent = parent;
449 while (prevParent != null) {
450 prevParent.branchTokenTypes = null;
451 prevParent = prevParent.parent;
452 }
453 }
454
455
456
457
458
459
460 public void setNextSibling(DetailAST nextSibling) {
461 clearBranchTokenTypes();
462 clearChildCountCache(parent);
463 this.nextSibling = (DetailAstImpl) nextSibling;
464 if (nextSibling != null && parent != null) {
465 ((DetailAstImpl) nextSibling).setParent(parent);
466 }
467 if (nextSibling != null) {
468 ((DetailAstImpl) nextSibling).previousSibling = this;
469 }
470 }
471
472
473
474
475
476
477 public void setFirstChild(DetailAST firstChild) {
478 clearBranchTokenTypes();
479 clearChildCountCache(this);
480 this.firstChild = (DetailAstImpl) firstChild;
481 if (firstChild != null) {
482 ((DetailAstImpl) firstChild).setParent(this);
483 }
484 }
485
486
487
488
489 public void removeChildren() {
490 firstChild = null;
491 }
492
493
494
495
496
497
498
499 public List<Token> getHiddenBefore() {
500 List<Token> returnList = null;
501 if (hiddenBefore != null) {
502 returnList = UnmodifiableCollectionUtil.unmodifiableList(hiddenBefore);
503 }
504 return returnList;
505 }
506
507
508
509
510
511
512
513 public List<Token> getHiddenAfter() {
514 List<Token> returnList = null;
515 if (hiddenAfter != null) {
516 returnList = UnmodifiableCollectionUtil.unmodifiableList(hiddenAfter);
517 }
518 return returnList;
519 }
520
521
522
523
524
525
526 public void setHiddenBefore(List<Token> hiddenBefore) {
527 this.hiddenBefore = UnmodifiableCollectionUtil.unmodifiableList(hiddenBefore);
528 }
529
530
531
532
533
534
535 public void setHiddenAfter(List<Token> hiddenAfter) {
536 this.hiddenAfter = UnmodifiableCollectionUtil.unmodifiableList(hiddenAfter);
537 }
538 }