no-equal-arguments
Same as no-equal-arguments in Dart Code Metrics
- Group
- Suspicious
- 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
// 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);
}void testEqualArguments() { foo(value, value); foo(value, value); bar(x, x, z); bar(x, x, z); baz(a, b, a); 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); padding, padding, name: userName, email: userName,bool compare(int x, int y) { return equals(x, x);void testMultipleDuplicates(String a, String b) { process(a, a, b);void containersRegression(int rcount) { final (ra, _) = (foo(rcount, rcount), 0); lbl: { final rb = foo(rcount, rcount); final rc = switch (rcount) { 0 => foo(rcount, rcount), }; final rd = switch (foo(rcount, rcount)) { }; final re = [if (rcount > 0) foo(rcount, rcount)]; final re = [if (rcount > 0) foo(rcount, rcount)]; final rf = [...[foo(rcount, rcount)]]; final rf = [...[foo(rcount, rcount)]]; final rg = (p: foo(rcount, rcount), q: 0); c ..configure(dup, dup)Valid
// 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.
{
"linter": {
"rules": {
"suspicious": {
"no-equal-arguments": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/suspicious/no-equal-arguments: <reason>More suspicious rules
- no-equal-then-else
no-equal-then-elserecommendedFlags an
if/elseor ternary whose two branches are identical. - no-magic-string
Extract inline string literals into named variables or constants.
- no-self-comparisons
no_self_comparisonsrecommendedFlags proven self-comparisons of side-effect-free scalar values.
- no-wildcard-variable-uses
no_wildcard_variable_usesrecommendedFlags references to a wildcard variable or parameter (a name made solely of underscores, such as
_or__). - overridden-fields
overridden_fieldsrecommendedFlags instance fields that redeclare an inherited field.
- prefer-unique-test-namestest
Reports duplicate test descriptions within a group and constant names in loops.
- recursive-getters
recursive_gettersrecommendedFlags a getter that unconditionally returns itself.
- unnecessary-null-aware-assignments
unnecessary_null_aware_assignmentsrecommendedFlags
x ??= null, which can never have an effect.