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     @Nullable
398     @Override
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 }