KickJava   Java API By Example, From Geeks To Geeks.

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


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.DetailAST;
22 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
23
24 /**
25  * Handler for parents of blocks ('if', 'else', 'while', etc).
26  * <P>
27  * The "block" handler classes use a common superclass BlockParentHandler,
28  * employing the Template Method pattern.
29  * <P>
30  * <UL>
31  * <LI>template method to get the lcurly</LI>
32  * <LI>template method to get the rcurly</LI>
33  * <LI>if curlys aren't present, then template method to get expressions
34  * is called</LI>
35  * <LI>now all the repetitous code which checks for BOL, if curlys are on
36  * same line, etc. can be collapsed into the superclass</LI>
37  * </UL>
38  *
39  * @author jrichard
40  */

41 public class BlockParentHandler extends ExpressionHandler
42 {
43     /**
44      * Children checked by parent handlers.
45      */

46     private static final int[] CHECKED_CHILDREN = new int[] {
47         TokenTypes.VARIABLE_DEF,
48         TokenTypes.EXPR,
49         TokenTypes.OBJBLOCK,
50         TokenTypes.LITERAL_BREAK,
51         TokenTypes.LITERAL_RETURN,
52         TokenTypes.LITERAL_THROW,
53         TokenTypes.LITERAL_CONTINUE,
54     };
55
56     /**
57      * Returns array of token types which should be checked among childrens.
58      * @return array of token types to check.
59      */

60     protected int[] getCheckedChildren()
61     {
62         return CHECKED_CHILDREN;
63     }
64
65     /**
66      * Construct an instance of this handler with the given indentation check,
67      * name, abstract syntax tree, and parent handler.
68      *
69      * @param aIndentCheck the indentation check
70      * @param aName the name of the handler
71      * @param aAst the abstract syntax tree
72      * @param aParent the parent handler
73      */

74     public BlockParentHandler(IndentationCheck aIndentCheck,
75         String JavaDoc aName, DetailAST aAst, ExpressionHandler aParent)
76     {
77         super(aIndentCheck, aName, aAst, aParent);
78     }
79
80     /**
81      * Get the top level expression being managed by this handler.
82      *
83      * @return the top level expression
84      */

85     protected DetailAST getToplevelAST()
86     {
87         return getMainAst();
88     }
89
90     /**
91      * Check the indent of the top level token.
92      */

93     protected void checkToplevelToken()
94     {
95         final DetailAST toplevel = getToplevelAST();
96
97         if ((toplevel == null)
98             || getLevel().accept(expandedTabsColumnNo(toplevel)))
99         {
100             return;
101         }
102         if (!toplevelMustStartLine() && !startsLine(toplevel)) {
103             return;
104         }
105         logError(toplevel, "", expandedTabsColumnNo(toplevel));
106     }
107
108     /**
109      * Determines if the top level token must start the line.
110      *
111      * @return true
112      */

113     protected boolean toplevelMustStartLine()
114     {
115         return true;
116     }
117
118     /**
119      * Determines if this block expression has curly braces.
120      *
121      * @return true if curly braces are present, false otherwise
122      */

123     protected boolean hasCurlys()
124     {
125         return (getLCurly() != null) && (getRCurly() != null);
126     }
127
128     /**
129      * Get the left curly brace portion of the expression we are handling.
130      *
131      * @return the left curly brace expression
132      */

133     protected DetailAST getLCurly()
134     {
135         return getMainAst().findFirstToken(TokenTypes.SLIST);
136     }
137
138     /**
139      * Get the right curly brace portion of the expression we are handling.
140      *
141      * @return the right curly brace expression
142      */

143     protected DetailAST getRCurly()
144     {
145         final DetailAST slist = getMainAst().findFirstToken(TokenTypes.SLIST);
146         if (slist == null) {
147             return null;
148         }
149
150         return slist.findFirstToken(TokenTypes.RCURLY);
151     }
152
153     /**
154      * Check the indentation of the left curly brace.
155      */

156     protected void checkLCurly()
157     {
158         // the lcurly can either be at the correct indentation, or nested
159
// with a previous expression
160
final DetailAST lcurly = getLCurly();
161         final int lcurlyPos = expandedTabsColumnNo(lcurly);
162
163         if ((lcurly == null)
164             || curlyLevel().accept(lcurlyPos)
165             || !startsLine(lcurly))
166         {
167             return;
168         }
169
170         logError(lcurly, "lcurly", lcurlyPos);
171     }
172
173     /**
174      * Get the expected indentation level for the curly braces.
175      *
176      * @return the curly brace indentation level
177      */

178     private IndentLevel curlyLevel()
179     {
180         return new IndentLevel(getLevel(), getBraceAdjustement());
181     }
182
183     /**
184      * Determines if the right curly brace must be at the start of the line.
185      *
186      * @return true
187      */

188     protected boolean rcurlyMustStart()
189     {
190         return true;
191     }
192
193     /**
194      * Determines if child elements within the expression may be nested.
195      *
196      * @return false
197      */

198     protected boolean childrenMayNest()
199     {
200         return false;
201     }
202
203     /**
204      * Check the indentation of the right curly brace.
205      */

206     protected void checkRCurly()
207     {
208         // the rcurly can either be at the correct indentation, or
209
// on the same line as the lcurly
210
final DetailAST lcurly = getLCurly();
211         final DetailAST rcurly = getRCurly();
212         final int rcurlyPos = expandedTabsColumnNo(rcurly);
213
214         if ((rcurly == null)
215             || curlyLevel().accept(rcurlyPos)
216             || (!rcurlyMustStart() && !startsLine(rcurly))
217             || areOnSameLine(rcurly, lcurly))
218         {
219             return;
220         }
221         logError(rcurly, "rcurly", rcurlyPos, curlyLevel());
222     }
223
224     /**
225      * Get the child element that is not a list of statements.
226      *
227      * @return the non-list child element
228      */

229     protected DetailAST getNonlistChild()
230     {
231         return (DetailAST) getMainAst().findFirstToken(
232             TokenTypes.RPAREN).getNextSibling();
233     }
234
235     /**
236      * Check the indentation level of a child that is not a list of statements.
237      */

238     private void checkNonlistChild()
239     {
240         // TODO: look for SEMI and check for it here?
241
final DetailAST nonlist = getNonlistChild();
242         if (nonlist == null) {
243             return;
244         }
245
246         final IndentLevel expected =
247             new IndentLevel(getLevel(), getBasicOffset());
248         checkExpressionSubtree(nonlist, expected, false, false);
249     }
250
251     /**
252      * Get the child element representing the list of statements.
253      *
254      * @return the statement list child
255      */

256     protected DetailAST getListChild()
257     {
258         return getMainAst().findFirstToken(TokenTypes.SLIST);
259     }
260
261     /**
262      * Get the right parenthesis portion of the expression we are handling.
263      *
264      * @return the right parenthis expression
265      */

266     protected DetailAST getRParen()
267     {
268         return getMainAst().findFirstToken(TokenTypes.RPAREN);
269     }
270
271     /**
272      * Get the left parenthesis portion of the expression we are handling.
273      *
274      * @return the left parenthis expression
275      */

276     protected DetailAST getLParen()
277     {
278         return getMainAst().findFirstToken(TokenTypes.LPAREN);
279     }
280
281     /**
282      * Check the indentation of the expression we are handling.
283      */

284     public void checkIndentation()
285     {
286         checkToplevelToken();
287         // seperate to allow for eventual configuration
288
checkLParen(getLParen());
289         checkRParen(getLParen(), getRParen());
290         if (hasCurlys()) {
291             checkLCurly();
292             checkRCurly();
293         }
294         final DetailAST listChild = getListChild();
295         if (listChild != null) {
296             // NOTE: switch statements usually don't have curlys
297
if (!hasCurlys() || !areOnSameLine(getLCurly(), getRCurly())) {
298                 checkChildren(listChild,
299                               getCheckedChildren(),
300                               getChildrenExpectedLevel(),
301                               true,
302                               childrenMayNest());
303             }
304         }
305         else {
306             checkNonlistChild();
307         }
308     }
309
310     /**
311      * @return indentation level expected for children
312      */

313     protected IndentLevel getChildrenExpectedLevel()
314     {
315         // if we have multileveled expected level then we should
316
// try to suggest single level to children using curlies'
317
// levels.
318
if (getLevel().isMultiLevel() && hasCurlys()
319             && !areOnSameLine(getLCurly(), getRCurly()))
320         {
321             if (startsLine(getLCurly())) {
322                 return new IndentLevel(expandedTabsColumnNo(getLCurly())
323                                        + getBasicOffset());
324             }
325             else if (startsLine(getRCurly())) {
326                 return new IndentLevel(expandedTabsColumnNo(getRCurly())
327                                        + getBasicOffset());
328             }
329         }
330         return new IndentLevel(getLevel(), getBasicOffset());
331     }
332
333     /** {@inheritDoc} */
334     public IndentLevel suggestedChildLevel(ExpressionHandler aChild)
335     {
336         return getChildrenExpectedLevel();
337     }
338
339 }
340
Popular Tags