Source code: com/puppycrawl/tools/checkstyle/checks/blocks/AvoidNestedBlocksCheck.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.blocks;
20
21 import com.puppycrawl.tools.checkstyle.api.Check;
22 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
23 import com.puppycrawl.tools.checkstyle.api.DetailAST;
24
25 /**
26 * Finds nested blocks.
27 *
28 * <p>
29 * For example this Check flags confusing code like
30 * <pre>
31 * public void guessTheOutput()
32 * {
33 * int whichIsWich = 0;
34 * {
35 * int whichIsWhich = 2;
36 * }
37 * System.out.println("value = " + whichIsWhich);
38 * }
39 * </pre>
40 *
41 * and debugging / refactoring leftovers such as
42 *
43 * <pre>
44 * // if (someOldCondition)
45 * {
46 * System.out.println("unconditional");
47 * }
48 * </pre>
49 *
50 * <p>
51 * A case in a switch statement does not implicitly form a block.
52 * Thus to be able to introduce local variables that have case scope
53 * it is necessary to open a nested block. This is supported, set
54 * the allowInSwitchCase property to true and include all statements
55 * of the case in the block.
56 * </p>
57 *
58 * <pre>
59 * switch (a)
60 * {
61 * case 0:
62 * // Never OK, break outside block
63 * {
64 * x = 1;
65 * }
66 * break;
67 * case 1:
68 * // Never OK, statement outside block
69 * System.out.println("Hello");
70 * {
71 * x = 2;
72 * break;
73 * }
74 * case 1:
75 * // OK if allowInSwitchCase is true
76 * {
77 * System.out.println("Hello");
78 * x = 2;
79 * break;
80 * }
81 * }
82 * </pre>
83 *
84 * @author lkuehne
85 */
86 public class AvoidNestedBlocksCheck extends Check
87 {
88 /**
89 * Whether nested blocks are allowed if they are the
90 * only child of a switch case.
91 */
92 private boolean mAllowInSwitchCase;
93
94 /** @see Check */
95 public int[] getDefaultTokens()
96 {
97 return new int[] {TokenTypes.SLIST};
98 }
99
100 /** @see Check */
101 public void visitToken(DetailAST aAST)
102 {
103 final DetailAST parent = aAST.getParent();
104 if (parent.getType() == TokenTypes.SLIST) {
105 if (mAllowInSwitchCase
106 && parent.getParent().getType() == TokenTypes.CASE_GROUP
107 && parent.getNumberOfChildren() == 1)
108 {
109 return;
110 }
111 log(aAST.getLineNo(), aAST.getColumnNo(), "block.nested");
112 }
113 }
114
115 /**
116 * Setter for allowInSwitchCase property.
117 * @param aAllowInSwitchCase whether nested blocks are allowed
118 * if they are the only child of a switch case.
119 */
120 public void setAllowInSwitchCase(boolean aAllowInSwitchCase)
121 {
122 mAllowInSwitchCase = aAllowInSwitchCase;
123 }
124 }