no-equal-arguments

Same as no-equal-arguments in Dart Code Metrics

Path
lint/suspicious/no-equal-arguments
Default
Off, opt in
Origin
Dart Code Metrics
Rule
285 of 512

Flags an argument passed more than once in the same invocation.

When two arguments to a call or constructor have identical source text — such as Point(x, x) where one was meant to be y — the repetition is usually a copy-paste slip that silently produces wrong results. Positional arguments are compared against other positional arguments by source text, and named arguments against other named arguments by their value expression (the label is ignored); a positional is never matched against a named. Literal-valued arguments are excluded, since repeating a literal like Size(48, 48) is intentional. The report lands on the last duplicate.

Invalid

example.dartdart
// Test cases for no-equal-arguments rule
// All violations are marked inline below.

void testEqualArguments() {
  foo(value, value);
  bar(x, x, z);
  baz(a, b, a);
}

// A label on the enclosing loop must not hide the equal-argument call inside.
void testLabeledLoop() {
  outer:
  for (var i = 0; i < 3; i++) {
    foo(value, value);
  }
}

void testRectFromPoints() {
  final rect = Rect.fromPoints(start, start);
}

void testStringOperations() {
  final check = areEqual(value, value);
}

// dcl reports on the LAST occurrence of the duplicate, so a hand-written
// `// ignore` on the trailing argument lines up. The annotation therefore
// belongs on the final `padding` argument, not the first.
void testLastOccurrenceLocation() {
  const value = EdgeInsets.fromLTRB(
    padding,
    other,
    padding,
    padding,
  );
}

class Math {
  static double min(double a, double b) => a < b ? a : b;

  static int gcd(int a, int b) {
    if (a == b) return a;
    return b == 0 ? a : gcd(b, a % b);
  }
}

void testDuplicateNamed() {
  createUser(
    name: userName,
    email: userName,
  );
}

bool compare(int x, int y) {
  return equals(x, x);
}

void testListOperations() {
  final list = [1, 2, 3];
  list.setRange(0, 2, list);
}

void setupAnimation(Animation anim) {
  anim.addListener(anim.forward);
}

void copyMap(Map map) {
  final copy = Map.from(map);
  map.addAll(map);
}

void testMultipleDuplicates(String a, String b) {
  process(a, a, b);
}

// Regression: the violation must still be found inside Dart 3 containers
// (pattern declaration, labeled statement, switch expression and subject,
// collection if/spread, record field).
void containersRegression(int rcount) {
  final (ra, _) = (foo(rcount, rcount), 0);
  lbl: {
    final rb = foo(rcount, rcount);
    print(rb);
  }
  final rc = switch (rcount) {
    0 => foo(rcount, rcount),
    _ => null,
  };
  final rd = switch (foo(rcount, rcount)) {
    _ => 0,
  };
  final re = [if (rcount > 0) foo(rcount, rcount)];
  final rf = [...[foo(rcount, rcount)]];
  final rg = (p: foo(rcount, rcount), q: 0);
  print([ra, rc, rd, re, rf, rg]);
}

// Regression: a cascade call carries its own argument list and is never
// rebuilt as a plain call expression, so it needs checking on its own.
class Configurable {
  void configure(int a, int b) {}
}

