widget-tree-depth
- Group
- Complexity
- Path
lint/complexity/widget-tree-depth- Default
- Off, opt in
- Origin
- Falcon
- Domain
- flutter
- Rule
- 512 of 512
Limits the depth of an inline Flutter widget construction tree.
Only resolved constructors of Flutter Widget subtypes add a level.
Canonical Flutter SizedBox constructors are transparent and do not count.
Lists, parentheses, casts, null assertions and conditional branches add no levels.
Helper calls and closures start independent trees: their bodies/arguments are
not evidence of the widget returned by the call. References to extracted
widgets likewise do not expand a tree. Each tree is reported once at its root.
max-nesting (integer, default: 8) is the maximum permitted widget depth;
the root is level one. This follows the widgets-nesting-level metric's default.
Invalid
import 'package:flutter/widgets.dart' as f;
class Panel extends f.Widget {
const Panel({required this.child});
const Panel.named({required this.child});
final f.Widget child;
}
typedef PanelAlias = Panel;
f.Widget direct() => f.Center(child: f.Center(child: f.Center(child: f.Text('deep'))));
f.Widget explicitNew() => new f.Center(child: new f.Center(child: new f.Center(child: new f.Text('deep'))));
f.Widget constant() => const f.Center(child: f.Center(child: f.Center(child: f.Text('deep'))));
f.Widget children() => f.Column(children: [f.Center(child: f.Center(child: f.Text('deep'))), f.Text('sibling')]);
f.Widget conditional(bool flag) => f.Center(child: flag ? f.Center(child: f.Center(child: f.Text('deep'))) : f.Text('shallow'));
f.Widget custom() => Panel.named(child: PanelAlias(child: f.Center(child: f.Text('deep'))));
f.Widget parentheses() => f.Center(child: ((f.Center(child: (f.Center(child: f.Text('deep')))))));
f.Widget collectionIf(bool flag) => f.Column(children: [if (flag) f.Center(child: f.Center(child: f.Text('deep')))]);
f.Widget collectionSpread() => f.Column(children: [...[f.Center(child: f.Center(child: f.Text('deep')))]]);
f.Widget sizedBoxIsTransparent() => f.Center(child: f.SizedBox(child: f.Center(child: f.Center(child: f.Text('deep')))));
class SizedBox extends f.Widget {
const SizedBox({required this.child});
final f.Widget child;
}
f.Widget unrelatedSizedBoxCounts() => SizedBox(child: SizedBox(child: SizedBox(child: f.Text('deep')))); f.Widget direct() => f.Center(child: f.Center(child: f.Center(child: f.Text('deep'))));f.Widget direct() => f.Center(child: f.Center(child: f.Center(child: f.Text('deep'))));f.Widget explicitNew() => new f.Center(child: new f.Center(child: new f.Center(child: new f.Text('deep'))));f.Widget explicitNew() => new f.Center(child: new f.Center(child: new f.Center(child: new f.Text('deep'))));f.Widget constant() => const f.Center(child: f.Center(child: f.Center(child: f.Text('deep'))));f.Widget constant() => const f.Center(child: f.Center(child: f.Center(child: f.Text('deep'))));f.Widget children() => f.Column(children: [f.Center(child: f.Center(child: f.Text('deep'))), f.Text('sibling')]);f.Widget children() => f.Column(children: [f.Center(child: f.Center(child: f.Text('deep'))), f.Text('sibling')]);f.Widget conditional(bool flag) => f.Center(child: flag ? f.Center(child: f.Center(child: f.Text('deep'))) : f.Text('shallow'));f.Widget conditional(bool flag) => f.Center(child: flag ? f.Center(child: f.Center(child: f.Text('deep'))) : f.Text('shallow'));f.Widget custom() => Panel.named(child: PanelAlias(child: f.Center(child: f.Text('deep'))));f.Widget custom() => Panel.named(child: PanelAlias(child: f.Center(child: f.Text('deep'))));f.Widget parentheses() => f.Center(child: ((f.Center(child: (f.Center(child: f.Text('deep')))))));f.Widget parentheses() => f.Center(child: ((f.Center(child: (f.Center(child: f.Text('deep')))))));f.Widget collectionIf(bool flag) => f.Column(children: [if (flag) f.Center(child: f.Center(child: f.Text('deep')))]);f.Widget collectionIf(bool flag) => f.Column(children: [if (flag) f.Center(child: f.Center(child: f.Text('deep')))]);f.Widget collectionSpread() => f.Column(children: [...[f.Center(child: f.Center(child: f.Text('deep')))]]);f.Widget collectionSpread() => f.Column(children: [...[f.Center(child: f.Center(child: f.Text('deep')))]]);f.Widget sizedBoxIsTransparent() => f.Center(child: f.SizedBox(child: f.Center(child: f.Center(child: f.Text('deep')))));}f.Widget unrelatedSizedBoxCounts() => SizedBox(child: SizedBox(child: SizedBox(child: f.Text('deep'))));Valid
import 'package:flutter/widgets.dart' as f;
f.Widget leaf() => f.Text('one');
f.Widget atLimit() => f.Center(child: f.Center(child: f.Text('three')));
f.Widget parentheses() => (((((f.Text('one'))))));
f.Widget siblings() => f.Column(children: [f.Text('a'), f.Text('b'), f.Text('c'), f.Text('d'), f.Text('e')]);
f.Widget conditional(bool flag) => f.Center(child: flag ? f.Center(child: f.Text('three')) : f.Text('two'));
f.Widget collectionFor(List<String> names) => f.Column(children: [for (final name in names) f.Text(name)]);
f.Widget extracted(f.Widget subtree) => f.Center(child: subtree);
f.Widget identity(f.Widget widget) => widget;
f.Widget helperBoundary() => f.Center(child: identity(f.Center(child: f.Center(child: f.Text('three')))));
class Deferred extends f.Widget {
const Deferred(this.builder);
final f.Widget Function() builder;
}
f.Widget callbackBoundary() => Deferred(() => f.Center(child: f.Center(child: f.Text('three'))));
void shadowed() {
final Center = (Object value) => value;
Center(Center(Center(Center('not widget construction'))));
}
class Wrapper {
Wrapper(Object value);
}
Object unrelatedConstructors() => Wrapper(Wrapper(Wrapper(Wrapper(f.Text('one')))));
f.Widget ignoredSizedBoxes() => f.SizedBox(child: f.SizedBox(child: f.SizedBox(child: f.SizedBox(child: f.Text('one')))));
f.Widget sizedBoxWithinTree() => f.Center(child: f.SizedBox(child: f.Center(child: f.Text('three'))));Configure widget-tree-depth
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"complexity": {
"widget-tree-depth": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/complexity/widget-tree-depth: <reason>More complexity rules
- avoid-classes-with-only-static-members
avoid_classes_with_only_static_membersFlags a class that declares only static members.
- avoid-collapsible-if
Flags an else-free
ifwhose only then-statement is another else-freeif. - avoid-complex-arithmetic-expressions
Reports arithmetic expressions containing too many terms.
- avoid-complex-conditions
Flags boolean expressions with more logical operands than the configured threshold.
- avoid-complex-loop-conditions
Flags loop conditions with more logical operands than the configured threshold.
- avoid-function-literals-in-foreach-calls
avoid_function_literals_in_foreach_callsFlags a function literal passed to an Iterable's
forEach. - avoid-if-with-many-branches
Reports long if/else-if chains; replace them with a switch or extracted helpers.
- avoid-inverted-boolean-expressions
avoid_inverted_boolean_expressionsrecommendedFlags a doubly-negated boolean expression such as
!!x.