Skip to content
This repository was archived by the owner on Jul 16, 2023. It is now read-only.

Commit 0f3199e

Browse files
authored
fix: use-setstate-synchronously edge cases (#1128)
* chore: fill in expected release version * test: add new edge cases * fix: if-block await invalidates mounted check * chore: add to changelog
1 parent 1630010 commit 0f3199e

File tree

5 files changed

+45
-29
lines changed

5 files changed

+45
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* feat: support ignoring nesting for [`prefer-conditional-expressions`](https://dartcodemetrics.dev/docs/rules/common/prefer-conditional-expressions).
99
* fix: ignore Providers for ['avoid-returning-widgets'](https://dartcodemetrics.dev/docs/rules/common/avoid-returning-widgets).
1010
* feat: add [`use-setstate-synchronously`](https://dartcodemetrics.dev/docs/rules/flutter/use-setstate-synchronously).
11+
* fix: correctly invalidate edge cases for [`use-setstate-synchronously`](https://dartcodemetrics.dev/docs/rules/flutter/use-setstate-synchronously)
1112

1213
## 5.3.0
1314

lib/src/analyzers/lint_analyzer/rules/rules_list/use_setstate_synchronously/visitor.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,9 @@ class _AsyncSetStateVisitor extends RecursiveAstVisitor<void> {
6464
}
6565

6666
node.condition.visitChildren(this);
67-
final oldMounted = mounted;
6867
final newMounted = _extractMountedCheck(node.condition);
69-
7068
mounted = newMounted.or(mounted);
69+
7170
final beforeThen = mounted;
7271
node.thenStatement.visitChildren(this);
7372
final afterThen = mounted;
@@ -86,8 +85,6 @@ class _AsyncSetStateVisitor extends RecursiveAstVisitor<void> {
8685
mounted = beforeThen != afterThen
8786
? afterThen
8887
: _extractMountedCheck(node.condition, permitAnd: false);
89-
} else {
90-
mounted = oldMounted;
9188
}
9289
}
9390

@@ -103,7 +100,9 @@ class _AsyncSetStateVisitor extends RecursiveAstVisitor<void> {
103100
mounted = newMounted.or(mounted);
104101
node.body.visitChildren(this);
105102

106-
mounted = _blockDiverges(node.body) ? _tryInvert(newMounted) : oldMounted;
103+
if (_blockDiverges(node.body)) {
104+
mounted = _tryInvert(newMounted).or(oldMounted);
105+
}
107106
}
108107

109108
@override

test/src/analyzers/lint_analyzer/rules/rules_list/use_setstate_synchronously/examples/example.dart

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
class _FooState extends State<StatefulWidget> {
2-
void fetchData() async {
2+
Widget build(context) {
3+
return FooWidget(
4+
onChange: (value) async {
5+
setState(() {});
6+
await fetchData();
7+
setState(() {}); // LINT
8+
9+
if (mounted) setState(() {});
10+
},
11+
);
12+
}
13+
14+
void customConfig() async {
15+
await fetch();
16+
foobar(); // LINT
17+
this.foobar(); // LINT
18+
}
19+
20+
void pathologicalCases() async {
321
setState(() {});
422

523
await fetch();
@@ -62,24 +80,21 @@ class _FooState extends State<StatefulWidget> {
6280
return;
6381
}
6482
setState(() {}); // LINT
65-
}
6683

67-
Widget build(context) {
68-
return FooWidget(
69-
onChange: (value) async {
70-
setState(() {});
71-
await fetchData();
72-
setState(() {}); // LINT
84+
while (!mounted || foo || foo) {
85+
return;
86+
}
87+
setState(() {});
7388

74-
if (mounted) setState(() {});
75-
},
76-
);
77-
}
89+
while (mounted) {
90+
await fetch();
91+
}
92+
setState(() {}); // LINT
7893

79-
void customConfig() async {
80-
await fetch();
81-
foobar(); // LINT
82-
this.foobar(); // LINT
94+
if (mounted) {
95+
await fetch();
96+
}
97+
setState(() {}); // LINT
8398
}
8499
}
85100

test/src/analyzers/lint_analyzer/rules/rules_list/use_setstate_synchronously/use_setstate_synchronously_rule_test.dart

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ void main() {
2626

2727
RuleTestHelper.verifyIssues(
2828
issues: issues,
29-
startLines: [6, 11, 18, 33, 48, 52, 58, 64, 72],
30-
startColumns: [10, 7, 7, 5, 7, 5, 5, 5, 9],
29+
startLines: [7, 24, 29, 36, 51, 66, 70, 76, 82, 92, 97],
30+
startColumns: [9, 10, 7, 7, 5, 7, 5, 5, 5, 5, 5],
3131
locationTexts: [
3232
'setState',
3333
'setState',
@@ -38,6 +38,8 @@ void main() {
3838
'setState',
3939
'setState',
4040
'setState',
41+
'setState',
42+
'setState',
4143
],
4244
messages: [
4345
"Avoid calling 'setState' past an await point without checking if the widget is mounted.",
@@ -49,6 +51,8 @@ void main() {
4951
"Avoid calling 'setState' past an await point without checking if the widget is mounted.",
5052
"Avoid calling 'setState' past an await point without checking if the widget is mounted.",
5153
"Avoid calling 'setState' past an await point without checking if the widget is mounted.",
54+
"Avoid calling 'setState' past an await point without checking if the widget is mounted.",
55+
"Avoid calling 'setState' past an await point without checking if the widget is mounted.",
5256
],
5357
);
5458
});
@@ -77,12 +81,9 @@ void main() {
7781

7882
RuleTestHelper.verifyIssues(
7983
issues: issues,
80-
startLines: [81, 82],
84+
startLines: [16, 17],
8185
startColumns: [5, 10],
82-
locationTexts: [
83-
'foobar',
84-
'foobar',
85-
],
86+
locationTexts: ['foobar', 'foobar'],
8687
messages: [
8788
"Avoid calling 'foobar' past an await point without checking if the widget is mounted.",
8889
"Avoid calling 'foobar' past an await point without checking if the widget is mounted.",

website/docs/rules/flutter/use-setstate-synchronously.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import RuleDetails from '@site/src/components/RuleDetails';
22

3-
<RuleDetails version="UNRELEASED" severity="warning" hasConfig />
3+
<RuleDetails version="5.4.0" severity="warning" hasConfig />
44

55
Warns when [`setState`] is called past an *await point* (also known as asynchronous gap) within a subclass of State.
66

0 commit comments

Comments
 (0)