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