avoid-recursive-widget-calls

Path
lint/correctness/avoid-recursive-widget-calls
Default
On (recommended)
Origin
Falcon
Domain
flutter
Rule
119 of 512
recommendedflutter

Warns when a widget's build method constructs the same widget again.

Resolved Flutter StatelessWidget subclasses and State subclasses are checked in build only. Constructor identity, not spelling, is compared; unrelated factories, createState, and other methods are ignored. Deferred builders and conditional expressions are excluded because recursive data-driven widget trees can terminate normally.

Invalid

example.dartdart
import 'package:flutter/material.dart';
class A extends StatelessWidget { Widget build(BuildContext context) => A();  }
class B extends StatelessWidget { Widget build(BuildContext context) => new B();  }
class C extends StatelessWidget { Widget build(BuildContext context) => Container(child: C());  }
class D extends StatefulWidget { State<D> createState() => DState(); }
class DState extends State<D> { Widget build(BuildContext context) => D();  }
class E extends StatelessWidget { E.named(); Widget build(BuildContext context) => E.named();  }
This build constructs its own widget recursively; return a different widget.
1import 'package:flutter/material.dart';
2class A extends StatelessWidget { Widget build(BuildContext context) => A(); }
This build constructs its own widget recursively; return a different widget.
2class A extends StatelessWidget { Widget build(BuildContext context) => A(); }
3class B extends StatelessWidget { Widget build(BuildContext context) => new B(); }
This build constructs its own widget recursively; return a different widget.
3class B extends StatelessWidget { Widget build(BuildContext context) => new B(); }
4class C extends StatelessWidget { Widget build(BuildContext context) => Container(child: C()); }
This build constructs its own widget recursively; return a different widget.
5class D extends StatefulWidget { State<D> createState() => DState(); }
6class DState extends State<D> { Widget build(BuildContext context) => D(); }
This build constructs its own widget recursively; return a different widget.
6class DState extends State<D> { Widget build(BuildContext context) => D(); }
7class E extends StatelessWidget { E.named(); Widget build(BuildContext context) => E.named(); }

Valid

example.dartdart
import 'package:flutter/material.dart';
class A extends StatelessWidget {
 Widget build(BuildContext context) => Container();
 A copy() => A();
}
class B extends StatelessWidget { Widget build(BuildContext context) => A(); }
class C extends StatefulWidget { State<C> createState() => CState(); }
class CState extends State<C> { Widget build(BuildContext context) => A(); }
class Other { Object build() => Other(); }
Object create() => A();
class Tree extends StatelessWidget {
 Widget build(BuildContext context) => Builder(builder: (_) => Tree());
}
class Nested extends StatelessWidget {
 final int depth = 0;
 Widget build(BuildContext context) {
   if (depth > 0) return Nested();
   return Container();
 }
}
class Forest extends StatelessWidget {
 final List<int> children = [];
 Widget build(BuildContext context) => Column(children: [
   for (final child in children) Forest(),
 ]);
}
class Shadow extends StatelessWidget {
 Widget build(BuildContext context) {
   final Shadow = () => Container();
   return Shadow();
 }
}

Configure avoid-recursive-widget-calls

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "avoid-recursive-widget-calls": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/avoid-recursive-widget-calls: <reason>