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