avoid-redundant-argument-values

Same as avoid_redundant_argument_values in Dart lints

Group
Style
Path
lint/style/avoid-redundant-argument-values
Default
Off, opt in
Origin
Dart lints
Rule
120 of 512

Flags arguments that pass exactly the parameter's default value.

An optional parameter's default already applies when the argument is omitted, so f(flag: false) against void f({bool flag = false}) is noise. The rule compares each constant argument with the constant default of the optional parameter it binds to and reports matches. Arguments are visited from last to first, stopping after the first optional positional parameter: an earlier positional argument may be needed to reach a later one. For a redirecting factory constructor the defaults of the final redirect target apply. Required parameters and @required ones are never reported.

Defaults come from indexed callable declarations, local functions and function-valued locals, and the call method of callable objects. An optional parameter without a declared default defaults to null; a super formal inherits its super parameter's default. Members of generic declarations whose function type mentions the owner's type parameters are skipped: the analyzer invokes them through a substituted type whose parameters carry no defaults. Values are evaluated in the default's declaring library (including external named extensions) and captured local constant scope, and the caller's lexical context separately. Values that cannot be folded are skipped; the analyzer's unknown web environment booleans remain unknown even with an explicit fallback.

Invalid

example.dartdart
void configure({bool verbose = false, int retries = 3, String mode = 'fast'}) {}

void positional(int a, [int b = 1, int c = 2]) {}

const defaultLimit = 10;
void limited({int limit = defaultLimit}) {}

class Widget {
  const Widget({this.size = 1.0, this.label = ''});
  Widget.named({int count = 0}) : size = 0, label = '';
  factory Widget.redirect({double size}) = Widget;
  final double size;
  final String label;

  static const zero = 0;
  void resize({int by = zero, bool animate = true}) {}

  void selfCall() {
    resize(animate: true);
  }
}

enum Level {
  low(weight: 1),
  high(weight: 5);

  const Level({this.weight = 1});
  final int weight;
}

class Marker {
  const Marker([this.value = 'x']);
  final String value;
}

@Marker('x')
void annotated() {}

void main() {
  configure(verbose: false);
  configure(retries: 3);
  configure(mode: 'fast', verbose: true);
  positional(0, 5, 2);
  positional(0, 1);
  limited(limit: 10);
  Widget(size: 1.0);
  Widget(size: 1);
  Widget.named(count: 0);
  Widget.redirect(size: 1.0);
  const Widget(label: '');
  final w = Widget();
  w.resize(by: 0);
  w.resize(animate: !false);
}

void nullable({String? name}) {}

class Box<E> {
  void fill(E value, [int start = 0]) {}
  void clear([int start = 0]) {}
}

void more(Box<int> box) {
  nullable(name: null);
  box.clear(0);
  void local({int x = 1}) {}
  local(x: 1);
  final closure = (int x, {int y = 0}) => x + y;
  closure(1, y: 0);
}

const lexicalDefault = 2;
void capturedLocalDefault() {
  const lexicalDefault = 1;
  void local([int value = lexicalDefault]) {}
  final alias = local;
  local(1);
  alias(1);
  {
    const lexicalDefault = 3;
    local(1);
    alias(1);
  }
}

const anonymousLimit = 1;
class AnonymousReceiver {}
extension on AnonymousReceiver {
  void method([int value = anonymousLimit]) {}
}
class AnonymousCaller {
  static const anonymousLimit = 2;
  void run(AnonymousReceiver receiver) {
    receiver.method(1);
  }
}

void transitiveLocalScope() {
  const x = 1;
  const y = x;
  {
    const x = 2;
    void local([int value = y]) {}
    local(1);
  }
}

class ScopeReceiver { static const limit = 2; }
const limit = 1;
extension on ScopeReceiver {
  void run() {
    void local([int value = limit]) {}
    local(1);
  }
}

