KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > indentation > IndentationCheck


1 ////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2005 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.checks.indentation;
20
21 import com.puppycrawl.tools.checkstyle.api.Check;
22 import com.puppycrawl.tools.checkstyle.api.DetailAST;
23 import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
24 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
25
26 import org.apache.commons.collections.ArrayStack;
27
28 // TODO: allow preset indentation styles (IE... GNU style, Sun style, etc...)?
29

30 // TODO: optionally make imports (and other?) statements required to start
31
// line? -- but maybe this should be a different check
32

33 // TODO: optionally allow array children, throws clause, etc...
34
// to be of any indentation > required, for emacs-style indentation
35

36 // TODO: this is not illegal, but probably should be:
37
// myfunc3(11, 11, Integer.
38
// getInteger("mytest").intValue(), // this should be in 4 more
39
// 11);
40

41 // TODO: any dot-based indentation doesn't work (at least not yet...) the
42
// problem is that we don't know which way an expression tree will be built
43
// and with dot trees, they are built backwards. This means code like
44
//
45
// org.blah.mystuff
46
// .myclass.getFactoryObject()
47
// .objFunc().otherMethod();
48
// and
49
// return ((MethodCallHandler) parent)
50
// .findContainingMethodCall(this);
51
// is all checked at the level of the first line. Simple dots are actually
52
// checked but the method call handler will have to be changed drastically
53
// to fix the above...
54

55
56 /**
57  * Checks correct indentation of Java Code.
58  *
59  * <p>
60  * The basic idea behind this is that while
61  * pretty printers are sometimes convienent for bulk reformats of
62  * legacy code, they often either aren't configurable enough or
63  * just can't anticipate how format should be done. Sometimes this is
64  * personal preference, other times it is practical experience. In any
65  * case, this check should just ensure that a minimal set of indentation
66  * rules are followed.
67  * </p>
68  *
69  * <p>
70  * Implementation --
71  * Basically, this check requests visitation for all handled token
72  * types (those tokens registered in the HandlerFactory). When visitToken
73  * is called, a new ExpressionHandler is created for the AST and pushed
74  * onto the mHandlers stack. The new handler then checks the indentation
75  * for the currently visiting AST. When leaveToken is called, the
76  * ExpressionHandler is popped from the stack.
77  * </p>
78  *
79  * <p>
80  * While on the stack the ExpressionHandler can be queried for the
81  * indentation level it suggests for children as well as for other
82  * values.
83  * </p>
84  *
85  * <p>
86  * While an ExpressionHandler checks the indentation level of its own
87  * AST, it typically also checks surrounding ASTs. For instance, a
88  * while loop handler checks the while loop as well as the braces
89  * and immediate children.
90  * </p>
91  * <pre>
92  * - handler class -to-> ID mapping kept in Map
93  * - parent passed in during construction
94  * - suggest child indent level
95  * - allows for some tokens to be on same line (ie inner classes OBJBLOCK)
96  * and not increase indentation level
97  * - looked at using double dispatch for suggestedChildLevel(), but it
98  * doesn't seem worthwhile, at least now
99  * - both tabs and spaces are considered whitespace in front of the line...
100  * tabs are converted to spaces
101  * - block parents with parens -- for, while, if, etc... -- are checked that
102  * they match the level of the parent
103  * </pre>
104  *
105  * @author jrichard
106  * @author o_sukhodolsky
107  *
108  * @checkstyle-docpage misc
109  */