void cascadeRegression(Configurable c, int dup) {
  c
    ..configure(dup, dup)
    ..configure(1, 2);
}
The argument has already been passed.
4void testEqualArguments() {
5 foo(value, value);
The argument has already been passed.
5 foo(value, value);
6 bar(x, x, z);
The argument has already been passed.
6 bar(x, x, z);
7 baz(a, b, a);
The argument has already been passed.
13 for (var i = 0; i < 3; i++) {
14 foo(value, value);
The argument has already been passed.
18void testRectFromPoints() {
19 final rect = Rect.fromPoints(start, start);
The argument has already been passed.
22void testStringOperations() {
23 final check = areEqual(value, value);
The argument has already been passed.
33 padding,
34 padding,
The argument has already been passed.
49 name: userName,
50 email: userName,
The argument has already been passed.
54bool compare(int x, int y) {
55 return equals(x, x);
The argument has already been passed.
72void testMultipleDuplicates(String a, String b) {
73 process(a, a, b);
The argument has already been passed.
79void containersRegression(int rcount) {
80 final (ra, _) = (foo(rcount, rcount), 0);
The argument has already been passed.
81 lbl: {
82 final rb = foo(rcount, rcount);
The argument has already been passed.
85 final rc = switch (rcount) {
86 0 => foo(rcount, rcount),
The argument has already been passed.
88 };
89 final rd = switch (foo(rcount, rcount)) {
The argument has already been passed.
91 };
92 final re = [if (rcount > 0) foo(rcount, rcount)];
The argument has already been passed.
92 final re = [if (rcount > 0) foo(rcount, rcount)];
93 final rf = [...[foo(rcount, rcount)]];
The argument has already been passed.
93 final rf = [...[foo(rcount, rcount)]];
94 final rg = (p: foo(rcount, rcount), q: 0);
The argument has already been passed.
105 c
106 ..configure(dup, dup)

Valid

example.dartdart
// Good cases for no-equal-arguments rule
// No violations expected

void testDistinctArguments() {
  foo(value1, value2);
  bar(x, y, z);
  baz(a, b, c);
}

void testRectFromPoints() {
  final rect = Rect.fromPoints(topLeft, bottomRight);
}

void testStringOperations() {
  final result = str.replaceAll("old", "new");
  final check = areEqual(value1, value2);
}

class Math {
  static double min(double a, double b) => a < b ? a : b;

  static int gcd(int a, int b) {
    if (a == b) return a;
    return b == 0 ? a : gcd(b, a % b);
  }
}

void testDifferentNamed() {
  createUser(
    name: userName,
    email: userEmail,
  );
}

bool compare(int x, int y) {
  return equals(x, y);
}

void testListOperations() {
  final list = [1, 2, 3];
  final source = [4, 5, 6];
  list.setRange(0, 2, source);
}

void setupAnimation(Animation anim) {
  anim.addListener(() => anim.forward());
}

void copyMap(Map original) {
  final copy = Map.from(original);
  final updates = {'key': 'value'};
  copy.addAll(updates);
}

void testDistinctValues(String a, String b) {
  process(a, b, c, d);
}

void testWithDefaults(int value, {int other = 10}) {
  calculate(value, other);
}

void testFunctionCalls() {
  final x = getValue();
  final y = getOtherValue();
  combine(x, y);
}

class Pair<T> {
  final T first;
  final T second;

  Pair(this.first, this.second);

  bool areSame() => first == second;
  bool areDifferent() => first != second;
}

void testComparing(String a, String b) {
  if (a != b) {
    print('Different');
  }
}

void mergeCollections(List<int> list1, List<int> list2) {
  list1.addAll(list2);
}

// Literal arguments are compared by identity in dcl, so two equal literals are
// never flagged — passing the same literal to different parameters is routine
// and intentional, not a copy-paste bug.
void testEqualLiterals() {
  const box = Size(48, 48);
  final state = current.copyWith(isSaving: false, isSaved: false);
  showModal(useSafeArea: true, showDragHandle: true);
  final edges = EdgeInsets.fromLTRB(0, 0, 0, 0);
  final negative = clamp(-1, -1);
}

// A labeled loop whose call passes distinct arguments is not a violation.
void testLabeledDistinct() {
  outer:
  for (var i = 0; i < 3; i++) {
    foo(a, b);
  }
}

Configure no-equal-arguments

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "no-equal-arguments": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/suspicious/no-equal-arguments: <reason>
  • no-equal-then-elseno-equal-then-elserecommended

    Flags an if/else or ternary whose two branches are identical.

  • no-magic-string

    Extract inline string literals into named variables or constants.

  • no-self-comparisonsno_self_comparisonsrecommended

    Flags proven self-comparisons of side-effect-free scalar values.

  • no-wildcard-variable-usesno_wildcard_variable_usesrecommended

    Flags references to a wildcard variable or parameter (a name made solely of underscores, such as _ or __).

  • overridden-fieldsoverridden_fieldsrecommended

    Flags instance fields that redeclare an inherited field.

  • prefer-unique-test-namestest

    Reports duplicate test descriptions within a group and constant names in loops.

  • recursive-gettersrecursive_gettersrecommended

    Flags a getter that unconditionally returns itself.

  • unnecessary-null-aware-assignmentsunnecessary_null_aware_assignmentsrecommended

    Flags x ??= null, which can never have an effect.