avoid-recursive-calls
- Group
- Correctness
- Path
lint/correctness/avoid-recursive-calls- Default
- Off, opt in
- Origin
- Falcon
- Rule
- 118 of 512
Reports direct self-calls in functions and methods, including guarded recursion.
Local declaration identities exclude shadowed call targets. Calls on another receiver, getters, extension dispatch, and calls inside anonymous closures are deliberately excluded rather than guessed to be recursive.
Invalid
int forever() => forever();
int recursive(int n) { return recursive(n - 1); }
void again() { again(); }
class Broken {
int run() => this.run();
static int staticRun() => staticRun();
}
void outer() {
int local() => local();
print(local);
}
int bounded(int n) => n <= 0 ? 0 : bounded(n - 1);
int guarded(int n) { if (n <= 0) return 0; return guarded(n - 1); }
Iterable<int> sequence() sync* { yield* sequence(); }
Future<void> asyncAgain() async => asyncAgain();int forever() => forever();int forever() => forever();int recursive(int n) { return recursive(n - 1); }int recursive(int n) { return recursive(n - 1); }void again() { again(); }class Broken { int run() => this.run(); int run() => this.run(); static int staticRun() => staticRun();void outer() { int local() => local();}int bounded(int n) => n <= 0 ? 0 : bounded(n - 1);int bounded(int n) => n <= 0 ? 0 : bounded(n - 1);int guarded(int n) { if (n <= 0) return 0; return guarded(n - 1); }int guarded(int n) { if (n <= 0) return 0; return guarded(n - 1); }Iterable<int> sequence() sync* { yield* sequence(); }Iterable<int> sequence() sync* { yield* sequence(); }Future<void> asyncAgain() async => asyncAgain();Valid
int delegates(int Function() delegates) => delegates();
int other() => 1;
int wrapper() => other();
class Valid {
Valid? next;
int run() => next!.run();
int shadow(int Function() shadow) => shadow();
int get recursiveGetter => recursiveGetter; // Covered by recursive-getters.
}
void nested() { void closure() { print('not recursive'); } closure(); }
int iterative(int n) { var result = 0; while (n > 0) { result += n; n--; } return result; }
void shadowed() {
final shadowed = () => 1;
print(shadowed());
}
void captured() { final callback = () => captured(); print(callback); }Configure avoid-recursive-calls
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"avoid-recursive-calls": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/avoid-recursive-calls: <reason>More correctness rules
- avoid-recursive-widget-callsrecommendedflutter
Warns when a widget's build method constructs the same widget again.
- avoid-ref-inside-state-disposeriverpod
Rejects Riverpod widget references used during State.dispose.
- avoid-ref-read-inside-buildrecommendedriverpod
Flags one-time Riverpod reads of provider state during widget build.
- avoid-ref-watch-outside-buildrecommendedriverpod
Flags Riverpod WidgetRef.watch subscriptions outside synchronous widget build bodies.
- avoid-relative-lib-imports
avoid_relative_lib_importsrecommendedDisallow relative imports that reach into a
lib/directory. - avoid-returning-widgets
avoid-returning-widgetsflutterDisallow functions and methods that return a
Widget. - avoid-type-to-string
avoid_type_to_stringrecommendedAvoid
Type.toString()in production code, where type names may be minified. - avoid-uncaught-future-errorsrecommended
Flags local futures first awaited after another await inside a try/catch.