1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2019 the original author or authors.
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
20 package com.puppycrawl.tools.checkstyle.checks.coding;
21
22 import com.puppycrawl.tools.checkstyle.StatelessCheck;
23 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
24 import com.puppycrawl.tools.checkstyle.api.DetailAST;
25 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
26
27 /**
28 * <p>
29 * Checks that switch statement has a "default" clause.
30 * </p>
31 * <p>
32 * Rationale: It's usually a good idea to introduce a
33 * default case in every switch statement. Even if
34 * the developer is sure that all currently possible
35 * cases are covered, this should be expressed in the
36 * default branch, e.g. by using an assertion. This way
37 * the code is protected against later changes, e.g.
38 * introduction of new types in an enumeration type.
39 * </p>
40 * <p>
41 * To configure the check:
42 * </p>
43 * <pre>
44 * <module name="MissingSwitchDefault"/>
45 * </pre>
46 *
47 * @since 3.1
48 */
49 @StatelessCheck
50 public class MissingSwitchDefaultCheck extends AbstractCheck {
51
52 /**
53 * A key is pointing to the warning message text in "messages.properties"
54 * file.
55 */
56 public static final String MSG_KEY = "missing.switch.default";
57
58 @Override
59 public int[] getDefaultTokens() {
60 return getRequiredTokens();
61 }
62
63 @Override
64 public int[] getAcceptableTokens() {
65 return getRequiredTokens();
66 }
67
68 @Override
69 public int[] getRequiredTokens() {
70 return new int[] {TokenTypes.LITERAL_SWITCH};
71 }
72
73 @Override
74 public void visitToken(DetailAST ast) {
75 final DetailAST firstCaseGroupAst = ast.findFirstToken(TokenTypes.CASE_GROUP);
76
77 if (!containsDefaultSwitch(firstCaseGroupAst)) {
78 log(ast.getLineNo(), MSG_KEY);
79 }
80 }
81
82 /**
83 * Checks if the case group or its sibling contain the 'default' switch.
84 * @param caseGroupAst first case group to check.
85 * @return true if 'default' switch found.
86 */
87 private static boolean containsDefaultSwitch(DetailAST caseGroupAst) {
88 DetailAST nextAst = caseGroupAst;
89 boolean found = false;
90
91 while (nextAst != null) {
92 if (nextAst.findFirstToken(TokenTypes.LITERAL_DEFAULT) != null) {
93 found = true;
94 break;
95 }
96
97 nextAst = nextAst.getNextSibling();
98 }
99
100 return found;
101 }
102
103 }