Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c600b39
feat: add avoid_missing_dispose lint
Artur-Wisniewski Jul 31, 2025
fcc23ae
feat: update test with missing dispose
Artur-Wisniewski Jul 31, 2025
2ccd6a0
feat: Add avoid missing dispose lint fix
Artur-Wisniewski Jul 31, 2025
d59f090
feat: add readme avoid missing dispose
Artur-Wisniewski Aug 1, 2025
9c6320c
feat: add ignored_instances config to avoid missing dispose lint
Artur-Wisniewski Aug 1, 2025
554d33b
chore: pr fixes
Artur-Wisniewski Aug 1, 2025
3a8f573
chore: pr fixes
Artur-Wisniewski Aug 1, 2025
b1f39f3
feat: remove nestedDispose example
Artur-Wisniewski Aug 1, 2025
fd57f03
feat: add ignored instance from package
Artur-Wisniewski Aug 1, 2025
c89f6dc
refactor: add dispose ignore for file
Artur-Wisniewski Aug 1, 2025
eb50a43
refactor: adding where type hint from CR
Artur-Wisniewski Aug 1, 2025
0f2d6ba
refactor: pattern matching DartFix class
Artur-Wisniewski Aug 1, 2025
62c8af1
refactor: pattern matching DartFix class
Artur-Wisniewski Aug 1, 2025
fd08a41
refactor: CR hint
Artur-Wisniewski Aug 1, 2025
f4309dc
refactor: CR hint with typeChecker
Artur-Wisniewski Aug 1, 2025
9f54966
feat: used type checker instead manually checking if class is a widget
Artur-Wisniewski Aug 1, 2025
34a0e67
refactor: replace as with cast method
Artur-Wisniewski Aug 12, 2025
538a026
refactor: rename ignored instances to ignored types
Artur-Wisniewski Aug 12, 2025
e7c94a8
refactor: add CR suggestions
Artur-Wisniewski Aug 12, 2025
3dcd430
feat: add close dispose cancel configuration
Artur-Wisniewski Aug 22, 2025
6783459
refactor: change name from avoid_missing_dispose to missing_cleanup
Artur-Wisniewski Aug 22, 2025
1030a5f
refactor: leancode_lint imports order
Artur-Wisniewski Aug 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions packages/leancode_lint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,85 @@ class MyWidget extends StatelessWidget {

None

### `missing_cleanup`

**DO** cleanup of resources that require `dispose()`, `close()` or `cancel()` in StatefulWidget `State` classes.

Resources such as controllers, stream controllers or focus nodes must be cleanup in the `dispose()` method to prevent memory leaks.

**BAD:**`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**BAD:**`
**BAD:**


```dart
class MyWidgetState extends State<MyWidget> {
late final TextEditingController controller = TextEditingController();

@override
Widget build(BuildContext context) {
return TextField(controller: controller);
}
}
```

**BAD:**

```dart
class MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return TextField(controller: TextEditingController());
}
}
```

**GOOD:**

```dart
class MyWidgetState extends State<MyWidget> {
late final TextEditingController controller;

@override
void initState() {
super.initState();
controller = TextEditingController();
}
Comment on lines +508 to +512
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this GOOD example confusing: is it good because of the dispose in the void dispose() method of the Widget or is it good because the controller is initialized in void initState()? I would minimize the diff between the BAD and GOOD example


@override
Widget build(BuildContext context) {
return TextField(controller: controller);
}

@override
void dispose() {
controller.dispose();
super.dispose();
}
}
```

#### Configuration

```yaml
custom_lint:
rules:
- missing_cleanup:
ignored_types:
- ignore: AnimationController
from_package: flutter
cleanup_methods:
close: true
dispose: true
cancel: true

```

- `ignored_types` - an optional YamlList - skips dispose checks for specified types. This allows disabling the lint rule for classes where dispose method checks are not needed.
- `ignore` - A required String - name of the instance to ignore
- `from_package` - A required String - name of the source package
- `cleanup_methods` - an optional YamlMap - controls which disposal methods the lint rule should recognize and check for. By default, the rule looks for `dispose`, `close`, and `cancel` methods. You can selectively enable or disable checking for each of these methods.
Comment on lines +543 to +546
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not use package:yaml jargon here (YamlList, YamlMap). End users don't know what that is. Just saying it is a list and respectively a map with keys X Y Z is enough

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of this configuration? What is the usecase of disabling some of them globally (rather than putting a type in the ignored_types list)?

- `dispose` - A boolean (default: true) - whether to check for `dispose()` method calls
- `close` - A boolean (default: true) - whether to check for `close()` method calls
- `cancel` - A boolean (default: true) - whether to check for `cancel()` method calls

## Assists

Assists are IDE refactorings not related to a particular issue. They can be triggered by placing your cursor over a relevant piece of code and opening the code actions dialog. For instance, in VSCode this is done with <kbd>ctrl</kbd>+<kbd>.</kbd> or <kbd>⌘</kbd>+<kbd>.</kbd>.
Expand Down
2 changes: 2 additions & 0 deletions packages/leancode_lint/lib/leancode_lint.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:leancode_lint/lints/avoid_single_child_in_multi_child_widget.dar
import 'package:leancode_lint/lints/catch_parameter_names.dart';
import 'package:leancode_lint/lints/constructor_parameters_and_fields_should_have_the_same_order.dart';
import 'package:leancode_lint/lints/hook_widget_does_not_use_hooks.dart';
import 'package:leancode_lint/lints/missing_cleanup.dart';
import 'package:leancode_lint/lints/prefer_center_over_align.dart';
import 'package:leancode_lint/lints/prefix_widgets_returning_slivers.dart';
import 'package:leancode_lint/lints/start_comments_with_space.dart';
Expand All @@ -34,6 +35,7 @@ class _Linter extends PluginBase {
const UsePadding(),
const UseDedicatedMediaQueryMethods(),
const PreferCenterOverAlign(),
MissingCleanup.fromConfigs(configs),
];

@override
Expand Down
Loading