Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 }