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

Commit d20764e

Browse files
authored
feat: support context.mounted for use-setstate-synchronously (#1164)
* feat: support context.mounted for use-setstate-synchronously * test: fix test example
1 parent ae2674f commit d20764e

File tree

4 files changed

+49
-8
lines changed

4 files changed

+49
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
* fix: export missing parts of public API.
6+
* feat: support `context.mounted` for [`use-setstate-synchronously`](https://dcm.dev/docs/individuals/rules/flutter/use-setstate-synchronously).
67

78
## 5.5.0
89

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

+15-8
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ MountedFact _extractMountedCheck(
1414
bool permitAnd = true,
1515
bool expandOr = false,
1616
}) {
17-
// ![this.]mounted
17+
// ![this. || context.]mounted
1818
if (node is PrefixExpression &&
1919
node.operator.type == TokenType.BANG &&
20-
_isIdentifier(_thisOr(node.operand), 'mounted')) {
20+
_isIdentifier(_thisOrContextOr(node.operand), 'mounted')) {
2121
return false.asFact();
2222
}
2323

24-
// [this.]mounted
25-
if (_isIdentifier(_thisOr(node), 'mounted')) {
24+
// [this. || context.]mounted
25+
if (_isIdentifier(_thisOrContextOr(node), 'mounted')) {
2626
return true.asFact();
2727
}
2828

@@ -91,10 +91,17 @@ bool _isDivergent(Statement node, {bool allowControlFlow = false}) =>
9191
node is ExpressionStatement && node.expression is ThrowExpression;
9292

9393
@pragma('vm:prefer-inline')
94-
Expression _thisOr(Expression node) =>
95-
node is PropertyAccess && node.target is ThisExpression
96-
? node.propertyName
97-
: node;
94+
Expression _thisOrContextOr(Expression node) {
95+
if (node is PropertyAccess && node.target is ThisExpression) {
96+
return node.propertyName;
97+
}
98+
99+
if (node is PrefixedIdentifier && isBuildContext(node.prefix.staticType)) {
100+
return node.identifier;
101+
}
102+
103+
return node;
104+
}
98105

99106
bool _blockDiverges(Statement block, {required bool allowControlFlow}) => block
100107
is Block
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class _FooState extends State<StatefulWidget> {
2+
Widget build(BuildContext context) {
3+
return FooWidget(
4+
onChange: (value) async {
5+
setState(() {});
6+
await fetchData();
7+
8+
if (context.mounted) setState(() {});
9+
},
10+
);
11+
}
12+
}
13+
14+
typedef VoidCallback = void Function();
15+
16+
class State {
17+
void setState(VoidCallback callback) {}
18+
}
19+
20+
class BuildContext {
21+
bool get mounted => true;
22+
}
23+
24+
Future<String> fetchData() => Future.value('123');

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

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const _examplePath = 'use_setstate_synchronously/examples/example.dart';
88
const _issuesPath = 'use_setstate_synchronously/examples/known_errors.dart';
99
const _trySwitchPath =
1010
'use_setstate_synchronously/examples/extras_try_switch.dart';
11+
const _contextMountedPath =
12+
'use_setstate_synchronously/examples/context_mounted.dart';
1113

1214
void main() {
1315
group('UseSetStateSynchronouslyTest', () {
@@ -115,5 +117,12 @@ void main() {
115117
],
116118
);
117119
});
120+
121+
test('reports no issues for context.mounted', () async {
122+
final unit = await RuleTestHelper.resolveFromFile(_contextMountedPath);
123+
final issues = UseSetStateSynchronouslyRule().check(unit);
124+
125+
RuleTestHelper.verifyNoIssues(issues);
126+
});
118127
});
119128
}

0 commit comments

Comments
 (0)