prefer_correct_handler_name
This rule flags a method passed as an event handler that is not named _onSomething or _handleSomething.
A handler is the other half of the onTap:/onChanged: convention that prefer_correct_callback_field_name enforces on the parameter. When the parameter is onTap: and the method behind it is submit, the call site reads onTap: submit and the reader holds the mapping themselves; onTap: _onTap states it once.
Only a tear-off passed to an on... parameter is considered. A closure is not a named handler, a method called normally is not a handler at all, and a parameter that is not named on... gives the rule no anchor to judge by.
The prefix must start a new word, so _online does not satisfy on.
This rule is in the pedantic preset.
class Button { Button({this.onTap});
final void Function()? onTap;}
class CheckoutForm { void _submit() {}
Button buildButton() => Button(onTap: _submit);}class CheckoutForm { void _onTap() {}
Button buildButton() => Button(onTap: _onTap);}_handleTap is accepted too — handle is the second default prefix.
Examples
Section titled “Examples”Only a tear-off passed to an on... parameter is judged
Section titled “Only a tear-off passed to an on... parameter is judged”The rule needs both halves: a parameter named on..., and a bare method name as its value. Anything else gives it no anchor:
class Button { Button({this.onTap, this.builder});
final void Function()? onTap; final void Function()? builder;}
class CheckoutForm { void submit() {}
void run() { // Not reported — a closure is not a named handler Button(onTap: () => submit());
// Not reported — `builder` is not an `on...` parameter Button(builder: submit);
// Not reported — called normally, not passed as a handler submit(); }}The prefix must start a new word
Section titled “The prefix must start a new word”_online does not satisfy on, because l is not the start of a new word:
class CheckoutForm { void _online() {} void _onLine() {}
void run() { Button(onTap: _online); // LINT Button(onTap: _onLine); // accepted }}Dropping the private requirement
Section titled “Dropping the private requirement”require_private: true — the default — means a handler must also start with an underscore, so onTap as a method name is reported while _onTap passes. Set it to false when your widgets expose their handlers:
rules: prefer_correct_handler_name: require_private: falseclass CheckoutForm { void onTap() {}
void run() { Button(onTap: onTap); // accepted with `require_private: false` }}Adding a prefix of your own
Section titled “Adding a prefix of your own”additional_prefixes extends the defaults. Writing prefixes: instead replaces them, so on and handle stop being accepted unless you list them again:
rules: prefer_correct_handler_name: additional_prefixes: [process]class CheckoutForm { void _processTap() {}
void run() { Button(onTap: _processTap); // accepted with the config above }}Enabling this rule
Section titled “Enabling this rule”This rule is in the pedantic preset, so it is enabled by preset: pedantic or by name:
rules: prefer_correct_handler_name: enabled: trueOptions
Section titled “Options”many_lints: rules: prefer_correct_handler_name: additional_prefixes: [process] require_private: truerules: prefer_correct_handler_name: additional_prefixes: [process] require_private: true| Option | Type | Default | Description |
|---|---|---|---|
prefixes |
list | [on, handle] |
Accepted handler prefixes. Replaces the defaults |
additional_prefixes |
list | [] |
Prefixes to add without replacing the defaults |
require_private |
bool | true |
Whether a handler must also start with an underscore |
Known limitations
Section titled “Known limitations”Methods only. A top-level function or a local function passed as a handler is not reported — the value has to resolve to a method on a class.
Closures are invisible. onTap: () => submit() is never reported, however the method behind it is named.
No quick fix. Renaming a method touches every call site, which is a rename refactoring rather than a one-file edit.
Turning this rule off
Section titled “Turning this rule off”To disable this rule:
rules: prefer_correct_handler_name: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”prefer_correct_callback_field_name— Name callbacks onSomething, the way Flutter does.prefer_correct_error_name— Name exception and error classes with the matching suffix.prefer_correct_setter_parameter_name— Use one parameter name in every setter.prefer_boolean_prefixes— Name booleans as questions.