unnecessary-parenthesis

Same as unnecessary_parenthesis in Dart lints

Group
Style
Path
lint/style/unnecessary-parenthesis
Default
On (recommended)
Origin
Dart lints
Rule
470 of 512
recommended

Flags parentheses that can be removed without changing the meaning or hurting readability.

Parentheses are always reported when they sit directly inside other parentheses, a string interpolation, the only argument of an argument list, or the condition of an if, while, do, or switch. Elsewhere they are reported around a single token (identifier, literal) or a null-aware chain unless they are needed: before .hashCode/.runtimeType/.toString()/ .noSuchMethod(), before !, before a member of a nullable-type extension, or around a null-aware index in a conditional then branch or map key.

Parentheses are kept around conditional expressions, type literals, cascades and anything inside a cascade, function expressions in a constructor field initializer, ==/!= comparisons that are assigned, returned, or yielded, a switch expression starting a statement, and expressions with internal whitespace (binary, as, is, await, assignments, ...) unless the parentheses are the whole right-hand side, return value, argument, or record field. Inside another expression they are kept when the parent is a binary, conditional, as, is, or function invocation, before a member access on a prefix/postfix expression, and where removing them would turn a set or map literal into a statement block.

Generic constructor tear-offs need parentheses when type arguments are followed by invocation arguments ((C.named)<T>()), but not when the instantiated tear-off is used as a value ((C.named)<T>). When constructor signatures are unavailable, a type-qualified target is kept unless it is known to be a nonconstructor member.

Explicit expression grouping is retained by the parser, including parentheses separated from their expression by comments. Pattern grouping is not an expression and is not reported. The official exemption for a parenthesized non-record argument to a record-typed parameter (a missing trailing comma) only applies to code that does not compile and is not modeled here.

a = (b);          // flagged
print((x));       // flagged
a = (b == c);     // ok
(b ? c : d).foo(); // ok

Invalid

example.dartdart
class Point {
  final int x;
  final int y;
  Point(this.x, int y) : y = (y);
}

int value() => 1;

void f(int a, int b, bool c, String s, List<int> list, int? n) {
  a = (b);
  print((a));
  print((a + b));
  if ((c)) {}
  while ((c)) {}
  print('${(a)}');
  var x = (1);
  var y = ('text');
  var z = (a).isEven;
  var w = (s).length;
  var v = a + ((b));
  var u = (value());
  var t = (list[0]);
  switch ((a)) {
    default:
  }
  var r = (n?.isEven) ?? false;
  print([x, y, z, w, v, u, t, r]);
}

int g(int a) {
  return (a);
}

int h(int a) => (a);

void literalTarget() {
  (1.5).floor();
  print(!(!true));
}

void cascadeClosure(List<int> list) {
  list
    ..forEach((e) {
      var even = (e.isEven);
      print(even);
    });
}

// Only the expression parentheses are reported, not wildcard-pattern grouping.
int groupedSwitch(Object value) => switch ((value)) {
  (_) => (1),
};