class DefaultBase {
  void method([int value = 4]) {}
}
class DefaultDerived extends DefaultBase {
  void run() {
    super.method(4);
  }
}
class DefaultReceiver {}
extension DefaultExtension on DefaultReceiver {
  void method([int value = 5]) {}
}
void alternateDefaultCalls(DefaultReceiver receiver) {
  void local([int value = 1]) {}
  local.call(1);
  receiver..method(5);
  DefaultExtension(receiver).method(5);
}

const double contextualTopOne = 1;
const double contextualTopZero = -0;
class ContextualDefaults {
  static const double one = 1;
  static const double zero = -0;
}
void contextualOne([num value = 1.0]) {}
void contextualZero([num value = -0.0]) {}
void contextualConstants() {
  const double localOne = 1;
  const double localZero = -0;
  contextualOne(contextualTopOne);
  contextualOne(ContextualDefaults.one);
  contextualOne(localOne);
  contextualZero(contextualTopZero);
  contextualZero(ContextualDefaults.zero);
  contextualZero(localZero);
}
The value of the argument is redundant because it matches the default value.
18 void selfCall() {
19 resize(animate: true);
The value of the argument is redundant because it matches the default value.
23enum Level {
24 low(weight: 1),
The value of the argument is redundant because it matches the default value.
35
36@Marker('x')
The value of the argument is redundant because it matches the default value.
39void main() {
40 configure(verbose: false);
The value of the argument is redundant because it matches the default value.
40 configure(verbose: false);
41 configure(retries: 3);
The value of the argument is redundant because it matches the default value.
41 configure(retries: 3);
42 configure(mode: 'fast', verbose: true);
The value of the argument is redundant because it matches the default value.
42 configure(mode: 'fast', verbose: true);
43 positional(0, 5, 2);
The value of the argument is redundant because it matches the default value.
43 positional(0, 5, 2);
44 positional(0, 1);
The value of the argument is redundant because it matches the default value.
44 positional(0, 1);
45 limited(limit: 10);
The value of the argument is redundant because it matches the default value.
45 limited(limit: 10);
46 Widget(size: 1.0);
The value of the argument is redundant because it matches the default value.
46 Widget(size: 1.0);
47 Widget(size: 1);
The value of the argument is redundant because it matches the default value.
47 Widget(size: 1);
48 Widget.named(count: 0);
The value of the argument is redundant because it matches the default value.
48 Widget.named(count: 0);
49 Widget.redirect(size: 1.0);
The value of the argument is redundant because it matches the default value.
49 Widget.redirect(size: 1.0);
50 const Widget(label: '');
The value of the argument is redundant because it matches the default value.
51 final w = Widget();
52 w.resize(by: 0);
The value of the argument is redundant because it matches the default value.
52 w.resize(by: 0);
53 w.resize(animate: !false);
The value of the argument is redundant because it matches the default value.
63void more(Box<int> box) {
64 nullable(name: null);
The value of the argument is redundant because it matches the default value.
64 nullable(name: null);
65 box.clear(0);
The value of the argument is redundant because it matches the default value.
66 void local({int x = 1}) {}
67 local(x: 1);
The value of the argument is redundant because it matches the default value.
68 final closure = (int x, {int y = 0}) => x + y;
69 closure(1, y: 0);
The value of the argument is redundant because it matches the default value.
76 final alias = local;
77 local(1);
The value of the argument is redundant because it matches the default value.
77 local(1);
78 alias(1);
The value of the argument is redundant because it matches the default value.
80 const lexicalDefault = 3;
81 local(1);
The value of the argument is redundant because it matches the default value.
81 local(1);
82 alias(1);
The value of the argument is redundant because it matches the default value.
93 void run(AnonymousReceiver receiver) {
94 receiver.method(1);
The value of the argument is redundant because it matches the default value.
103 void local([int value = y]) {}
104 local(1);
The value of the argument is redundant because it matches the default value.
112 void local([int value = limit]) {}
113 local(1);
The value of the argument is redundant because it matches the default value.
121 void run() {
122 super.method(4);
The value of the argument is redundant because it matches the default value.
130 void local([int value = 1]) {}
131 local.call(1);
The value of the argument is redundant because it matches the default value.
131 local.call(1);
132 receiver..method(5);
The value of the argument is redundant because it matches the default value.
132 receiver..method(5);
133 DefaultExtension(receiver).method(5);
The value of the argument is redundant because it matches the default value.
146 const double localZero = -0;
147 contextualOne(contextualTopOne);
The value of the argument is redundant because it matches the default value.
147 contextualOne(contextualTopOne);
148 contextualOne(ContextualDefaults.one);
The value of the argument is redundant because it matches the default value.
148 contextualOne(ContextualDefaults.one);
149 contextualOne(localOne);
The value of the argument is redundant because it matches the default value.
149 contextualOne(localOne);
150 contextualZero(contextualTopZero);
The value of the argument is redundant because it matches the default value.
150 contextualZero(contextualTopZero);
151 contextualZero(ContextualDefaults.zero);
The value of the argument is redundant because it matches the default value.
151 contextualZero(ContextualDefaults.zero);
152 contextualZero(localZero);

Valid

example.dartdart
void configure({bool verbose = false, int retries = 3, String? name}) {}

void positional(int a, [int b = 1, int c = 2]) {}

void required({required int count}) {}

void numeric({num value = 1}) {}

void listDefault({List<int> values = const []}) {}

class Widget {
  Widget({this.size = 1.0});
  factory Widget.redirect({double size}) = Widget.other;
  Widget.other({this.size = 2.0});
  final double size;
}

void main(bool flag, int n) {
  configure(verbose: true);
  configure(retries: 4);
  configure(name: 'n');
  configure(verbose: flag);
  positional(0, 1, 3);
  positional(0, 1, 2 + 1);
  required(count: 0);
  numeric(value: 1.0);
  listDefault(values: []);
  configure(retries: n);
  Widget(size: 2.0);
  Widget.redirect(size: 1.0);
  print(1);
}

void shadowed(void Function({bool verbose}) configure) {
  configure(verbose: false);
}

class Box<E> {
  void fill(E value, [int start = 0]) {}
}

void generic(Box<int> box, List<int> list) {
  box.fill(1, 0);
  list.setRange(0, 1, list, 0);
}

const lexicalDefault = 2;
void capturedDefaultDoesNotUseTopLevel() {
  const lexicalDefault = 1;
  void local([int value = lexicalDefault]) {}
  final alias = local;
  local(2);
  alias(2);
  {
    const lexicalDefault = 3;
    local(3);
    alias(3);
  }
}

void reusedCallableScope(bool d, List<void Function(int)> callbacks) {
  if (d) { void log([int level = 0]) {} }
  callbacks.forEach((log) => log(0));
  {
    if (d) { void log([int level = 0]) {} }
    callbacks.forEach((log) => log(0));
  }
  if (d) { void log([int level = 0]) {} }
  for (final log in callbacks) { log(0); }
}

void transitive([int value = 2]) {}
void transitiveLocalScope() {
  const x = 1;
  const y = x;
  {
    const x = 2;
    transitive(y);
    void local([int value = y]) {}
    local(2);
  }
}

class ScopeReceiver { static const limit = 2; }
const limit = 1;
extension on ScopeReceiver {
  void run() {
    void local([int value = limit]) {}
    local(2);
  }
}

class DefaultBase {
  void method([int value = 4]) {}
}
class DefaultDerived extends DefaultBase {
  void run() { super.method(5); }
}
class DefaultReceiver {}
extension DefaultExtension on DefaultReceiver {
  void method([int value = 5]) {}
}
void alternateDefaultCalls(DefaultReceiver receiver) {
  void local([int value = 1]) {}
  local.call(2);
  receiver..method(6);
  DefaultExtension(receiver).method(6);
}

Configure avoid-redundant-argument-values

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "avoid-redundant-argument-values": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/avoid-redundant-argument-values: <reason>