Source code: com/puppycrawl/tools/checkstyle/api/DetailAST.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 Oliver Burn
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ////////////////////////////////////////////////////////////////////////////////
19 package com.puppycrawl.tools.checkstyle.api;
20
21 import java.util.BitSet;
22
23 import antlr.CommonAST;
24 import antlr.Token;
25 import antlr.collections.AST;
26
27 /**
28 * An extension of the CommonAST that records the line and column
29 * number. The idea was taken from <a target="_top"
30 * href="http://www.jguru.com/jguru/faq/view.jsp?EID=62654">Java Guru
31 * FAQ: How can I include line numbers in automatically generated
32 * ASTs?</a>.
33 * @author Oliver Burn
34 * @author lkuehne
35 * @version 1.0
36 * @see <a target="_top" href="http://www.antlr.org/">ANTLR Website</a>
37 */
38 public final class DetailAST
39 extends CommonAST
40 {
41 /** constant to indicate if not calculated the child count */
42 private static final int NOT_INITIALIZED = Integer.MIN_VALUE;
43
44 /** the line number **/
45 private int mLineNo = NOT_INITIALIZED;
46 /** the column number **/
47 private int mColumnNo = NOT_INITIALIZED;
48
49 /** number of children */
50 private int mChildCount = NOT_INITIALIZED;
51 /** the parent token */
52 private DetailAST mParent;
53
54 /**
55 * All token types in this branch.
56 * Token 'x' (where x is an int) is in this branch
57 * if mBranchTokenTypes.get(x) is true.
58 */
59 private BitSet mBranchTokenTypes;
60
61 /** @see antlr.CommonAST **/
62 public void initialize(Token aTok)
63 {
64 super.initialize(aTok);
65 mLineNo = aTok.getLine();
66 mColumnNo = aTok.getColumn() - 1; // expect columns to start @ 0
67 }
68
69 /** @see antlr.CommonAST **/
70 public void initialize(AST aAST)
71 {
72 final DetailAST da = (DetailAST) aAST;
73 setText(da.getText());
74 setType(da.getType());
75 mLineNo = da.getLineNo();
76 mColumnNo = da.getColumnNo();
77 }
78
79 /**
80 * Sets this AST's first Child.
81 * @param aAST the new first child
82 */
83 public void setFirstChild(AST aAST)
84 {
85 mChildCount = NOT_INITIALIZED;
86 super.setFirstChild(aAST);
87 if (aAST != null) {
88 ((DetailAST) aAST).setParent(this);
89 }
90 }
91
92 /**
93 * Sets AST's next sibling.
94 * @param aAST the new next sibling
95 */
96 public void setNextSibling(AST aAST)
97 {
98 super.setNextSibling(aAST);
99 if (aAST != null && mParent != null) {
100 ((DetailAST) aAST).setParent(mParent);
101 }
102 }
103
104 /**
105 * Adds new child to AST.
106 * @param aAST the new child
107 */
108 public void addChild(AST aAST)
109 {
110 super.addChild(aAST);
111 if (aAST != null) {
112 ((DetailAST) aAST).setParent(this);
113 }
114 }
115
116 /**
117 * Returns the number of child nodes one level below this node. That is is
118 * does not recurse down the tree.
119 * @return the number of child nodes
120 */
121 public int getChildCount()
122 {
123 // lazy init
124 if (mChildCount == NOT_INITIALIZED) {
125 mChildCount = 0;
126 AST child = getFirstChild();
127
128 while (child != null) {
129 mChildCount += 1;
130 child = child.getNextSibling();
131 }
132 }
133 return mChildCount;
134 }
135
136 /**
137 * Set the parent token.
138 * @param aParent the parent token
139 */
140 // TODO: should be private but that breaks the DetailASTTest
141 // until we manage parent in DetailAST instead of externally
142 void setParent(DetailAST aParent)
143 {
144 // TODO: Check visibility, could be private
145 // if set in setFirstChild() and friends
146 mParent = aParent;
147 DetailAST nextSibling = (DetailAST) getNextSibling();
148 if (nextSibling != null) {
149 nextSibling.setParent(aParent);
150 }
151 }
152
153 /**
154 * Returns the parent token.
155 * @return the parent token
156 */
157 public DetailAST getParent()
158 {
159 return mParent;
160 }
161
162 /** @return the line number **/
163 public int getLineNo()
164 {
165 if (mLineNo == NOT_INITIALIZED) {
166 // an inner AST that has been initialized
167 // with initialize(String text)
168 final DetailAST child = (DetailAST) getFirstChild();
169 final DetailAST sibling = (DetailAST) getNextSibling();
170 if (child != null) {
171 return child.getLineNo();
172 }
173 else if (sibling != null) {
174 return sibling.getLineNo();
175 }
176 }
177 return mLineNo;
178 }
179
180 /** @return the column number **/
181 public int getColumnNo()
182 {
183 if (mColumnNo == NOT_INITIALIZED) {
184 // an inner AST that has been initialized
185 // with initialize(String text)
186 final DetailAST child = (DetailAST) getFirstChild();
187 final DetailAST sibling = (DetailAST) getNextSibling();
188 if (child != null) {
189 return child.getColumnNo();
190 }
191 else if (sibling != null) {
192 return sibling.getColumnNo();
193 }
194 }
195 return mColumnNo;
196 }
197
198 /** @return the last child node */
199 public DetailAST getLastChild()
200 {
201 AST ast = getFirstChild();
202 while ((ast != null) && (ast.getNextSibling() != null)) {
203 ast = ast.getNextSibling();
204 }
205 return (DetailAST) ast;
206 }
207
208 /**
209 * @return the token types that occur in the branch as a sorted set.
210 */
211 private BitSet getBranchTokenTypes()
212 {
213 // lazy init
214 if (mBranchTokenTypes == null) {
215
216 mBranchTokenTypes = new BitSet();
217 mBranchTokenTypes.set(getType());
218
219 // add union of all childs
220 DetailAST child = (DetailAST) getFirstChild();
221 while (child != null) {
222 final BitSet childTypes = child.getBranchTokenTypes();
223 mBranchTokenTypes.or(childTypes);
224
225 child = (DetailAST) child.getNextSibling();
226 }
227 }
228 return mBranchTokenTypes;
229 }
230
231 /**
232 * Checks if this branch of the parse tree contains a token
233 * of the provided type.
234 * @param aType a TokenType
235 * @return true if and only if this branch (including this node)
236 * contains a token of type <code>aType</code>.
237 */
238 public boolean branchContains(int aType)
239 {
240 return getBranchTokenTypes().get(aType);
241 }
242
243 /**
244 * Returns the number of direct child tokens that have the specified type.
245 * @param aType the token type to match
246 * @return the number of matching token
247 */
248 public int getChildCount(int aType)
249 {
250 int count = 0;
251 for (AST i = getFirstChild(); i != null; i = i.getNextSibling()) {
252 if (i.getType() == aType) {
253 count++;
254 }
255 }
256 return count;
257 }
258
259 /**
260 * Returns the previous sibling or null if no such sibling exists.
261 * @return the previous sibling or null if no such sibling exists.
262 */
263 public DetailAST getPreviousSibling()
264 {
265 final DetailAST parent = getParent();
266 if (parent == null) {
267 return null;
268 }
269
270 AST ast = parent.getFirstChild();
271 while (ast != null) {
272 AST nextSibling = ast.getNextSibling();
273 if (this == nextSibling) {
274 return (DetailAST) ast;
275 }
276 ast = nextSibling;
277 }
278 return null;
279 }
280
281 /**
282 * Returns the first child token that makes a specified type.
283 * @param aType the token type to match
284 * @return the matching token, or null if no match
285 */
286 public DetailAST findFirstToken(int aType)
287 {
288 DetailAST retVal = null;
289 for (AST i = getFirstChild(); i != null; i = i.getNextSibling()) {
290 if (i.getType() == aType) {
291 retVal = (DetailAST) i;
292 break;
293 }
294 }
295 return retVal;
296 }
297 }