avoid_complex_conditions
This rule flags a boolean expression combining more &&/|| operands than the configured budget.
a && b && !c || d forces the reader to hold four facts and two precedence rules at once, and it is where an && that should have been || hides longest. Naming the parts makes the condition readable at a glance and debuggable one piece at a time.
This rule is in the pedantic preset. The default budget is max_operands: 3.
Four operands in one expression:
class Account { const Account(this.isActive, this.hasPaidBalance, this.isSuspended, this.age);
final bool isActive; final bool hasPaidBalance; final bool isSuspended; final int age;}
bool canCheckOut(Account account) { return account.isActive && account.hasPaidBalance && !account.isSuspended && account.age >= 18;}Name the two halves. The condition now reads as one sentence, and either half can be tested on its own:
class Account { const Account(this.isActive, this.hasPaidBalance, this.isSuspended, this.age);
final bool isActive; final bool hasPaidBalance; final bool isSuspended; final int age;}
bool canCheckOut(Account account) { final isInGoodStanding = account.isActive && account.hasPaidBalance; final isPermitted = !account.isSuspended && account.age >= 18;
return isInGoodStanding && isPermitted;}More examples
Section titled “More examples”The whole chain counts once
Section titled “The whole chain counts once”The diagnostic lands on the root of the chain, so a long condition reports once rather than once per operator. Parentheses do not break a chain either:
// One diagnostic, five operands — not three overlapping ones.bool ready(bool a, bool b, bool c, bool d, bool e) => (a && b) && (c || d) && e;Each !x counts as one operand, not two — only && and || add to the count.
It is not only if conditions
Section titled “It is not only if conditions”Any boolean expression is measured, wherever it appears — a return, a
variable initialiser, an argument:
class Filter { Filter(this.a, this.b, this.c, this.d);
final bool a; final bool b; final bool c; final bool d;
// Reported: four operands in a field initialiser. late final bool matches = a && b && c && d;}operator == is never reported
Section titled “operator == is never reported”It is one && per field by construction, and splitting it would scatter an
equality check that reads as a unit. This accounted for most of the hits when
the rule was first run against a production codebase:
class Booking { const Booking(this.id, this.court, this.start, this.end, this.notes);
final String id; final int court; final DateTime start; final DateTime end; final String? notes;
// Not reported, however many fields it grows to. @override bool operator ==(Object other) => other is Booking && other.id == id && other.court == court && other.start == start && other.end == end && other.notes == notes;
@override int get hashCode => Object.hash(id, court, start, end, notes);}The exemption covers anything inside a member named ==, not just its return
expression.
Tightening the budget
Section titled “Tightening the budget”Three operands is one && chain a reader can still hold. Drop it to two if you
want every compound condition named:
rules: avoid_complex_conditions: max_operands: 2Enabling 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: avoid_complex_conditions: enabled: trueOptions
Section titled “Options”many_lints: rules: avoid_complex_conditions: max_operands: 2rules: avoid_complex_conditions: max_operands: 2| Option | Type | Default | Description |
|---|---|---|---|
max_operands |
int | 3 |
How many &&/` |
Turning this rule off
Section titled “Turning this rule off”To disable this rule:
rules: avoid_complex_conditions: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”avoid_deep_nesting— Keep control flow within a nesting budget.avoid_high_cyclomatic_complexity— Keep a function within a complexity budget.avoid_long_functions— Keep function bodies within a line budget.max_statements— Keep a function within a statement budget.