Skip to content

Commit 5c77f66

Browse files
refactor: add CR suggestions
1 parent d68ba72 commit 5c77f66

File tree

2 files changed

+52
-69
lines changed

2 files changed

+52
-69
lines changed

packages/leancode_lint/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,11 @@ None.
343343

344344
### `avoid_missing_dispose`
345345

346-
**DO** dispose of disposable resources in StatefulWidget State classes.
346+
**DO** dispose of resources that require `dispose()` in StatefulWidget `State` classes.
347347

348-
Disposable resources like controllers, and focus nodes must be properly disposed in the `dispose()` method to prevent memory leaks.
348+
Resources such as controllers and focus nodes must be disposed in the `dispose()` method to prevent memory leaks.
349349

350-
**BAD:**
350+
**BAD:**`
351351

352352
```dart
353353
class MyWidgetState extends State<MyWidget> {

packages/leancode_lint/lib/lints/avoid_missing_dispose.dart

Lines changed: 49 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ class _IgnoredTypes {
1919
}
2020

2121
class AvoidMissingDisposeConfig {
22-
const AvoidMissingDisposeConfig({
23-
this.ignoredTypes = const {},
24-
this.ignoredInstancesCheckers = const [],
25-
});
22+
const AvoidMissingDisposeConfig({this.ignoredTypesCheckers = const []});
2623

2724
factory AvoidMissingDisposeConfig.fromConfig(Map<String, YamlList?> json) {
2825
final ignoredTypes =
@@ -36,8 +33,7 @@ class AvoidMissingDisposeConfig {
3633
.toSet() ??
3734
const {};
3835
return AvoidMissingDisposeConfig(
39-
ignoredTypes: ignoredTypes,
40-
ignoredInstancesCheckers: [
36+
ignoredTypesCheckers: [
4137
for (final _IgnoredTypes(:name, :packageName) in ignoredTypes)
4238
if (packageName.startsWith('dart:'))
4339
TypeChecker.fromUrl('$packageName#$name')
@@ -47,8 +43,7 @@ class AvoidMissingDisposeConfig {
4743
);
4844
}
4945

50-
final Set<_IgnoredTypes> ignoredTypes;
51-
final List<TypeChecker> ignoredInstancesCheckers;
46+
final List<TypeChecker> ignoredTypesCheckers;
5247
}
5348

5449
/// Checks for proper disposal of resources in StatefulWidget classes.
@@ -144,26 +139,21 @@ class AvoidMissingDispose extends DartLintRule {
144139

145140
if (_isInReturnWidget(node)) {
146141
reporter.atNode(node, code);
147-
return;
148142
}
149143
});
150144
}
151145

152-
bool _isIgnoredInstance(InterfaceType type) {
153-
return config.ignoredInstancesCheckers.any(
154-
(checker) => checker.isExactly(type.element),
155-
);
156-
}
146+
bool _isIgnoredInstance(InterfaceType type) => config.ignoredTypesCheckers
147+
.any((checker) => checker.isExactly(type.element));
157148

158149
InterfaceType? _getFieldDeclarationType(FieldDeclaration field) {
159150
if (field.fields.type?.type case final InterfaceType type) {
160151
return type;
161152
}
162-
if (field.fields.variables.first.initializer?.staticType
163-
case final InterfaceType? type) {
164-
return type;
165-
}
166-
return null;
153+
return switch (field.fields.variables.first.initializer?.staticType) {
154+
final InterfaceType type => type,
155+
_ => null,
156+
};
167157
}
168158

169159
bool _isFieldUsedByConstructor(
@@ -198,29 +188,26 @@ class AvoidMissingDispose extends DartLintRule {
198188

199189
ConstructorDeclaration? _getConstructorDeclaration(
200190
ClassDeclaration classNode,
201-
) {
202-
return classNode.members.whereType<ConstructorDeclaration>().firstOrNull;
203-
}
191+
) => classNode.members.whereType<ConstructorDeclaration>().firstOrNull;
204192

205193
ClassDeclaration? _getContainingClass(AstNode node) {
206194
var classNode = node.parent;
207195
while (classNode != null && classNode is! ClassDeclaration) {
208196
classNode = classNode.parent;
209197
}
210-
if (classNode case final ClassDeclaration classNode) {
211-
return classNode;
212-
}
213-
return null;
198+
return switch (classNode) {
199+
final ClassDeclaration classNode => classNode,
200+
_ => null,
201+
};
214202
}
215203

216-
bool _isDisposable(InterfaceType type) {
217-
return type.methods2.any((method) => method.name3 == 'dispose') ||
218-
type.element3.inheritedMembers.entries.any(
219-
(entry) =>
220-
entry.key.name == 'dispose' &&
221-
entry.value.baseElement is MethodElement2,
222-
);
223-
}
204+
bool _isDisposable(InterfaceType type) =>
205+
type.methods2.any((method) => method.name3 == 'dispose') ||
206+
type.element3.inheritedMembers.entries.any(
207+
(entry) =>
208+
entry.key.name == 'dispose' &&
209+
entry.value.baseElement is MethodElement2,
210+
);
224211

225212
bool _isWidgetType(InterfaceType type) {
226213
const widgetTypeChecker = TypeChecker.fromName(
@@ -236,14 +223,16 @@ class AvoidMissingDispose extends DartLintRule {
236223
AstNode? currentNode = node;
237224
var returnsWidget = false;
238225
var isInReturn = false;
226+
227+
bool isCurrentNodeReturn() =>
228+
currentNode is ReturnStatement || currentNode is ExpressionFunctionBody;
229+
239230
while (currentNode != null && !(returnsWidget && isInReturn)) {
240-
if (!isInReturn &&
241-
(currentNode is ReturnStatement ||
242-
currentNode is ExpressionFunctionBody)) {
231+
if (!isInReturn && isCurrentNodeReturn()) {
243232
isInReturn = true;
244233
}
245234
if (currentNode case MethodDeclaration(
246-
returnType: NamedType(type: final InterfaceType type),
235+
returnType: NamedType(:final InterfaceType type),
247236
) when _isWidgetType(type)) {
248237
returnsWidget = true;
249238
}
@@ -253,28 +242,23 @@ class AvoidMissingDispose extends DartLintRule {
253242
return returnsWidget && isInReturn;
254243
}
255244

256-
bool _isStateOfWidget(ClassDeclaration classNode) {
257-
const stateTypeChecker = TypeChecker.fromName(
258-
'State',
259-
packageName: 'flutter',
260-
);
261-
return switch (classNode.declaredElement) {
262-
final element? =>
263-
stateTypeChecker.isExactly(element) ||
264-
stateTypeChecker.isSuperOf(element),
265-
_ => false,
266-
};
267-
}
268-
269-
bool _isWidgetClass(ClassDeclaration classNode) {
270-
const widgetTypeChecker = TypeChecker.fromName(
271-
'Widget',
272-
packageName: 'flutter',
273-
);
245+
bool _isStateOfWidget(ClassDeclaration classNode) =>
246+
switch (classNode.declaredElement) {
247+
final element? => const TypeChecker.fromName(
248+
'State',
249+
packageName: 'flutter',
250+
).isAssignableFrom(element),
251+
_ => false,
252+
};
274253

275-
return widgetTypeChecker.isExactly(classNode.declaredElement!) ||
276-
widgetTypeChecker.isSuperOf(classNode.declaredElement!);
277-
}
254+
bool _isWidgetClass(ClassDeclaration classNode) =>
255+
switch (classNode.declaredElement) {
256+
final element? => const TypeChecker.fromName(
257+
'Widget',
258+
packageName: 'flutter',
259+
).isAssignableFrom(element),
260+
_ => false,
261+
};
278262
}
279263

280264
class _DisposeExpressionsGatherer extends GeneralizingAstVisitor<void> {
@@ -318,8 +302,8 @@ class _AddDisposeMethod extends DartFix {
318302
List<AnalysisError> others,
319303
) {
320304
if (analysisError.data case _AvoidMissingDisposeAnalysisData(
321-
classNode: final classNode,
322-
instanceName: final instanceName,
305+
:final classNode,
306+
:final instanceName,
323307
)) {
324308
final disposeMethodNode = _getStateDisposeMethod(classNode);
325309
if (disposeMethodNode?.body case BlockFunctionBody(
@@ -341,11 +325,10 @@ class _AddDisposeMethod extends DartFix {
341325
}
342326
}
343327

344-
MethodDeclaration? _getStateDisposeMethod(ClassDeclaration classNode) {
345-
return classNode.members.whereType<MethodDeclaration>().firstWhereOrNull(
346-
(member) => member.name.lexeme == 'dispose',
347-
);
348-
}
328+
MethodDeclaration? _getStateDisposeMethod(ClassDeclaration classNode) =>
329+
classNode.members.whereType<MethodDeclaration>().firstWhereOrNull(
330+
(member) => member.name.lexeme == 'dispose',
331+
);
349332
}
350333

351334
class _AvoidMissingDisposeAnalysisData {

0 commit comments

Comments
 (0)