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

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheck.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.checks.indentation;
20  
21  import com.puppycrawl.tools.checkstyle.api.Check;
22  import com.puppycrawl.tools.checkstyle.api.DetailAST;
23  
24  import org.apache.commons.collections.ArrayStack;
25  
26  // TODO: allow preset indentation styles (IE... GNU style, Sun style, etc...)?
27  
28  // TODO: optionally make imports (and other?) statements required to start
29  //   line? -- but maybe this should be a different check
30  
31  // TODO: optionally allow array children, throws clause, etc...
32  //   to be of any indentation > required, for emacs-style indentation
33  
34  // TODO: this is not illegal, but probably should be:
35  //        myfunc3(11, 11, Integer.
36  //            getInteger("mytest").intValue(),  // this should be in 4 more
37  //            11);
38  
39  // TODO: any dot-based indentation doesn't work (at least not yet...) the
40  //  problem is that we don't know which way an expression tree will be built
41  //  and with dot trees, they are built backwards.  This means code like
42  //
43  //  org.blah.mystuff
44  //      .myclass.getFactoryObject()
45  //          .objFunc().otherMethod();
46  // and
47  //  return ((MethodCallHandler) parent)
48  //      .findContainingMethodCall(this);
49  //  is all checked at the level of the first line.  Simple dots are actually
50  // checked but the method call handler will have to be changed drastically
51  // to fix the above...
52  
53  
54  /**
55   * Checks correct indentation of Java Code.
56   *
57   * <p>
58   * The basic idea behind this is that while
59   * pretty printers are sometimes convienent for bulk reformats of
60   * legacy code, they often either aren't configurable enough or
61   * just can't anticipate how format should be done.  Sometimes this is
62   * personal preference, other times it is practical experience.  In any
63   * case, this check should just ensure that a minimal set of indentation
64   * rules are followed.
65   * </p>
66   *
67   * <p>
68   * Implementation --
69   *  Basically, this check requests visitation for all handled token
70   *  types (those tokens registered in the HandlerFactory).  When visitToken
71   *  is called, a new ExpressionHandler is created for the AST and pushed
72   *  onto the mHandlers stack.  The new handler then checks the indentation
73   *  for the currently visiting AST.  When leaveToken is called, the
74   *  ExpressionHandler is popped from the stack.
75   * </p>
76   *
77   * <p>
78   *  While on the stack the ExpressionHandler can be queried for the
79   *  indentation level it suggests for children as well as for other
80   *  values.
81   * </p>
82   *
83   * <p>
84   *  While an ExpressionHandler checks the indentation level of its own
85   *  AST, it typically also checks surrounding ASTs.  For instance, a
86   *  while loop handler checks the while loop as well as the braces
87   *  and immediate children.
88   * </p>
89   * Created on November 2, 2002, 10:59 PM
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 
109 public class IndentationCheck extends Check
110 {
111     /** Default indentation amount - based on Sun */
112     private static final int DEFAULT_INDENTATION = 4;
113 
114     /** how many tabs or spaces to use */
115     private int mBasicOffset = DEFAULT_INDENTATION;
116 
117     /** how much to indent a case label */
118     private int mCaseIndentationAmount = DEFAULT_INDENTATION;
119 
120     /** how far brace should be indented when on next line */
121     private int mBraceAdjustment;
122 
123     /** handlers currently in use */
124     private ArrayStack mHandlers = new ArrayStack();
125 
126     /** factory from which handlers are distributed */
127     private HandlerFactory mHandlerFactory = new HandlerFactory();
128 
129     /** Creates a new instance of IndentationCheck. */
130     public IndentationCheck()
131     {
132     }
133 
134     /**
135      * Set the basic offset.
136      *
137      * @param aBasicOffset   the number of tabs or spaces to indent
138      */
139     public void setBasicOffset(int aBasicOffset)
140     {
141         mBasicOffset = aBasicOffset;
142     }
143 
144     /**
145      * Get the basic offset.
146      *
147      * @return the number of tabs or spaces to indent
148      */
149     public int getBasicOffset()
150     {
151         return mBasicOffset;
152     }
153 
154     /**
155      * Adjusts brace indentation (positive offset).
156      *
157      * @param aAdjustmentAmount   the brace offset
158      */
159     public void setBraceAdjustment(int aAdjustmentAmount)
160     {
161         mBraceAdjustment = aAdjustmentAmount;
162     }
163 
164     /**
165      * Get the brace adjustment amount.
166      *
167      * @return the positive offset to adjust braces
168      */
169     public int getBraceAdjustement()
170     {
171         return mBraceAdjustment;
172     }
173 
174     /**
175      * Set the case indentation level.
176      *
177      * @param aAmount   the case indentation level
178      */
179     public void setCaseIndent(int aAmount)
180     {
181         mCaseIndentationAmount = aAmount;
182     }
183 
184     /**
185      * Get the case indentation level.
186      *
187      * @return the case indentation level
188      */
189     public int getCaseIndent()
190     {
191         return mCaseIndentationAmount;
192     }
193 
194     /**
195      * Log an error message.
196      *
197      * @param aLine the line number where the error was found
198      * @param aKey the message that describes the error
199      * @param aArgs the details of the message
200      *
201      * @see java.text.MessageFormat
202      */
203     public void indentationLog(int aLine, String aKey, Object[] aArgs)
204     {
205         super.log(aLine, aKey, aArgs);
206     }
207 
208     /**
209      * Get the width of a tab.
210      *
211      * @return the width of a tab
212      */
213     public int getIndentationTabWidth()
214     {
215         return getTabWidth();
216     }
217 
218     /**
219      * Get the tokens that this check will handle.
220      *
221      * @return the array of tokens that this check handles
222      */
223     public int[] getDefaultTokens()
224     {
225         return mHandlerFactory.getHandledTypes();
226     }
227 
228     /**
229      * @see com.puppycrawl.tools.checkstyle.api.Check
230      */
231     public void beginTree(DetailAST aAst)
232     {
233         mHandlerFactory.clearCreatedHandlers();
234         mHandlers.clear();
235         mHandlers.push(new PrimordialHandler(this));
236     }
237 
238     /**
239      * @see com.puppycrawl.tools.checkstyle.api.Check
240      */
241     public void visitToken(DetailAST aAST)
242     {
243         ExpressionHandler handler = mHandlerFactory.getHandler(this, aAST,
244             (ExpressionHandler) mHandlers.peek());
245         mHandlers.push(handler);
246         handler.checkIndentation();
247     }
248 
249     /**
250      * @see com.puppycrawl.tools.checkstyle.api.Check
251      */
252     public void leaveToken(DetailAST aAST)
253     {
254         mHandlers.pop();
255     }
256 
257     /**
258      * Accessor for the handler factory.
259      *
260      * @return the handler factory
261      */
262     final HandlerFactory getHandlerFactory()
263     {
264         return mHandlerFactory;
265     }
266 }