Skip to content

avoid_long_parameter_list

v1.0.0WarningConfigurableCode Quality

This rule flags a function taking more parameters than the configured budget.

A long parameter list is usually several values that belong together travelling separately, and every caller has to assemble them in the right order. Grouping them into a record or a small class names the thing they form and makes the call sites read.

Positional and named parameters are counted separately, with a larger budget for named — they are labelled at the call site and do not depend on order. The defaults are max_positional: 4 and max_named: 10.

This rule is in the pedantic preset.

Five positional parameters, one over the default budget. The call site is five bare values in an order nobody can check:

class Court {
const Court(this.number, this.surface);
final int number;
final String surface;
}
void schedule(
String title,
DateTime start,
DateTime end,
int courtNumber,
String surface,
) {}
void book() {
schedule('Semi-final', DateTime.now(), DateTime.now(), 3, 'clay');
}

Group the values that travel together. Three parameters, and the call site says what each one is:

class Court {
const Court(this.number, this.surface);
final int number;
final String surface;
}
typedef DateRange = ({DateTime start, DateTime end});
void schedule(String title, DateRange when, Court court) {}
void book() {
schedule(
'Semi-final',
(start: DateTime.now(), end: DateTime.now()),
const Court(3, 'clay'),
);
}

A widget-style constructor with eight named parameters is not the problem this rule exists for, so it passes at the default max_named: 10. It only starts reporting once you lower the budget below eight:

class Booking {
const Booking({
required this.id,
required this.title,
required this.start,
required this.end,
required this.court,
this.notes,
this.cancelled = false,
this.reminderSent = false,
});
final String id;
final String title;
final DateTime start;
final DateTime end;
final int court;
final String? notes;
final bool cancelled;
final bool reminderSent;
}

It cannot change its signature, so reporting it would demand an impossible fix:

abstract class Renderer {
void draw(int x, int y, int width, int height, double opacity);
}
class CanvasRenderer implements Renderer {
// Not reported — the supertype decided this list.
@override
void draw(int x, int y, int width, int height, double opacity) {}
}

Note this is checked by the presence of the @override annotation, not by resolving the supertype — an unannotated override still reports.

many_lints.yaml
rules:
avoid_long_parameter_list:
max_positional: 3
max_named: 6

The two budgets are independent. Only the exceeded kind is reported, and a declaration is reported once: positional is checked first, so a function over both budgets names the positional count.

This rule is in the pedantic preset, so it is enabled by preset: pedantic or by name:

many_lints.yaml
rules:
avoid_long_parameter_list:
enabled: true
analysis_options.yaml
many_lints:
rules:
avoid_long_parameter_list:
max_positional: 3
max_named: 6
Option Type Default Description
max_positional int 4 How many positional parameters are allowed
max_named int 10 How many named parameters are allowed

To disable this rule:

many_lints.yaml
rules:
avoid_long_parameter_list: false

To keep the rule on but skip certain paths, use per-rule exclude.