1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.blocks;
21
22 import java.util.regex.Pattern;
23
24 import com.puppycrawl.tools.checkstyle.StatelessCheck;
25 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26 import com.puppycrawl.tools.checkstyle.api.DetailAST;
27 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 @StatelessCheck
45 public class EmptyCatchBlockCheck extends AbstractCheck {
46
47
48
49
50
51 public static final String MSG_KEY_CATCH_BLOCK_EMPTY = "catch.block.empty";
52
53
54
55
56 private static final Pattern LINE_END_PATTERN = Pattern.compile("\\r?+\\n|\\r");
57
58
59
60
61
62 private Pattern exceptionVariableName = Pattern.compile("^$");
63
64
65
66
67
68
69 private Pattern commentFormat = Pattern.compile(".*");
70
71
72
73
74
75
76
77
78
79 public void setExceptionVariableName(Pattern exceptionVariablePattern) {
80 exceptionVariableName = exceptionVariablePattern;
81 }
82
83
84
85
86
87
88
89
90
91
92 public void setCommentFormat(Pattern commentPattern) {
93 commentFormat = commentPattern;
94 }
95
96 @Override
97 public int[] getDefaultTokens() {
98 return getRequiredTokens();
99 }
100
101 @Override
102 public int[] getAcceptableTokens() {
103 return getRequiredTokens();
104 }
105
106 @Override
107 public int[] getRequiredTokens() {
108 return new int[] {
109 TokenTypes.LITERAL_CATCH,
110 };
111 }
112
113 @Override
114 public boolean isCommentNodesRequired() {
115 return true;
116 }
117
118 @Override
119 public void visitToken(DetailAST ast) {
120 visitCatchBlock(ast);
121 }
122
123
124
125
126
127
128
129
130 private void visitCatchBlock(DetailAST catchAst) {
131 if (isEmptyCatchBlock(catchAst)) {
132 final String commentContent = getCommentFirstLine(catchAst);
133 if (isVerifiable(catchAst, commentContent)) {
134 log(catchAst.findFirstToken(TokenTypes.SLIST), MSG_KEY_CATCH_BLOCK_EMPTY);
135 }
136 }
137 }
138
139
140
141
142
143
144
145
146 private static String getCommentFirstLine(DetailAST catchAst) {
147 final DetailAST slistToken = catchAst.getLastChild();
148 final DetailAST firstElementInBlock = slistToken.getFirstChild();
149 String commentContent = "";
150 if (firstElementInBlock.getType() == TokenTypes.SINGLE_LINE_COMMENT) {
151 commentContent = firstElementInBlock.getFirstChild().getText();
152 }
153 else if (firstElementInBlock.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
154 commentContent = firstElementInBlock.getFirstChild().getText();
155 final String[] lines = LINE_END_PATTERN.split(commentContent);
156 for (String line : lines) {
157 if (!line.isEmpty()) {
158 commentContent = line;
159 break;
160 }
161 }
162 }
163 return commentContent;
164 }
165
166
167
168
169
170
171
172
173
174 private boolean isVerifiable(DetailAST emptyCatchAst, String commentContent) {
175 final String variableName = getExceptionVariableName(emptyCatchAst);
176 final boolean isMatchingVariableName = exceptionVariableName
177 .matcher(variableName).find();
178 final boolean isMatchingCommentContent = !commentContent.isEmpty()
179 && commentFormat.matcher(commentContent).find();
180 return !isMatchingVariableName && !isMatchingCommentContent;
181 }
182
183
184
185
186
187
188
189 private static boolean isEmptyCatchBlock(DetailAST catchAst) {
190 boolean result = true;
191 final DetailAST slistToken = catchAst.findFirstToken(TokenTypes.SLIST);
192 DetailAST catchBlockStmt = slistToken.getFirstChild();
193 while (catchBlockStmt.getType() != TokenTypes.RCURLY) {
194 if (catchBlockStmt.getType() != TokenTypes.SINGLE_LINE_COMMENT
195 && catchBlockStmt.getType() != TokenTypes.BLOCK_COMMENT_BEGIN) {
196 result = false;
197 break;
198 }
199 catchBlockStmt = catchBlockStmt.getNextSibling();
200 }
201 return result;
202 }
203
204
205
206
207
208
209
210 private static String getExceptionVariableName(DetailAST catchAst) {
211 final DetailAST parameterDef = catchAst.findFirstToken(TokenTypes.PARAMETER_DEF);
212 final DetailAST variableName = parameterDef.findFirstToken(TokenTypes.IDENT);
213 return variableName.getText();
214 }
215
216 }