Rules / Suspicious / no-equal-arguments

no-equal-arguments

lint/suspicious/no-equal-arguments
recommended
Same as no-equal-arguments · Dart Code Metrics

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);
}

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);
}
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
10void testRectFromPoints() {
11 final rect = Rect.fromPoints(start, start);
The argument has already been passed
14void testStringOperations() {
15 final check = areEqual(value, value);
The argument has already been passed
25 padding,
26 padding,
The argument has already been passed
41 name: userName,
42 email: userName,
The argument has already been passed
46bool compare(int x, int y) {
47 return equals(x, x);
The argument has already been passed
64void testMultipleDuplicates(String a, String b) {
65 process(a, a, b);

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);
}

How to configure

Set the severity of no-equal-arguments in your falcon.json:

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