public class UnnecessaryParenthesesCheck extends AbstractCheck
Checks if unnecessary parentheses are used in a statement or expression. The check will flag the following with warnings:
return (x); // parens around identifier
return (x + 1); // parens around return value
int x = (y / 2 + 1); // parens around assignment rhs
for (int i = (0); i < 10; i++) { // parens around literal
t -= (z + 1); // parens around assignment rhs
boolean a = (x > 7 && y > 5) // parens around expression
|| z < 9;
boolean b = (~a) > -27 // parens around ~a
&& (a-- < 30); // parens around expression
The check is not "type aware", that is to say, it can't tell if parentheses are unnecessary based on the types in an expression. The check is partially aware about operator precedence but unaware about operator associativity. It won't catch cases such as:
int x = (a + b) + c; // 1st Case
boolean p = true; // 2nd Case
int q = 4;
int r = 3;
if (p == (q <= r)) {}
In the first case, given that a, b, and c are
all int variables, the parentheses around a + b
are not needed.
In the second case, parentheses are required as q, r are
of type int and p is of type boolean
and removing parentheses will give a compile time error. Even if q
and r were boolean still there will be no violation
raised as check is not "type aware".
The partial support for operator precedence includes cases of the following type:
boolean a = true, b = true;
boolean c = false, d = false;
if ((a && b) || c) { // violation, unnecessary paren
}
if (a && (b || c)) { // ok
}
if ((a == b) && c) { // violation, unnecessary paren
}
String e = "e";
if ((e instanceof String) && a || b) { // violation, unnecessary paren
}
int f = 0;
int g = 0;
if (!(f >= g) // ok
&& (g > f)) { // violation, unnecessary paren
}
if ((++f) > g && a) { // violation, unnecessary paren
}
tokens - tokens to check
Type is java.lang.String[].
Validation type is tokenSet.
Default value is:
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,
LOR,
LITERAL_INSTANCEOF,
GT,
LT,
GE,
LE,
EQUAL,
NOT_EQUAL,
UNARY_MINUS,
UNARY_PLUS,
INC,
DEC,
LNOT,
BNOT,
POST_INC,
POST_DEC.
To configure the check:
<module name="UnnecessaryParentheses"/>
Which results in the following violations:
public int square(int a, int b){
int square = (a * b); // violation
return (square); // violation
}
int sumOfSquares = 0;
for(int i=(0); i<10; i++){ // violation
int x = (i + 1); // violation
sumOfSquares += (square(x * x)); // violation
}
double num = (10.0); //violation
List<String> list = Arrays.asList("a1", "b1", "c1");
myList.stream()
.filter((s) -> s.startsWith("c")) // violation
.forEach(System.out::println);
int a = 10, b = 12, c = 15;
boolean x = true, y = false, z= true;
if ((a >= 0 && b <= 9) // violation, unnecessary parenthesis
|| (c >= 5 && b <= 5) // violation, unnecessary parenthesis
|| (c >= 3 && a <= 7)) { // violation, unnecessary parenthesis
return;
}
if ((-a) != -27 // violation, unnecessary parenthesis
&& b > 5) {
return;
}
if (x==(a <= 15)) { // ok
return;
}
if (x==(y == z)) { // ok
return;
}
Parent is com.puppycrawl.tools.checkstyle.TreeWalker
Violation Message Keys:
unnecessary.paren.assign
unnecessary.paren.expr
unnecessary.paren.ident
unnecessary.paren.lambda
unnecessary.paren.literal
unnecessary.paren.return
unnecessary.paren.string
AutomaticBean.OutputStreamOptions| Modifier and Type | Field and Description |
|---|---|
private int |
assignDepth
Depth of nested assignments.
|
private static int[] |
ASSIGNMENTS
Token types for assignment operations.
|
private static int[] |
CONDITIONALS_AND_RELATIONAL
Token types for conditional and relational operators.
|
private static int[] |
LITERALS
Token types for literals.
|
private static int |
MAX_QUOTED_LENGTH
The maximum string length before we chop the string.
|
static java.lang.String |
MSG_ASSIGN
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_EXPR
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_IDENT
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_LAMBDA
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_LITERAL
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_RETURN
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_STRING
A key is pointing to the warning message text in "messages.properties"
file.
|
private static java.util.regex.Pattern |
NEWLINE
Compiled pattern used to match newline control characters, for replacement.
|
private DetailAST |
parentToSkip
Used to test if logging a warning in a parent node may be skipped
because a warning was already logged on an immediate child node.
|
private static java.lang.String |
QUOTE
String used to amend TEXT_BLOCK_CONTENT so that it matches STRING_LITERAL.
|
private static int[] |
UNARY_AND_POSTFIX
Token types for unary and postfix operators.
|
| Constructor and Description |
|---|
UnnecessaryParenthesesCheck() |
| Modifier and Type | Method and Description |
|---|---|
private void |
checkExpression(DetailAST ast)
Checks whether an expression is surrounded by parentheses.
|
private static java.lang.String |
chopString(java.lang.String value)
Returns the specified string chopped to
MAX_QUOTED_LENGTH
plus an ellipsis (...) if the length of the string exceeds MAX_QUOTED_LENGTH. |
int[] |
getAcceptableTokens()
The configurable token set.
|
int[] |
getDefaultTokens()
Returns the default token a check is interested in.
|
int[] |
getRequiredTokens()
The tokens that this check must be registered for.
|
private static boolean |
isExprSurrounded(DetailAST ast)
Tests if the given expression node is surrounded by parentheses.
|
private static boolean |
isLambdaSingleParameterSurrounded(DetailAST ast)
Tests if the given lambda node has a single parameter, no defined type, and is surrounded
by parentheses.
|
private static boolean |
isSurrounded(DetailAST ast)
Tests if the given
DetailAST is surrounded by parentheses. |
void |
leaveToken(DetailAST ast)
Called after all the child nodes have been process.
|
private static boolean |
unnecessaryParenAroundOperators(DetailAST ast)
Checks if conditional, relational, unary and postfix operators
in expressions are surrounded by unnecessary parentheses.
|
void |
visitToken(DetailAST ast)
Called to process a token.
|
beginTree, clearViolations, destroy, finishTree, getFileContents, getLine, getLineCodePoints, getLines, getTabWidth, getTokenNames, getViolations, init, isCommentNodesRequired, log, log, log, setFileContents, setTabWidth, setTokensfinishLocalSetup, getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, setId, setSeverityconfigure, contextualize, getConfiguration, setupChildpublic static final java.lang.String MSG_IDENT
public static final java.lang.String MSG_ASSIGN
public static final java.lang.String MSG_EXPR
public static final java.lang.String MSG_LITERAL
public static final java.lang.String MSG_STRING
public static final java.lang.String MSG_RETURN
public static final java.lang.String MSG_LAMBDA
private static final java.util.regex.Pattern NEWLINE
private static final java.lang.String QUOTE
private static final int MAX_QUOTED_LENGTH
private static final int[] LITERALS
private static final int[] ASSIGNMENTS
private static final int[] CONDITIONALS_AND_RELATIONAL
private static final int[] UNARY_AND_POSTFIX
private DetailAST parentToSkip
private int assignDepth
public UnnecessaryParenthesesCheck()
public int[] getDefaultTokens()
AbstractCheckgetDefaultTokens in class AbstractCheckTokenTypespublic int[] getAcceptableTokens()
AbstractCheckgetAcceptableTokens in class AbstractCheckTokenTypespublic int[] getRequiredTokens()
AbstractCheckgetRequiredTokens in class AbstractCheckTokenTypespublic void visitToken(DetailAST ast)
AbstractCheckvisitToken in class AbstractCheckast - the token to processpublic void leaveToken(DetailAST ast)
AbstractCheckleaveToken in class AbstractCheckast - the token leavingprivate static boolean isSurrounded(DetailAST ast)
DetailAST is surrounded by parentheses.
In short, does ast have a previous sibling whose type is
TokenTypes.LPAREN and a next sibling whose type is TokenTypes.RPAREN.ast - the DetailAST to check if it is surrounded by
parentheses.true if ast is surrounded by
parentheses.private static boolean isExprSurrounded(DetailAST ast)
ast - a DetailAST whose type is
TokenTypes.EXPR.true if the expression is surrounded by
parentheses.private void checkExpression(DetailAST ast)
ast - the DetailAST to check if it is surrounded by
parentheses.private static boolean unnecessaryParenAroundOperators(DetailAST ast)
ast - the DetailAST to check if it is surrounded by
unnecessary parentheses.true if the expression is surrounded by
unnecessary parentheses.private static boolean isLambdaSingleParameterSurrounded(DetailAST ast)
ast - a DetailAST whose type is
TokenTypes.LAMBDA.true if the lambda has a single parameter, no defined type, and is
surrounded by parentheses.private static java.lang.String chopString(java.lang.String value)
MAX_QUOTED_LENGTH
plus an ellipsis (...) if the length of the string exceeds MAX_QUOTED_LENGTH.value - the string to potentially chop.string is longer than
MAX_QUOTED_LENGTH; otherwise string.Copyright © 2001-2022. All Rights Reserved.