From 8a28d063a4c13a4a2e1a2800ac00a08addc7e7d9 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Sat, 2 Sep 2017 18:02:41 -0400 Subject: [PATCH] Issue #4294: ParenPad: handle trailing semi-colons in try-with-resources --- .../ParenPadTest.java | 2 ++ .../InputParenPad.java | 9 ++++++ .../checks/whitespace/ParenPadCheck.java | 31 +++++++++++++++++-- .../checks/whitespace/ParenPadCheckTest.java | 10 ++++++ .../InputParenPadTryWithResources.java | 12 +++++++ src/xdocs/config_whitespace.xml | 18 +++++++++-- 6 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/parenpad/InputParenPadTryWithResources.java diff --git a/src/it/java/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/ParenPadTest.java b/src/it/java/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/ParenPadTest.java index 104785e9da76..06cedac0ed66 100644 --- a/src/it/java/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/ParenPadTest.java +++ b/src/it/java/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/ParenPadTest.java @@ -158,6 +158,8 @@ public void testMethodParen() throws Exception { "212:49: " + getCheckMessage(clazz, messageKeyFollowed, "("), "212:51: " + getCheckMessage(clazz, messageKeyPreceded, ")"), "212:53: " + getCheckMessage(clazz, messageKeyPreceded, ")"), + "220:36: " + getCheckMessage(clazz, messageKeyPreceded, ")"), + "221:60: " + getCheckMessage(clazz, messageKeyPreceded, ")"), }; final Configuration checkConfig = getModuleConfig("ParenPad"); final String filePath = getPath("InputParenPad.java"); diff --git a/src/it/resources/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/InputParenPad.java b/src/it/resources/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/InputParenPad.java index 5d7fc1fd8073..77399374f698 100644 --- a/src/it/resources/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/InputParenPad.java +++ b/src/it/resources/com/google/checkstyle/test/chapter4formatting/rule462horizontalwhitespace/InputParenPad.java @@ -211,4 +211,13 @@ private void except() { org.junit.Assert.assertThat( "Help! Integers don't work", // warning 0, org.hamcrest.CoreMatchers.is( 1 ) ); // warning } + + private void tryWithResources() throws Exception { + try (AutoCloseable a = null) {} // ok + try (AutoCloseable a = null; AutoCloseable b = null) {} // ok + try (AutoCloseable a = null; AutoCloseable b = null; ) {} // ok + try (AutoCloseable a = null; AutoCloseable b = null; ) {} // ok + try (AutoCloseable a = null ) {} // warning + try (AutoCloseable a = null; AutoCloseable b = null ) {} // warning + } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheck.java index bd5bc6059eab..a5cd4c1fa9c9 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheck.java @@ -28,9 +28,10 @@ /** *

Checks the padding of parentheses; that is whether a space is required * after a left parenthesis and before a right parenthesis, or such spaces are - * forbidden, with the exception that it does - * not check for padding of the right parenthesis at an empty for iterator and - * empty for initializer. + * forbidden. No check occurs at the right parenthesis after an empty for + * iterator, at the left parenthesis before an empty for initialization, or at + * the right parenthesis of a try-with-resources resource specification where + * the last resource variable has a trailing semi-colon. * Use Check {@link EmptyForIteratorPadCheck EmptyForIteratorPad} to validate * empty for iterators and {@link EmptyForInitializerPadCheck EmptyForInitializerPad} * to validate empty for initializers. Typecasts are also not checked, as there is @@ -137,6 +138,9 @@ public void visitToken(DetailAST ast) { case TokenTypes.LAMBDA: visitTokenWithOptionalParentheses(ast); break; + case TokenTypes.RESOURCE_SPECIFICATION: + visitResourceSpecification(ast); + break; default: processLeft(ast.findFirstToken(TokenTypes.LPAREN)); processRight(ast.findFirstToken(TokenTypes.RPAREN)); @@ -158,6 +162,27 @@ private void visitTokenWithOptionalParentheses(DetailAST ast) { } } + /** + * Checks parens in {@link TokenTypes#RESOURCE_SPECIFICATION}. + * @param ast the token to check. + */ + private void visitResourceSpecification(DetailAST ast) { + processLeft(ast.findFirstToken(TokenTypes.LPAREN)); + final DetailAST rparen = ast.findFirstToken(TokenTypes.RPAREN); + if (!hasPrecedingSemiColon(rparen)) { + processRight(rparen); + } + } + + /** + * Checks that a token is preceded by a semi-colon. + * @param ast the token to check + * @return whether a token is preceded by a semi-colon + */ + private static boolean hasPrecedingSemiColon(DetailAST ast) { + return ast.getPreviousSibling().getType() == TokenTypes.SEMI; + } + /** * Checks parens in {@link TokenTypes#LITERAL_FOR}. * @param ast the token to check. diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheckTest.java index 15377652b36f..a9df661709b0 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheckTest.java @@ -445,4 +445,14 @@ public void testLambdaCheckOnlyWithSpace1() throws Exception { }; verify(checkConfig, getPath("InputParenPadStartOfTheLine.java"), expected); } + + @Test + public void testTryWithResources() throws Exception { + final DefaultConfiguration checkConfig = createModuleConfig(ParenPadCheck.class); + final String[] expected = { + "9:36: " + getCheckMessage(MSG_WS_PRECEDED, ")"), + "10:60: " + getCheckMessage(MSG_WS_PRECEDED, ")"), + }; + verify(checkConfig, getPath("InputParenPadTryWithResources.java"), expected); + } } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/parenpad/InputParenPadTryWithResources.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/parenpad/InputParenPadTryWithResources.java new file mode 100644 index 000000000000..b45f2f4a31de --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/parenpad/InputParenPadTryWithResources.java @@ -0,0 +1,12 @@ +package com.puppycrawl.tools.checkstyle.checks.whitespace.parenpad; + +class InputParenPadTryWithResources { + private void tryWithResources() throws Exception { + try (AutoCloseable a = null) {} // ok + try (AutoCloseable a = null; AutoCloseable b = null) {} // ok + try (AutoCloseable a = null; AutoCloseable b = null; ) {} // ok + try (AutoCloseable a = null; AutoCloseable b = null; ) {} // ok + try (AutoCloseable a = null ) {} // warning + try (AutoCloseable a = null; AutoCloseable b = null ) {} // warning + } +} diff --git a/src/xdocs/config_whitespace.xml b/src/xdocs/config_whitespace.xml index e025bd484538..6b770c726fbe 100644 --- a/src/xdocs/config_whitespace.xml +++ b/src/xdocs/config_whitespace.xml @@ -1391,9 +1391,11 @@ import static java.math.BigInteger.ZERO;

Checks the policy on the padding of parentheses; i.e. whether a space is required after a left parenthesis and before a right - parenthesis, or such spaces are forbidden, with the exception that it does - not check for padding of the right parenthesis at an empty for iterator and - empty for initializer. + parenthesis, or such spaces are forbidden. No check occurs at + the right parenthesis after an empty for iterator, at the left + parenthesis before an empty for initialization, or at the right + parenthesis of a try-with-resources resource specification where + the last resource variable has a trailing semi-colon. Use Check EmptyForIteratorPad to validate empty for iterators and + +

+ The following cases not checked: +

+ +for ( ; i < j; i++, j--) // no check after left parenthesis +for (Iterator it = xs.iterator(); it.hasNext(); ) // no check before right parenthesis +try (Closeable resource = acquire(); ) // no check before right parenthesis + +