From 0fdbbda1022d3d78b5d64a2d9f7260adac377d77 Mon Sep 17 00:00:00 2001 From: liscju Date: Wed, 21 Dec 2016 07:58:23 +0100 Subject: [PATCH] Issue #3655: Fix NPE in NeedBraces on single line default stmt --- .../checks/blocks/NeedBracesCheck.java | 48 ++++++++++++++----- .../checks/blocks/NeedBracesCheckTest.java | 19 ++++++++ .../blocks/InputNeedBracesEmptyDefault.java | 19 ++++++++ 3 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 src/test/resources/com/puppycrawl/tools/checkstyle/checks/blocks/InputNeedBracesEmptyDefault.java diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheck.java index 06fdafdde..de566f109 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheck.java @@ -204,15 +204,30 @@ public class NeedBracesCheck extends AbstractCheck { && ast.findFirstToken(TokenTypes.LITERAL_IF) != null) { isElseIf = true; } - + final boolean isDefaultInAnnotation = isDefaultInAnnotation(ast); final boolean skipStatement = isSkipStatement(ast); final boolean skipEmptyLoopBody = allowEmptyLoopBody && isEmptyLoopBody(ast); - if (slistAST == null && !isElseIf && !skipStatement && !skipEmptyLoopBody) { + if (slistAST == null && !isElseIf && !isDefaultInAnnotation + && !skipStatement && !skipEmptyLoopBody) { log(ast.getLineNo(), MSG_KEY_NEED_BRACES, ast.getText()); } } + /** + * Checks if ast is default in annotation + * @param ast ast to test. + * @return true if current ast is default and it is part of annatation. + */ + private boolean isDefaultInAnnotation(DetailAST ast) { + boolean isDefaultInAnnotation = false; + if (ast.getType() == TokenTypes.LITERAL_DEFAULT + && ast.getParent().getType() == TokenTypes.ANNOTATION_FIELD_DEF) { + isDefaultInAnnotation = true; + } + return isDefaultInAnnotation; + } + /** * Checks if current statement can be skipped by "need braces" warning. * @param statement if, for, while, do-while, lambda, else, case, default statements. @@ -410,6 +425,7 @@ public class NeedBracesCheck extends AbstractCheck { * {@code * case 1: doSomeStuff(); break; * case 2: doSomeStuff(); break; + * case 3: ; * } *

* @param literalCase {@link TokenTypes#LITERAL_CASE case statement}. @@ -418,12 +434,17 @@ public class NeedBracesCheck extends AbstractCheck { private static boolean isSingleLineCase(DetailAST literalCase) { boolean result = false; final DetailAST slist = literalCase.getNextSibling(); - final DetailAST block = slist.getFirstChild(); - if (block.getType() != TokenTypes.SLIST) { - final DetailAST caseBreak = slist.findFirstToken(TokenTypes.LITERAL_BREAK); - final boolean atOneLine = literalCase.getLineNo() == block.getLineNo(); - if (caseBreak != null) { - result = atOneLine && block.getLineNo() == caseBreak.getLineNo(); + if (slist == null) { + result = true; + } + else { + final DetailAST block = slist.getFirstChild(); + if (block.getType() != TokenTypes.SLIST) { + final DetailAST caseBreak = slist.findFirstToken(TokenTypes.LITERAL_BREAK); + final boolean atOneLine = literalCase.getLineNo() == block.getLineNo(); + if (caseBreak != null) { + result = atOneLine && block.getLineNo() == caseBreak.getLineNo(); + } } } return result; @@ -442,9 +463,14 @@ public class NeedBracesCheck extends AbstractCheck { private static boolean isSingleLineDefault(DetailAST literalDefault) { boolean result = false; final DetailAST slist = literalDefault.getNextSibling(); - final DetailAST block = slist.getFirstChild(); - if (block.getType() != TokenTypes.SLIST) { - result = literalDefault.getLineNo() == block.getLineNo(); + if (slist == null) { + result = true; + } + else { + final DetailAST block = slist.getFirstChild(); + if (block != null && block.getType() != TokenTypes.SLIST) { + result = literalDefault.getLineNo() == block.getLineNo(); + } } return result; } diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheckTest.java index 4bd6a01d3..5e35b6af2 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/NeedBracesCheckTest.java @@ -115,6 +115,16 @@ public class NeedBracesCheckTest extends BaseCheckTestSupport { verify(checkConfig, getPath("InputBracesSingleLineStatements.java"), expected); } + @Test + public void testSingleLineCaseDefault2() throws Exception { + final DefaultConfiguration checkConfig = + createCheckConfig(NeedBracesCheck.class); + checkConfig.addAttribute("tokens", "LITERAL_CASE, LITERAL_DEFAULT"); + checkConfig.addAttribute("allowSingleLineStatement", "true"); + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, getPath("InputNeedBracesEmptyDefault.java"), expected); + } + @Test public void testCycles() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(NeedBracesCheck.class); @@ -178,4 +188,13 @@ public class NeedBracesCheckTest extends BaseCheckTestSupport { }; verify(checkConfig, getPath("InputNeedBracesNoBodyLoops.java"), expected); } + + @Test + public void testEmptySingleLineDefaultStmt() throws Exception { + final DefaultConfiguration checkConfig = createCheckConfig(NeedBracesCheck.class); + checkConfig.addAttribute("tokens", "LITERAL_DEFAULT"); + checkConfig.addAttribute("allowSingleLineStatement", "true"); + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, getPath("InputNeedBracesEmptyDefault.java"), expected); + } } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/blocks/InputNeedBracesEmptyDefault.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/blocks/InputNeedBracesEmptyDefault.java new file mode 100644 index 000000000..d482bddc3 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/blocks/InputNeedBracesEmptyDefault.java @@ -0,0 +1,19 @@ +package com.puppycrawl.tools.checkstyle.checks.blocks; + +public class InputNeedBracesEmptyDefault { + int value; + private void main() { + switch (value) { + default: + } + } + private void main1() { + switch (value) { + case 1: + } + } +} + +@interface Example { + String priority() default "value"; +}