diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheck.java index d9d49ca93..2aa1c6d06 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheck.java @@ -35,7 +35,8 @@ import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck; * {@link TokenTypes#LITERAL_IF LITERAL_IF}, * {@link TokenTypes#LITERAL_ELSE LITERAL_ELSE}, * {@link TokenTypes#LITERAL_FOR LITERAL_FOR}, - * {@link TokenTypes#STATIC_INIT STATIC_INIT}. + * {@link TokenTypes#STATIC_INIT STATIC_INIT}, + * {@link TokenTypes#LITERAL_SWITCH LITERAL_SWITCH}. *
* *An example of how to configure the check is: @@ -82,8 +83,7 @@ public class EmptyBlockCheck TokenTypes.LITERAL_FOR, TokenTypes.INSTANCE_INIT, TokenTypes.STATIC_INIT, - // TODO: need to handle.... - //TokenTypes.LITERAL_SWITCH, + TokenTypes.LITERAL_SWITCH, //TODO: does this handle TokenTypes.LITERAL_SYNCHRONIZED? }; } @@ -91,21 +91,30 @@ public class EmptyBlockCheck @Override public void visitToken(DetailAST aAST) { - final DetailAST slistAST = aAST.findFirstToken(TokenTypes.SLIST); - if (slistAST != null) { + final DetailAST slistToken = aAST.findFirstToken(TokenTypes.SLIST); + final DetailAST leftCurly = slistToken != null + ? slistToken : aAST.findFirstToken(TokenTypes.LCURLY); + if (leftCurly != null) { if (getAbstractOption() == BlockOption.STMT) { - if (slistAST.getChildCount() <= 1) { - log(slistAST.getLineNo(), - slistAST.getColumnNo(), + boolean emptyBlock; + if (leftCurly.getType() == TokenTypes.LCURLY) { + emptyBlock = leftCurly.getNextSibling().getType() != TokenTypes.CASE_GROUP; + } + else { + emptyBlock = leftCurly.getChildCount() <= 1; + } + if (emptyBlock) { + log(leftCurly.getLineNo(), + leftCurly.getColumnNo(), "block.noStmt", aAST.getText()); } } else if (getAbstractOption() == BlockOption.TEXT - && !hasText(slistAST)) + && !hasText(leftCurly)) { - log(slistAST.getLineNo(), - slistAST.getColumnNo(), + log(leftCurly.getLineNo(), + leftCurly.getColumnNo(), "block.empty", aAST.getText()); } @@ -120,7 +129,9 @@ public class EmptyBlockCheck { boolean retVal = false; - final DetailAST rcurlyAST = aSlistAST.findFirstToken(TokenTypes.RCURLY); + final DetailAST rightCurly = aSlistAST.findFirstToken(TokenTypes.RCURLY); + final DetailAST rcurlyAST = rightCurly != null + ? rightCurly : aSlistAST.getParent().findFirstToken(TokenTypes.RCURLY); if (rcurlyAST != null) { final int slistLineNo = aSlistAST.getLineNo(); final int slistColNo = aSlistAST.getColumnNo(); diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheckTest.java index 8fa594a51..2405ef080 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/EmptyBlockCheckTest.java @@ -95,11 +95,30 @@ public class EmptyBlockCheckTest checkConfig.addAttribute("option", BlockOption.STMT.toString()); checkConfig.addAttribute("tokens", "LITERAL_TRY, LITERAL_CATCH," + "LITERAL_FINALLY, LITERAL_DO, LITERAL_IF," - + "LITERAL_ELSE, INSTANCE_INIT, STATIC_INIT"); + + "LITERAL_ELSE, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH"); final String[] expected = { "16:29: Must have at least one statement.", "19:42: Must have at least one statement.", "22:29: Must have at least one statement.", + "23:28: Must have at least one statement.", + }; + verify(checkConfig, getPath("InputSemantic2.java"), expected); + } + + @Test + public void allowEmptyLoopsText() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(EmptyBlockCheck.class); + checkConfig.addAttribute("option", BlockOption.TEXT.toString()); + checkConfig.addAttribute("tokens", "LITERAL_TRY, LITERAL_CATCH," + + "LITERAL_FINALLY, LITERAL_DO, LITERAL_IF," + + "LITERAL_ELSE, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH"); + final String[] expected = { + "16:29: Empty if block.", + "19:42: Empty if block.", + "22:29: Empty if block.", + "23:28: Empty switch block.", }; verify(checkConfig, getPath("InputSemantic2.java"), expected); } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/InputSemantic2.java b/src/test/resources/com/puppycrawl/tools/checkstyle/InputSemantic2.java index 687a01301..36d9db37c 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/InputSemantic2.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/InputSemantic2.java @@ -20,6 +20,15 @@ class UpdateClass while ((r = in.read()) != 0) {} // is OK for (; index < s.length && s[index] != 'x'; index++) {} // is OK if (a == 1) {} else {System.out.println("a");} // is not OK + switch (a) {} //warn + switch (a) { //ok + case 1: + a = 2; + case 2: + a = 3; + default: + a = 0; + } } public int doSideEffect() diff --git a/src/xdocs/config_blocks.xml b/src/xdocs/config_blocks.xml index 78e3824fe..6743f4192 100644 --- a/src/xdocs/config_blocks.xml +++ b/src/xdocs/config_blocks.xml @@ -52,9 +52,11 @@ LITERAL_WHILE, INSTANCE_INIT + href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INSTANCE_INIT">INSTANCE_INIT, STATIC_INIT + href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#STATIC_INIT">STATIC_INIT, + LITERAL_SWITCH.