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

Commit 5618062

Browse files
committed
feat: method config for use-setstate-synchronously
1 parent 3e560c5 commit 5618062

File tree

5 files changed

+45
-9
lines changed

5 files changed

+45
-9
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
part of 'use_setstate_synchronously_rule.dart';
2+
3+
Set<String> readMethods(Map<String, Object> options) {
4+
final fromConfig = options['methods'];
5+
6+
return fromConfig is List
7+
? fromConfig.whereType<String>().toSet()
8+
: {'setState'};
9+
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@ import '../../rule_utils.dart';
1313

1414
part 'fact.dart';
1515
part 'helpers.dart';
16+
part 'config.dart';
1617
part 'visitor.dart';
1718

1819
class UseSetStateSynchronouslyRule extends FlutterRule {
1920
static const ruleId = 'use-setstate-synchronously';
20-
static const _warning =
21-
"Avoid calling 'setState' past an await point without checking if the widget is mounted.";
21+
22+
Set<String> methods;
2223

2324
UseSetStateSynchronouslyRule([Map<String, Object> options = const {}])
24-
: super(
25+
: methods = readMethods(options),
26+
super(
2527
id: ruleId,
2628
severity: readSeverity(options, Severity.warning),
2729
excludes: readExcludes(options),
@@ -30,14 +32,15 @@ class UseSetStateSynchronouslyRule extends FlutterRule {
3032

3133
@override
3234
Iterable<Issue> check(InternalResolvedUnitResult source) {
33-
final visitor = _Visitor();
35+
final visitor = _Visitor(methods: methods);
3436
source.unit.visitChildren(visitor);
3537

3638
return visitor.nodes
3739
.map((node) => createIssue(
3840
rule: this,
3941
location: nodeLocation(node: node, source: source),
40-
message: _warning,
42+
message: "Avoid calling '${node.name}' past an await point "
43+
'without checking if the widget is mounted.',
4144
))
4245
.toList(growable: false);
4346
}

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
part of 'use_setstate_synchronously_rule.dart';
22

33
class _Visitor extends RecursiveAstVisitor<void> {
4+
final Set<String> methods;
5+
_Visitor({required this.methods});
6+
47
final nodes = <SimpleIdentifier>[];
58

69
@override
@@ -15,13 +18,18 @@ class _Visitor extends RecursiveAstVisitor<void> {
1518
if (!node.isAsynchronous) {
1619
return super.visitBlockFunctionBody(node);
1720
}
18-
final visitor = _AsyncSetStateVisitor();
21+
final visitor = _AsyncSetStateVisitor(validateMethod: methods.contains);
1922
node.visitChildren(visitor);
2023
nodes.addAll(visitor.nodes);
2124
}
2225
}
2326

2427
class _AsyncSetStateVisitor extends RecursiveAstVisitor<void> {
28+
static bool _noop(String _) => false;
29+
30+
bool Function(String) validateMethod;
31+
_AsyncSetStateVisitor({this.validateMethod = _noop});
32+
2533
MountedFact mounted = true.asFact();
2634
final nodes = <SimpleIdentifier>[];
2735

@@ -36,8 +44,8 @@ class _AsyncSetStateVisitor extends RecursiveAstVisitor<void> {
3644
// [this.]setState()
3745
final mounted_ = mounted.value ?? false;
3846
if (!mounted_ &&
39-
node.methodName.name == 'setState' &&
40-
node.target is ThisExpression?) {
47+
(node.target is ThisExpression?) &&
48+
validateMethod(node.methodName.name)) {
4149
nodes.add(node.methodName);
4250
}
4351

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

Lines changed: 16 additions & 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" />
3+
<RuleDetails version="UNRELEASED" 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

@@ -42,6 +42,21 @@ Additional resources:
4242
- [`use_build_context_synchronously`](https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html),
4343
a lint that checks for async usages of `BuildContext`
4444

45+
### ⚙️ Config example {#config-example}
46+
47+
```yaml
48+
dart_code_metrics:
49+
...
50+
rules:
51+
...
52+
- use-setstate-synchronously:
53+
methods:
54+
- setState
55+
- yourMethod
56+
```
57+
58+
configures the methods `setState` and `yourMethod` to be scanned for unchecked async calls.
59+
4560
### Example {#example}
4661

4762
**❌ Bad:**

website/docs/rules/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ Rules are grouped by category to help you understand their purpose. Each rule ha
602602
type="flutter"
603603
severity="warning"
604604
version="UNRELEASED"
605+
hasConfig
605606
>
606607
Warns when <code>setState</code> is called past an await point.
607608
</RuleEntry>

0 commit comments

Comments
 (0)