From 2e1e27adf061e282e651f08d3fbee7d9f563bb4f Mon Sep 17 00:00:00 2001 From: Mohit Attry Date: Mon, 18 Nov 2024 16:03:51 +0530 Subject: [PATCH] Issue #14872: no violation on casting fix --- config/checkstyle-checks.xml | 2 +- .../coding/UnnecessaryParenthesesCheck.java | 115 ++++++++++++------ .../coding/UnnecessaryParenthesesCheck.xml | 2 +- .../UnnecessaryParenthesesCheckTest.java | 22 ++++ .../InputUnnecessaryParenthesesCasts.java | 109 +++++++++++++++++ .../checks/coding/unnecessaryparentheses.xml | 4 + 6 files changed, 217 insertions(+), 37 deletions(-) create mode 100644 src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/unnecessaryparentheses/InputUnnecessaryParenthesesCasts.java diff --git a/config/checkstyle-checks.xml b/config/checkstyle-checks.xml index 3f1f64fb371..86aaa4c973e 100644 --- a/config/checkstyle-checks.xml +++ b/config/checkstyle-checks.xml @@ -577,7 +577,7 @@ SL_ASSIGN, SR_ASSIGN, STAR_ASSIGN, LAMBDA, TEXT_BLOCK_LITERAL_BEGIN, LAND, LOR, LITERAL_INSTANCEOF, GT, LT, GE, LE, EQUAL, NOT_EQUAL, UNARY_MINUS, UNARY_PLUS, INC, DEC, LNOT, BNOT, POST_INC, POST_DEC, BOR, BXOR, BAND, - QUESTION"/> + QUESTION, TYPECAST"/> diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheck.java index 39d6e8b1ac9..75de0d66f98 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheck.java @@ -182,7 +182,9 @@ * * POST_INC, * - * POST_DEC. + * POST_DEC, + * + * TYPECAST. * * * @@ -394,6 +396,7 @@ public int[] getDefaultTokens() { TokenTypes.BNOT, TokenTypes.POST_INC, TokenTypes.POST_DEC, + TokenTypes.TYPECAST, }; } @@ -445,6 +448,7 @@ public int[] getAcceptableTokens() { TokenTypes.BOR, TokenTypes.BAND, TokenTypes.QUESTION, + TokenTypes.TYPECAST, }; } @@ -467,42 +471,83 @@ else if (ast.getType() == TokenTypes.QUESTION) { .forEach(unnecessaryChild -> log(unnecessaryChild, MSG_EXPR)); } else if (parent.getType() != TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR) { - final int type = ast.getType(); - final boolean surrounded = isSurrounded(ast); - // An identifier surrounded by parentheses. - if (surrounded && type == TokenTypes.IDENT) { - parentToSkip = ast.getParent(); - log(ast, MSG_IDENT, ast.getText()); - } - // A literal (numeric or string) surrounded by parentheses. - else if (surrounded && TokenUtil.isOfType(type, LITERALS)) { - parentToSkip = ast.getParent(); - if (type == TokenTypes.STRING_LITERAL) { - log(ast, MSG_STRING, - chopString(ast.getText())); - } - else if (type == TokenTypes.TEXT_BLOCK_LITERAL_BEGIN) { - // Strip newline control characters to keep message as single-line, add - // quotes to make string consistent with STRING_LITERAL - final String logString = QUOTE - + NEWLINE.matcher( - ast.getFirstChild().getText()).replaceAll("\\\\n") - + QUOTE; - log(ast, MSG_STRING, chopString(logString)); - } - else { - log(ast, MSG_LITERAL, ast.getText()); - } - } - // The rhs of an assignment surrounded by parentheses. - else if (TokenUtil.isOfType(type, ASSIGNMENTS)) { - assignDepth++; - final DetailAST last = ast.getLastChild(); - if (last.getType() == TokenTypes.RPAREN) { - log(ast, MSG_ASSIGN); - } + checkASTSurrounded(ast); + } + } + + /** + * Finds and logs if {@code LITERAL},{@code IDENT}, {@code ASSIGNMENT} + * and {@TYPECAST} are surrounded by parentheses. + * + * @param ast the {@code DetailAST} to check. + */ + private void checkASTSurrounded(DetailAST ast) { + final int type = ast.getType(); + final boolean surrounded = isSurrounded(ast); + // An identifier surrounded by parentheses. + if (surrounded && type == TokenTypes.IDENT) { + parentToSkip = ast.getParent(); + log(ast, MSG_IDENT, ast.getText()); + } + // A literal (numeric or string) surrounded by parentheses. + else if (surrounded && TokenUtil.isOfType(type, LITERALS)) { + checkLiteral(ast); + } + // The rhs of an assignment surrounded by parentheses. + else if (TokenUtil.isOfType(type, ASSIGNMENTS)) { + assignDepth++; + final DetailAST last = ast.getLastChild(); + if (last.getType() == TokenTypes.RPAREN) { + log(ast, MSG_ASSIGN); } } + // A typecast surrounded by parentheses. + else if (surrounded && type == TokenTypes.TYPECAST + && isTypeCaseSurrounded(ast)) { + log(ast, MSG_EXPR); + } + } + + /** + * Checks and logs if the given {@code LITERAL} is surrounded by parentheses. + * + * @param ast the {@code DetailAST} to check. + */ + private void checkLiteral(DetailAST ast) { + final int type = ast.getType(); + parentToSkip = ast.getParent(); + if (type == TokenTypes.STRING_LITERAL) { + log(ast, MSG_STRING, + chopString(ast.getText())); + } + else if (type == TokenTypes.TEXT_BLOCK_LITERAL_BEGIN) { + // Strip newline control characters to keep message as single-line, add + // quotes to make string consistent with STRING_LITERAL + final String logString = QUOTE + + NEWLINE.matcher( + ast.getFirstChild().getText()).replaceAll("\\\\n") + + QUOTE; + log(ast, MSG_STRING, chopString(logString)); + } + else { + log(ast, MSG_LITERAL, ast.getText()); + } + } + + /** + * Checks if the given {@code TYPECAST} is surrounded by parentheses. + * + * @param ast the {@code DetailAST} to check if it is surrounded by + * parentheses. + * @return {@code true} if is surrounded by + * parentheses. + */ + private boolean isTypeCaseSurrounded(DetailAST ast) { + final DetailAST parent = ast.getParent(); + final int parentType = parent.getType(); + return parentType != TokenTypes.DOT + && parentType != TokenTypes.EXPR; + && !TokenUtil.isOfType(parentType, ASSIGNMENTS) } @Override diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/UnnecessaryParenthesesCheck.xml b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/UnnecessaryParenthesesCheck.xml index 14cb05d78e6..5081364fb73 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/UnnecessaryParenthesesCheck.xml +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/UnnecessaryParenthesesCheck.xml @@ -68,7 +68,7 @@ } </pre> - diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheckTest.java index 4fbb0405fa3..6e5997a0a56 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessaryParenthesesCheckTest.java @@ -100,6 +100,28 @@ public void testDefault() throws Exception { getPath("InputUnnecessaryParenthesesOperatorsAndCasts.java"), expected); } + @Test + public void testCasts1() throws Exception { + + final String[] expected = { + "23:18: " + getCheckMessage(MSG_EXPR), + "23:43: " + getCheckMessage(MSG_EXPR), + "30:11: " + getCheckMessage(MSG_ASSIGN), + "32:11: " + getCheckMessage(MSG_ASSIGN), + "32:22: " + getCheckMessage(MSG_EXPR), + "45:18: " + getCheckMessage(MSG_EXPR), + "61:15: " + getCheckMessage(MSG_EXPR), + "66:31: " + getCheckMessage(MSG_EXPR), + "71:40: " + getCheckMessage(MSG_EXPR), + "78:22: " + getCheckMessage(MSG_EXPR), + "89:14: " + getCheckMessage(MSG_EXPR), + "95:28: " + getCheckMessage(MSG_EXPR), + "100:26: " + getCheckMessage(MSG_EXPR), + }; + verifyWithInlineConfigParser( + getPath("InputUnnecessaryParenthesesCasts.java"), expected); + } + @Test public void test15Extensions() throws Exception { final String[] expected = { diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/unnecessaryparentheses/InputUnnecessaryParenthesesCasts.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/unnecessaryparentheses/InputUnnecessaryParenthesesCasts.java new file mode 100644 index 00000000000..942099406f0 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/unnecessaryparentheses/InputUnnecessaryParenthesesCasts.java @@ -0,0 +1,109 @@ +/* +UnnecessaryParentheses +tokens = (default)EXPR, IDENT, NUM_DOUBLE, NUM_FLOAT, NUM_INT, NUM_LONG, \ + STRING_LITERAL, LITERAL_NULL, LITERAL_FALSE, LITERAL_TRUE, ASSIGN, \ + BAND_ASSIGN, BOR_ASSIGN, BSR_ASSIGN, BXOR_ASSIGN, DIV_ASSIGN, \ + MINUS_ASSIGN, MOD_ASSIGN, PLUS_ASSIGN, SL_ASSIGN, SR_ASSIGN, STAR_ASSIGN, \ + LAMBDA, TEXT_BLOCK_LITERAL_BEGIN, LAND, LITERAL_INSTANCEOF, GT, LT, GE, \ + LE, EQUAL, NOT_EQUAL, UNARY_MINUS, UNARY_PLUS, INC, DEC, LNOT, BNOT, \ + POST_INC, POST_DEC, TYPECAST + + +*/ + +package com.puppycrawl.tools.checkstyle.checks.coding.unnecessaryparentheses; +import java.util.HashSet; +import java.util.Arrays; +public class InputUnnecessaryParenthesesCasts { + public void valid1() { + int x = 23; + int y = 44; + float k = 12f; + + int d = ((int) 100f) + 100 * 2 / ((int) 12.5f) + (int) 90f; // 2 violations + + y = (int) (22.2 * 2) / ((int) 8f + 5); + + double arg2 = 23.2; + int i = (int) arg2; + + i = ((int) arg2); // violation 'Unnecessary parentheses around assignment right-hand side' + + x = (2 * 2 /((int) k)); // 2 violations + + int par = ((int)2f * 2) / 4; + } + + public void fooConditionals() { + int x = 12; + float xy = 40f; + int y = 0; + double limit = 3.2; + boolean finished = true; + boolean result = false; + + if(x >= ((int)xy) // violation 'Unnecessary parentheses around expression.' + | (y==1 | x>=1)) { + xy--; + } + + if (!((int) xy > y) + && x < 20) { + x++; + } + + char letter = 'a'; + if (35 + (int) letter == 100) { + x++; + } + + boolean checkone = true; + if (!((boolean) checkone)) { + // violation above 'Unnecessary parentheses around expression.' + checkone = false; + } + + for (int j = 0; j >= ((int) limit); j++) { + // violation above 'Unnecessary parentheses around expression.' + y+=1; + } + + for(int j = 10; !finished && !((boolean) (j > 5)) ; j++){ + // violation above 'Unnecessary parentheses around expression.' + break; + } + + String filevalue = "FILEVALUE"; + if (!finished + || !((boolean) filevalue.contains("O"))) { + // violation above 'Unnecessary parentheses around expression.' + filevalue += "F"; + } + + if (result && finished + || ((int)23.1 + 21) == 32) { + y--; + } + + // violation below 'Unnecessary parentheses around expression.' + if(!((boolean) filevalue.contains("G")) + || finished) { + x++; + } + String[] a = { "s", "a", "1", "2", "3" }; + Arrays.stream(a) + .filter(s -> !((boolean) s.isEmpty())) + // violation above 'Unnecessary parentheses around expression.' + .toArray(String[]::new); + + Arrays.stream(a) // violation below 'Unnecessary parentheses around expression.' + .filter(s -> ((boolean) s.isEmpty())) + .toArray(String[]::new); + + new HashSet() + .stream() + .filter(f -> f > ((int) 1.1 + 200)); + + y = ((Integer) x).hashCode(); + } +} diff --git a/src/xdocs/checks/coding/unnecessaryparentheses.xml b/src/xdocs/checks/coding/unnecessaryparentheses.xml index c380ee723a4..df1df3f31b0 100644 --- a/src/xdocs/checks/coding/unnecessaryparentheses.xml +++ b/src/xdocs/checks/coding/unnecessaryparentheses.xml @@ -179,6 +179,8 @@ if ((++f) > g && a) { // violation, unnecessary paren BAND , QUESTION + , + TYPECAST . @@ -264,6 +266,8 @@ if ((++f) > g && a) { // violation, unnecessary paren POST_INC , POST_DEC + , + TYPECAST . 3.4