Source code: com/puppycrawl/tools/checkstyle/checks/EmptyBlockCheck.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2002 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;
20
21 import com.puppycrawl.tools.checkstyle.api.DetailAST;
22 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
23
24 /**
25 * Checks for empty blocks. The policy to verify is specified using the {@link
26 * BlockOption} class and defaults to {@link BlockOption#STMT}.
27 *
28 * <p> By default the check will check the following blocks:
29 * {@link TokenTypes#LITERAL_WHILE LITERAL_WHILE},
30 * {@link TokenTypes#LITERAL_TRY LITERAL_TRY},
31 * {@link TokenTypes#LITERAL_CATCH LITERAL_CATCH},
32 * {@link TokenTypes#LITERAL_FINALLY LITERAL_FINALLY},
33 * {@link TokenTypes#LITERAL_DO LITERAL_DO},
34 * {@link TokenTypes#LITERAL_IF LITERAL_IF},
35 * {@link TokenTypes#LITERAL_ELSE LITERAL_ELSE},
36 * {@link TokenTypes#LITERAL_FOR LITERAL_FOR},
37 * {@link TokenTypes#STATIC_INIT STATIC_INIT}.
38 *
39 * <p> An example of how to configure the check is:
40 * <pre>
41 * <module name="EmptyBlock"/>
42 * </pre>
43 *
44 * <p> An example of how to configure the check for the {@link
45 * BlockOption#TEXT} policy and only catch blocks is:
46 *
47 * <pre>
48 * <module name="EmptyBlock">
49 * <property name="tokens" value="LITERAL_CATCH"/>
50 * <property name="option" value="text"/>
51 * </module>
52 * </pre>
53 *
54 * @author Lars Kühne
55 */
56 public class EmptyBlockCheck
57 extends AbstractOptionCheck
58 {
59 /**
60 * Creates a new <code>EmptyBlockCheck</code> instance.
61 */
62 public EmptyBlockCheck()
63 {
64 super(BlockOption.STMT);
65 }
66
67 /** @see com.puppycrawl.tools.checkstyle.api.Check */
68 public int[] getDefaultTokens()
69 {
70 return new int[] {
71 TokenTypes.LITERAL_WHILE,
72 TokenTypes.LITERAL_TRY,
73 TokenTypes.LITERAL_CATCH,
74 TokenTypes.LITERAL_FINALLY,
75 TokenTypes.LITERAL_DO,
76 TokenTypes.LITERAL_IF,
77 TokenTypes.LITERAL_ELSE,
78 TokenTypes.LITERAL_FOR,
79 TokenTypes.STATIC_INIT,
80 // TODO: need to handle....
81 //TokenTypes.LITERAL_SWITCH,
82 //TODO: does this handle TokenTypes.LITERAL_SYNCHRONIZED?
83 };
84 }
85
86 /** @see com.puppycrawl.tools.checkstyle.api.Check */
87 public void visitToken(DetailAST aAST)
88 {
89 final DetailAST slistAST = aAST.findFirstToken(TokenTypes.SLIST);
90 if (slistAST != null) {
91 if (getAbstractOption() == BlockOption.STMT) {
92 if (slistAST.getChildCount() <= 1) {
93 log(slistAST.getLineNo(),
94 slistAST.getColumnNo(),
95 "block.noStmt",
96 aAST.getText());
97 }
98 }
99 else if (getAbstractOption() == BlockOption.TEXT) {
100 if (!hasText(slistAST)) {
101 log(slistAST.getLineNo(),
102 slistAST.getColumnNo(),
103 "block.empty",
104 aAST.getText());
105 }
106 }
107 }
108 }
109
110 /**
111 * @param aSlistAST a <code>DetailAST</code> value
112 * @return whether the SLIST token contains any text.
113 */
114 private boolean hasText(final DetailAST aSlistAST)
115 {
116 boolean retVal = false;
117
118 final DetailAST rcurlyAST = aSlistAST.findFirstToken(TokenTypes.RCURLY);
119 if (rcurlyAST != null) {
120 final int slistLineNo = aSlistAST.getLineNo();
121 final int slistColNo = aSlistAST.getColumnNo();
122 final int rcurlyLineNo = rcurlyAST.getLineNo();
123 final int rcurlyColNo = rcurlyAST.getColumnNo();
124 final String[] lines = getLines();
125 if (slistLineNo == rcurlyLineNo) {
126 // Handle braces on the same line
127 final String txt = lines[slistLineNo - 1]
128 .substring(slistColNo + 1, rcurlyColNo);
129 if (txt.trim().length() != 0) {
130 retVal = true;
131 }
132 }
133 else {
134 // check only whitespace of first & last lines
135 if ((lines[slistLineNo - 1]
136 .substring(slistColNo + 1).trim().length() != 0)
137 || (lines[rcurlyLineNo - 1]
138 .substring(0, rcurlyColNo).trim().length() != 0))
139 {
140 retVal = true;
141 }
142 else {
143 // check if all lines are also only whitespace
144 for (int i = slistLineNo; i < (rcurlyLineNo - 1); i++) {
145 if (lines[i].trim().length() > 0) {
146 retVal = true;
147 break;
148 }
149 }
150 }
151 }
152 }
153 return retVal;
154 }
155 }