diff --git a/docs/checkstyle_checks.xml b/docs/checkstyle_checks.xml
index a1329e5d9..aea02960f 100644
--- a/docs/checkstyle_checks.xml
+++ b/docs/checkstyle_checks.xml
@@ -99,5 +99,6 @@
+ com.puppycrawl.tools.checkstyle.checks +
++ TreeWalker +
++ Checks that switch statement has "default" clause. +
++ Rationale: It's usually a good idea to introduce a default case + in every switch statement. Even if the developer is sure that + all currently possible cases are covered, this should be + expressed in the default branch, e.g. by using an + assertion. This way the code is protected aginst later changes, + e.g. introduction of new types in an enumeration type. +
++ To configure the check: +
+
+<module name="MissingSwitchDefault"/>
diff --git a/docs/releasenotes.html b/docs/releasenotes.html index ec5e5c653..5ac38a815 100644 --- a/docs/releasenotes.html +++ b/docs/releasenotes.html @@ -104,6 +104,10 @@ check that classes are declared final if they only contain private constructors (request 696290). +
diff --git a/docs/sun_checks.xml b/docs/sun_checks.xml
index 6119351dc..71d385d72 100644
--- a/docs/sun_checks.xml
+++ b/docs/sun_checks.xml
@@ -115,6 +115,9 @@
+ * Checks that switch statement has "default" clause. + *
+ *+ * Rationale: It's usually a good idea to introduce a + * default case in every switch statement. Even if + * the developer is sure that all currently possible + * cases are covered, this should be expressed in the + * default branch, e.g. by using an assertion. This way + * the code is protected aginst later changes, e.g. + * introduction of new types in an enumeration type. + *
+ *+ * An example of how to configure the check is: + *
+ *+ * <module name="MissingSwitchDefault"/> + *+ * @author o_sukhodolsky + */ +public class MissingSwitchDefaultCheck + extends Check +{ + /** @see Check */ + public int[] getDefaultTokens() + { + return new int[]{TokenTypes.LITERAL_SWITCH}; + } + + /** @see Check */ + public void visitToken(DetailAST aAst) + { + DetailAST child = aAst.findFirstToken(TokenTypes.CASE_GROUP); + while (child != null) { + if ((child.getType() == TokenTypes.CASE_GROUP) + && child.branchContains(TokenTypes.LITERAL_DEFAULT)) + { + return; + } + child = (DetailAST) child.getNextSibling(); + } + log(aAst.getLineNo(), "missing.switch.default"); + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties index 57a577c82..0ab794261 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/messages.properties @@ -79,3 +79,4 @@ doublechecked.locking.avoid=The double-checked locking idiom is broken and shoul design.forInheritance=Method ''{0}'' is not designed for inheritance - needs to be abstract, final or empty. final.class=Class {0} should be declared as final +missing.switch.default=switch without \"default\" clause diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/InputMissingSwitchDefault.java b/src/testinputs/com/puppycrawl/tools/checkstyle/InputMissingSwitchDefault.java new file mode 100755 index 000000000..a8fda9db3 --- /dev/null +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/InputMissingSwitchDefault.java @@ -0,0 +1,20 @@ +public class test { + public void foo() { + int i = 1; + switch (i) { + case 1: i++; break; + case 2: i--; break; + default: return; + } + } +} + +class bad_test { + public void foo() { + int i = 1; + switch (i) { + case 1: i++; break; + case 2: i--; break; + } + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java index 83784cc0e..2f18c6193 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java @@ -29,6 +29,7 @@ import com.puppycrawl.tools.checkstyle.checks.LocalVariableNameCheckTest; import com.puppycrawl.tools.checkstyle.checks.MemberNameCheckTest; import com.puppycrawl.tools.checkstyle.checks.MethodLengthCheckTest; import com.puppycrawl.tools.checkstyle.checks.MethodNameCheckTest; +import com.puppycrawl.tools.checkstyle.checks.MissingSwitchDefaultCheckTest; import com.puppycrawl.tools.checkstyle.checks.ModifierOrderCheckTest; import com.puppycrawl.tools.checkstyle.checks.NeedBracesCheckTest; import com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest; @@ -135,6 +136,7 @@ public class AllTests { suite.addTest(new TestSuite(WhitespaceAroundTest.class)); suite.addTest(new TestSuite(XMLLoggerTest.class)); suite.addTest(new TestSuite(FinalClassCheckTest.class)); + suite.addTest(new TestSuite(MissingSwitchDefaultCheckTest.class)); //$JUnit-END$ return suite; } diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/MissingSwitchDefaultCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/MissingSwitchDefaultCheckTest.java new file mode 100755 index 000000000..e19626c09 --- /dev/null +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/MissingSwitchDefaultCheckTest.java @@ -0,0 +1,26 @@ +package com.puppycrawl.tools.checkstyle.checks; + +import com.puppycrawl.tools.checkstyle.BaseCheckTestCase; +import com.puppycrawl.tools.checkstyle.DefaultConfiguration; + +public class MissingSwitchDefaultCheckTest + extends BaseCheckTestCase +{ + private DefaultConfiguration mCheckConfig; + + public void setUp() + { + mCheckConfig = createCheckConfig(MissingSwitchDefaultCheck.class); + } + + public void testMissingSwitchDefault() throws Exception + { + final String[] expected = { + "15: switch without \"default\" clause", + }; + verify( + mCheckConfig, + getPath("InputMissingSwitchDefault.java"), + expected); + } +}