diff --git a/lib/src/rules/unnecessary_parenthesis.dart b/lib/src/rules/unnecessary_parenthesis.dart index 2edf0c56f..38daa103a 100644 --- a/lib/src/rules/unnecessary_parenthesis.dart +++ b/lib/src/rules/unnecessary_parenthesis.dart @@ -131,11 +131,25 @@ class _Visitor extends SimpleAstVisitor { } } - if (parent is ParenthesizedExpression) { + // Directly wrapped into parentheses already - always report. + if (parent is ParenthesizedExpression || + parent is InterpolationExpression || + (parent is ArgumentList && parent.arguments.length == 1) || + (parent is IfStatement && node == parent.condition) || + (parent is IfElement && node == parent.condition) || + (parent is WhileStatement && node == parent.condition) || + (parent is DoStatement && node == parent.condition) || + (parent is SwitchStatement && node == parent.expression) || + (parent is SwitchExpression && node == parent.expression)) { rule.reportLint(node); return; } + // `(foo ? bar : baz)` is OK. + if (expression is ConditionalExpression) { + return; + } + // `a..b = (c..d)` is OK. if (expression is CascadeExpression || node.thisOrAncestorMatching( @@ -152,6 +166,19 @@ class _Visitor extends SimpleAstVisitor { return; } + // `foo = (a == b)` is OK, `return (count != 0)` is OK. + if (expression is BinaryExpression && + (expression.operator.type == TokenType.EQ_EQ || + expression.operator.type == TokenType.BANG_EQ)) { + if (parent is AssignmentExpression || + parent is VariableDeclaration || + parent is ReturnStatement || + parent is YieldStatement || + parent is ConstructorFieldInitializer) { + return; + } + } + if (parent is Expression) { if (parent is BinaryExpression) return; if (parent is ConditionalExpression) return; diff --git a/test_data/rules/unnecessary_parenthesis.dart b/test_data/rules/unnecessary_parenthesis.dart index de09af84b..a1245b8e0 100644 --- a/test_data/rules/unnecessary_parenthesis.dart +++ b/test_data/rules/unnecessary_parenthesis.dart @@ -125,8 +125,54 @@ main() async { (a?.abs())!; (a?..abs())!; (a?[0])!; + + print(!({"a": "b"}["a"]!.isEmpty)); // LINT + + print((1 + 2)); // LINT + + print((1 == 1 ? 2 : 3)); // LINT + print('a'.substring((1 == 1 ? 2 : 3), 4)); // OK + var a1 = (1 == 1 ? 2 : 3); // OK + print('${(1 == 1 ? 2 : 3)}'); // LINT + print([(1 == 1 ? 2 : 3)]); // OK + + var a2 = (1 == 1); // OK + a2 = (1 == 1); // OK + a2 = (1 == 1) || "".isEmpty; // OK + var a3 = (1 + 1); // LINT } +bool testTernaryAndEquality() { + if ((1 == 1 ? true : false)) // LINT + { + return (1 != 1); // OK + } else if ((1 == 1 ? true : false)) // LINT + { + return (1 > 1); // LINT + } + while ((1 == 1)) // LINT + { + print(''); + } + switch ((5 == 6)) // LINT + { + case true: + return false; + default: + return true; + } +} + +class TestConstructorFieldInitializer { + bool _x, _y; + TestConstructorFieldInitializer() + : _x = (1 == 2), // OK + _y = (true && false); // LINT +} + +int test2() => (1 == 1 ? 2 : 3); // OK +bool test3() => (1 == 1); // LINT + Invocation? invocation() => null; m({p}) => null;