// A declaration pattern's grouping is not the initializer's expression grouping.
void patternDeclaration() {
  var (_) = ('a');
}
Remove the unnecessary parentheses.
3 final int y;
4 Point(this.x, int y) : y = (y);
Remove the unnecessary parentheses.
9void f(int a, int b, bool c, String s, List<int> list, int? n) {
10 a = (b);
Remove the unnecessary parentheses.
10 a = (b);
11 print((a));
Remove the unnecessary parentheses.
11 print((a));
12 print((a + b));
Remove the unnecessary parentheses.
12 print((a + b));
13 if ((c)) {}
Remove the unnecessary parentheses.
13 if ((c)) {}
14 while ((c)) {}
Remove the unnecessary parentheses.
14 while ((c)) {}
15 print('${(a)}');
Remove the unnecessary parentheses.
15 print('${(a)}');
16 var x = (1);
Remove the unnecessary parentheses.
16 var x = (1);
17 var y = ('text');
Remove the unnecessary parentheses.
17 var y = ('text');
18 var z = (a).isEven;
Remove the unnecessary parentheses.
18 var z = (a).isEven;
19 var w = (s).length;
Remove the unnecessary parentheses.
19 var w = (s).length;
20 var v = a + ((b));
Remove the unnecessary parentheses.
20 var v = a + ((b));
21 var u = (value());
Remove the unnecessary parentheses.
21 var u = (value());
22 var t = (list[0]);
Remove the unnecessary parentheses.
22 var t = (list[0]);
23 switch ((a)) {
Remove the unnecessary parentheses.
25 }
26 var r = (n?.isEven) ?? false;
Remove the unnecessary parentheses.
30int g(int a) {
31 return (a);
Remove the unnecessary parentheses.
33
34int h(int a) => (a);
Remove the unnecessary parentheses.
36void literalTarget() {
37 (1.5).floor();
Remove the unnecessary parentheses.
37 (1.5).floor();
38 print(!(!true));
Remove the unnecessary parentheses.
43 ..forEach((e) {
44 var even = (e.isEven);
Remove the unnecessary parentheses.
49// Only the expression parentheses are reported, not wildcard-pattern grouping.
50int groupedSwitch(Object value) => switch ((value)) {
Remove the unnecessary parentheses.
50int groupedSwitch(Object value) => switch ((value)) {
51 (_) => (1),
Remove the unnecessary parentheses.
55void patternDeclaration() {
56 var (_) = ('a');

Valid

example.dartdart
class Holder {
  bool Function() e;
  Holder(bool Function()? e) : e = e ?? (() => true);
}

extension NullableString on String? {
  bool get isBlank => this == null || this!.isEmpty;
}

int value() => 1;

void f(int a, int b, bool c, String? s, List<int> list, int? n, Object o, List<int>? maybeList) {
  var x = a + b;
  print(x);
  var y = (a + b) * 2;
  var z = (c ? a : b).isEven;
  var w = (a == b);
  c = (a != b);
  var v = (o as int).isEven;
  var u = !(o is int);
  var t = (List<int>).hashCode;
  var r = (n)!;
  var q = (-a).abs();
  var p = (a++).isEven;
  var m = (s?.length).hashCode;
  var k = (s?.length).toString();
  var j = (s?.trim()).isBlank;
  var i = (list..clear()).length;
  ({1, 2, 3}).forEach(print);
  (switch (a) { _ => 1 });
  print([y, z, w, v, u, t, r, q, p, m, k, j, i]);
  print(c ? (maybeList?[0]) : null);
  print({(maybeList?[0]): 1});
  final items = [...(o as List<int>)];
  print(items);
  list..add(1)..[0] = (a + b);
}

bool g(int a, int b) {
  return (a == b);
}

Iterable<bool> gen(int a, int b) sync* {
  yield (a == b);
}

int h(int a, int b) => a * (b + 1);

void cases(Object o) {
  switch (o) {
    case const (1 + 2):
      break;
  }
}

class Callback {
  bool Function() e;
  Callback() : e = (() => true);
}

// Pattern grouping is distinct from parenthesized expressions.
int wildcardPattern(Object? value) => switch (value) {
  (_) => 1,
};

int nestedWildcardPattern(Object? value) => switch (value) {
  ((/* grouping */ _)) => 1,
};

int recordPattern((int?, int?) value) => switch (value) {
  (null, final int right) => right,
  (final int left, null) => left,
  (_) => 0,
};

void statementPattern(Object? value) {
  if (value case (_)) {}
  switch (value) {
    case (_):
      break;
  }
}

// A pattern initializer has a non-expression declaration parent, unlike an
// ordinary variable initializer.
Future<void> patternInitializers(
  int a,
  int b,
  Object value,
  Future<(int, int)> Function() fetch,
) async {
  var (sum) = (a + b);
  var (cast) = (value as int);
  var (check) = (value is int);
  final (left, right) = (await fetch());
  print([sum, cast, check, left, right]);
}

Configure unnecessary-parenthesis

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "unnecessary-parenthesis": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/unnecessary-parenthesis: <reason>
  • unnecessary-raw-stringsunnecessary_raw_stringsrecommended

    Flags raw string literals that contain no backslash or $.

  • unnecessary-string-escapesunnecessary_string_escapesrecommended

    Flags backslashes that do not affect a string's value.

  • unnecessary-string-interpolationsunnecessary_string_interpolationsrecommended

    Flags a string literal whose entire content is a single interpolation of a provably non-nullable String.

  • unnecessary-thisunnecessary_thisrecommended

    Flags a redundant this. qualifier on member access.

  • unreachable-from-mainunreachable_from_main

    Report public declarations that no entry point of an executable library reaches.

  • use-colored-boxuse_colored_boxrecommendedflutter

    Prefers ColoredBox over a Container that only paints a color behind its child.

  • use-decorated-boxuse_decorated_boxrecommendedflutter

    Prefers DecoratedBox over a Container that only decorates its child.

  • use-design-system-itemuse-design-system-itemflutter

    Flags construction of a widget or type that should be replaced by its design-system equivalent.