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.BitSet;
23
24 import antlr.CommonASTWithHiddenTokens;
25 import antlr.Token;
26 import antlr.collections.AST;
27 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
28
29
30
31
32
33
34
35 public final class DetailAST extends CommonASTWithHiddenTokens {
36
37 private static final long serialVersionUID = -2580884815577559874L;
38
39
40 private static final int NOT_INITIALIZED = Integer.MIN_VALUE;
41
42
43 private int lineNo = NOT_INITIALIZED;
44
45 private int columnNo = NOT_INITIALIZED;
46
47
48 private int childCount = NOT_INITIALIZED;
49
50 private DetailAST parent;
51
52 private DetailAST previousSibling;
53
54
55
56
57
58
59 private BitSet branchTokenTypes;
60
61 @Override
62 public void initialize(Token tok) {
63 super.initialize(tok);
64 lineNo = tok.getLine();
65
66
67 columnNo = tok.getColumn() - 1;
68 }
69
70 @Override
71 public void initialize(AST ast) {
72 final DetailAST detailAst = (DetailAST) ast;
73 setText(detailAst.getText());
74 setType(detailAst.getType());
75 lineNo = detailAst.getLineNo();
76 columnNo = detailAst.getColumnNo();
77 hiddenAfter = detailAst.getHiddenAfter();
78 hiddenBefore = detailAst.getHiddenBefore();
79 }
80
81 @Override
82 public void setFirstChild(AST ast) {
83 clearBranchTokenTypes();
84 clearChildCountCache(this);
85 super.setFirstChild(ast);
86 if (ast != null) {
87 ((DetailAST) ast).setParent(this);
88 }
89 }
90
91 @Override
92 public void setNextSibling(AST ast) {
93 clearBranchTokenTypes();
94 clearChildCountCache(parent);
95 super.setNextSibling(ast);
96 if (ast != null && parent != null) {
97 ((DetailAST) ast).setParent(parent);
98 }
99 if (ast != null) {
100 ((DetailAST) ast).previousSibling = this;
101 }
102 }
103
104
105
106
107
108
109 public void addPreviousSibling(DetailAST ast) {
110 clearBranchTokenTypes();
111 clearChildCountCache(parent);
112 if (ast != null) {
113
114 final DetailAST previousSiblingNode = previousSibling;
115
116 if (previousSiblingNode != null) {
117 ast.previousSibling = previousSiblingNode;
118 previousSiblingNode.setNextSibling(ast);
119 }
120 else if (parent != null) {
121 parent.setFirstChild(ast);
122 }
123
124 ast.setNextSibling(this);
125 previousSibling = ast;
126 }
127 }
128
129
130
131
132
133
134 public void addNextSibling(DetailAST ast) {
135 clearBranchTokenTypes();
136 clearChildCountCache(parent);
137 if (ast != null) {
138
139 final DetailAST nextSibling = getNextSibling();
140
141 if (nextSibling != null) {
142 ast.setNextSibling(nextSibling);
143 nextSibling.previousSibling = ast;
144 }
145
146 ast.previousSibling = this;
147 setNextSibling(ast);
148 }
149 }
150
151 @Override
152 public void addChild(AST ast) {
153 clearBranchTokenTypes();
154 clearChildCountCache(this);
155 if (ast != null) {
156 ((DetailAST) ast).setParent(this);
157 ((DetailAST) ast).previousSibling = getLastChild();
158 }
159 super.addChild(ast);
160 }
161
162
163
164
165
166
167 public int getChildCount() {
168
169 if (childCount == NOT_INITIALIZED) {
170 childCount = 0;
171 AST child = getFirstChild();
172
173 while (child != null) {
174 childCount += 1;
175 child = child.getNextSibling();
176 }
177 }
178 return childCount;
179 }
180
181
182
183
184
185
186 public int getChildCount(int type) {
187 int count = 0;
188 for (AST ast = getFirstChild(); ast != null; ast = ast.getNextSibling()) {
189 if (ast.getType() == type) {
190 count++;
191 }
192 }
193 return count;
194 }
195
196
197
198
199
200 private void setParent(DetailAST parent) {
201 DetailAST instance = this;
202 do {
203 instance.clearBranchTokenTypes();
204 instance.parent = parent;
205 instance = instance.getNextSibling();
206 } while (instance != null);
207 }
208
209
210
211
212
213 public DetailAST getParent() {
214 return parent;
215 }
216
217
218
219
220
221 public int getLineNo() {
222 int resultNo = -1;
223
224 if (lineNo == NOT_INITIALIZED) {
225
226
227 resultNo = findLineNo(getFirstChild());
228
229 if (resultNo == -1) {
230 resultNo = findLineNo(getNextSibling());
231 }
232 }
233 if (resultNo == -1) {
234 resultNo = lineNo;
235 }
236 return resultNo;
237 }
238
239
240
241
242
243
244 public void setLineNo(int lineNo) {
245 this.lineNo = lineNo;
246 }
247
248
249
250
251
252 public int getColumnNo() {
253 int resultNo = -1;
254
255 if (columnNo == NOT_INITIALIZED) {
256
257
258 resultNo = findColumnNo(getFirstChild());
259
260 if (resultNo == -1) {
261 resultNo = findColumnNo(getNextSibling());
262 }
263 }
264 if (resultNo == -1) {
265 resultNo = columnNo;
266 }
267 return resultNo;
268 }
269
270
271
272
273
274
275 public void setColumnNo(int columnNo) {
276 this.columnNo = columnNo;
277 }
278
279
280
281
282
283 public DetailAST getLastChild() {
284 DetailAST ast = getFirstChild();
285 while (ast != null && ast.getNextSibling() != null) {
286 ast = ast.getNextSibling();
287 }
288 return ast;
289 }
290
291
292
293
294
295
296
297 private static int findColumnNo(DetailAST ast) {
298 int resultNo = -1;
299 DetailAST node = ast;
300 while (node != null) {
301
302 if (TokenUtil.isCommentType(node.getType())) {
303 node = node.getNextSibling();
304 }
305 else {
306 resultNo = node.getColumnNo();
307 break;
308 }
309 }
310 return resultNo;
311 }
312
313
314
315
316
317
318
319 private static int findLineNo(DetailAST ast) {
320 int resultNo = -1;
321 DetailAST node = ast;
322 while (node != null) {
323
324 if (TokenUtil.isCommentType(node.getType())) {
325 node = node.getNextSibling();
326 }
327 else {
328 resultNo = node.getLineNo();
329 break;
330 }
331 }
332 return resultNo;
333 }
334
335
336
337
338
339 private BitSet getBranchTokenTypes() {
340
341 if (branchTokenTypes == null) {
342 branchTokenTypes = new BitSet();
343 branchTokenTypes.set(getType());
344
345
346 DetailAST child = getFirstChild();
347 while (child != null) {
348 final BitSet childTypes = child.getBranchTokenTypes();
349 branchTokenTypes.or(childTypes);
350
351 child = child.getNextSibling();
352 }
353 }
354 return branchTokenTypes;
355 }
356
357
358
359
360
361
362
363
364 public boolean branchContains(int type) {
365 return getBranchTokenTypes().get(type);
366 }
367
368
369
370
371
372 public DetailAST getPreviousSibling() {
373 return previousSibling;
374 }
375
376
377
378
379
380
381 public DetailAST findFirstToken(int type) {
382 DetailAST returnValue = null;
383 for (DetailAST ast = getFirstChild(); ast != null; ast = ast.getNextSibling()) {
384 if (ast.getType() == type) {
385 returnValue = ast;
386 break;
387 }
388 }
389 return returnValue;
390 }
391
392 @Override
393 public String toString() {
394 return super.toString() + "[" + getLineNo() + "x" + getColumnNo() + "]";
395 }
396
397 @Override
398 public DetailAST getNextSibling() {
399 return (DetailAST) super.getNextSibling();
400 }
401
402 @Override
403 public DetailAST getFirstChild() {
404 return (DetailAST) super.getFirstChild();
405 }
406
407
408
409
410
411 private static void clearChildCountCache(DetailAST ast) {
412 if (ast != null) {
413 ast.childCount = NOT_INITIALIZED;
414 }
415 }
416
417
418
419
420
421 private void clearBranchTokenTypes() {
422 DetailAST prevParent = parent;
423 while (prevParent != null) {
424 prevParent.branchTokenTypes = null;
425 prevParent = prevParent.parent;
426 }
427 }
428
429 }