110
111 public class IndentationCheck extends Check
112 {
113     /** Default indentation amount - based on Sun */
114     private static final int DEFAULT_INDENTATION = 4;
115
116     /** how many tabs or spaces to use */
117     private int mBasicOffset = DEFAULT_INDENTATION;
118
119     /** how much to indent a case label */
120     private int mCaseIndentationAmount = DEFAULT_INDENTATION;
121
122     /** how far brace should be indented when on next line */
123     private int mBraceAdjustment;
124
125     /** handlers currently in use */
126     private final ArrayStack mHandlers = new ArrayStack();
127
128     /** factory from which handlers are distributed */
129     private final HandlerFactory mHandlerFactory = new HandlerFactory();
130
131     /** Creates a new instance of IndentationCheck. */
132     public IndentationCheck()
133     {
134     }
135
136     /**
137      * Set the basic offset.
138      *
139      * @param aBasicOffset the number of tabs or spaces to indent
140      */

141     public void setBasicOffset(int aBasicOffset)
142     {
143         mBasicOffset = aBasicOffset;
144     }
145
146     /**
147      * Get the basic offset.
148      *
149      * @return the number of tabs or spaces to indent
150      */

151     public int getBasicOffset()
152     {
153         return mBasicOffset;
154     }
155
156     /**
157      * Adjusts brace indentation (positive offset).
158      *
159      * @param aAdjustmentAmount the brace offset
160      */

161     public void setBraceAdjustment(int aAdjustmentAmount)
162     {
163         mBraceAdjustment = aAdjustmentAmount;
164     }
165
166     /**
167      * Get the brace adjustment amount.
168      *
169      * @return the positive offset to adjust braces
170      */

171     public int getBraceAdjustement()
172     {
173         return mBraceAdjustment;
174     }
175
176     /**
177      * Set the case indentation level.
178      *
179      * @param aAmount the case indentation level
180      */

181     public void setCaseIndent(int aAmount)
182     {
183         mCaseIndentationAmount = aAmount;
184     }
185
186     /**
187      * Get the case indentation level.
188      *
189      * @return the case indentation level
190      */

191     public int getCaseIndent()
192     {
193         return mCaseIndentationAmount;
194     }
195
196     /**
197      * Log an error message.
198      *
199      * @param aLine the line number where the error was found
200      * @param aKey the message that describes the error
201      * @param aArgs the details of the message
202      *
203      * @see java.text.MessageFormat
204      */

205     public void indentationLog(int aLine, String JavaDoc aKey, Object JavaDoc[] aArgs)
206     {
207         super.log(aLine, aKey, aArgs);
208     }
209
210     /**
211      * Get the width of a tab.
212      *
213      * @return the width of a tab
214      */

215     public int getIndentationTabWidth()
216     {
217         return getTabWidth();
218     }
219
220     /**
221      * Get the tokens that this check will handle.
222      *
223      * @return the array of tokens that this check handles
224      */

225     public int[] getDefaultTokens()
226     {
227         return mHandlerFactory.getHandledTypes();
228     }
229
230     /**
231      * {@inheritDoc}
232      */

233     public void beginTree(DetailAST aAst)
234     {
235         mHandlerFactory.clearCreatedHandlers();
236         mHandlers.clear();
237         mHandlers.push(new PrimordialHandler(this));
238     }
239
240     /**
241      * {@inheritDoc}
242      */

243     public void visitToken(DetailAST aAST)
244     {
245         if ((aAST.getType() == TokenTypes.VARIABLE_DEF)
246             && ScopeUtils.isLocalVariableDef(aAST))
247         {
248             // we have handler only for members
249
return;
250         }
251
252         final ExpressionHandler handler = mHandlerFactory.getHandler(this, aAST,
253             (ExpressionHandler) mHandlers.peek());
254         mHandlers.push(handler);
255         try {
256             handler.checkIndentation();
257         }
258         catch (final NullPointerException JavaDoc npe) {
259             npe.printStackTrace();
260         }
261     }
262
263     /**
264      * {@inheritDoc}
265      */

266     public void leaveToken(DetailAST aAST)
267     {
268         if ((aAST.getType() == TokenTypes.VARIABLE_DEF)
269             && ScopeUtils.isLocalVariableDef(aAST))
270         {
271             // we have handler only for members
272
return;
273         }
274         mHandlers.pop();
275     }
276
277     /**
278      * Accessor for the handler factory.
279      *
280      * @return the handler factory
281      */

282     final HandlerFactory getHandlerFactory()
283     {
284         return mHandlerFactory;
285     }
286 }
287
Popular Tags