Skip to content

Commit

Permalink
feat(bloc_lint): move bloc_lint package from vmichalak repository to …
Browse files Browse the repository at this point in the history
…bloc monorepo

Implements: #4264
  • Loading branch information
vmichalak committed Nov 10, 2024
1 parent 07b0621 commit 87ccd4c
Show file tree
Hide file tree
Showing 39 changed files with 865 additions and 1 deletion.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,7 @@ mason-lock.json
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock
!/dev/ci/**/Gemfile.lock

# Custom_lint related.
custom_lint.log
3 changes: 3 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ analyzer:
strict-inference: true
strict-raw-types: true

plugins:
- custom_lint

errors:
close_sinks: ignore
missing_required_param: error
Expand Down
Empty file added packages/bloc_lint/.gitignore
Empty file.
11 changes: 11 additions & 0 deletions packages/bloc_lint/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## 0.1.0 - 2024-11-10

- Initial release
- New rules implemented:
- avoid_public_methods_on_bloc
- avoid_public_properties_on_bloc_and_cubit
- event_base_class_suffix
- prefer_multi_bloc_listener
- prefer_multi_bloc_provider
- prefer_multi_repository_provider
- state_base_class_suffix
21 changes: 21 additions & 0 deletions packages/bloc_lint/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Valentin Michalak

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
40 changes: 40 additions & 0 deletions packages/bloc_lint/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Bloc Lint
===

Custom linter rules for Flutter projects using the [bloc library](https://bloclibrary.dev/). This package is based on
[dart_custom_lint](https://github.com/invertase/dart_custom_lint) package.

## Usage

Add the following to your `pubspec.yaml` file:

```yaml
dev_dependencies:
custom_lint: ^0.7.0
bloc_lint: ^0.1.0
```
Add the following to your `analysis_options.yaml` file:

```yaml
analyzer:
plugins:
- custom_lint
```

That's it! After running pub get (and possibly restarting their IDE), users should now see our custom lints in their
Dart files. You can also run `dart pub custom_lint` to run the linter in your CLI.

## Tests

The example folder contains a dart project to unit test the rules. (see custom_lint readme for more info)

## Implemented Rules

- [avoid_public_methods_on_bloc](doc/rules/avoid_public_methods_on_bloc.md)
- [avoid_public_properties_on_bloc_and_cubit](doc/rules/avoid_public_properties_on_bloc_and_cubit.md)
- [event_base_class_suffix](doc/rules/event_base_class_suffix.md)
- [prefer_multi_bloc_listener](doc/rules/prefer_multi_bloc_listener.md)
- [prefer_multi_bloc_provider](doc/rules/prefer_multi_bloc_provider.md)
- [prefer_multi_repository_provider](doc/rules/prefer_multi_repository_provider.md)
- [state_base_class_suffix](doc/rules/state_base_class_suffix.md)
27 changes: 27 additions & 0 deletions packages/bloc_lint/doc/rules/avoid_public_methods_on_bloc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
avoid_public_method_on_bloc
===
severity: WARNING

Avoid public methods on `Bloc` classes.

## Example:

**BAD**:

```dart
class MyBloc extends Bloc<int, int> {
MyBloc(super.initialState);
void test() {}
}
```

**GOOD**:

```dart
class MyBloc extends Bloc<int, int> {
MyBloc(super.initialState);
void _test() {}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
avoid_public_properties_on_bloc_and_cubit
===
severity: WARNING

Avoid public properties on `Bloc` and `Cubit`, prefer emit state or use private value.

## Example:

**BAD**:

```dart
class MyCubit extends Cubit<int> {
MyCubit() : super(0);
int value = 1;
}
```

**GOOD**:
```dart
class MyCubit extends Cubit<int> {
MyCubit() : super(0);
void init() {
emit(1);
}
}
```

or

```dart
class MyCubit extends Cubit<int> {
MyCubit() : super(0);
int _value = 1;
}
```
29 changes: 29 additions & 0 deletions packages/bloc_lint/doc/rules/event_base_class_suffix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
event_base_class_suffix
===
severity: WARNING

The base event class should always be suffixed by `Event`.

## Example:

**BAD**:

```dart
@immutable
sealed class CounterData {}
final class CounterStarted extends CounterData {}
```

**GOOD**:

```dart
@immutable
sealed class CounterEvent {}
final class CounterStarted extends CounterEvent {}
```

## Additional Resources

- [Bloc Library Documentation: Naming Conventions / Event Conventions](https://bloclibrary.dev/naming-conventions/#event-conventions)
38 changes: 38 additions & 0 deletions packages/bloc_lint/doc/rules/prefer_multi_bloc_listener.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
prefer-multi-bloc-listener
===
severity: WARNING

Warns when a `BlocListener` can be replaced by a `MultiBlocListener`.

## Example:

**BAD**:

```dart
BlocListener<ACubit, AState>(
listener: (BuildContext context, state) {},
child: BlocListener<BCubit, BState>(
listener: (BuildContext context, state) {},
),
);
```

**GOOD**:

```dart
MultiBlocListener(
listeners: [
BlocListener<ACubit, AState>(
listener: (BuildContext context, state) {},
),
BlocListener<BCubit, BState>(
listener: (BuildContext context, state) {},
),
],
child: Container(),
);
```

## Additional Resources

- [Bloc Library Documentation: Flutter Bloc Concepts / MultiBlocListener](https://bloclibrary.dev/flutter-bloc-concepts/#multibloclistener)
35 changes: 35 additions & 0 deletions packages/bloc_lint/doc/rules/prefer_multi_bloc_provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
prefer-multi-bloc-provider
===
severity: WARNING

Warns when a `BlocProvider` can be replaced by a `MultiBlocProvider`.

## Example:

**BAD**:

```dart
BlocProvider<BlocA>(
create: (context) => BlocA(),
child: BlocProvider<BlocB>(
create: (context) => BlocB(),
child: Widget(),
),
);
```

**GOOD**:

```dart
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(create: (context) => BlocA()),
BlocProvider<BlocB>(create: (context) => BlocB()),
],
child: Widget(),
);
```

## Additional Resources

- [Bloc Library Documentation: Flutter Bloc Concepts / MultiBlocProvider](https://bloclibrary.dev/flutter-bloc-concepts/#multiblocprovider)
34 changes: 34 additions & 0 deletions packages/bloc_lint/doc/rules/prefer_multi_repository_provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
prefer-multi-repository-provider
===
severity: WARNING

Warns when a `RepositoryProvider` can be replaced by a `MultiRepositoryProvider`.

## Example:

**BAD**:

```dart
RepositoryProvider(
create: (_) => RepositoryA(),
child: RepositoryProvider(
create: (_) => RepositoryB(),
),
);
```

**GOOD**:

```dart
MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (_) => RepositoryA()),
RepositoryProvider(create: (_) => RepositoryB()),
],
child: Container(),
);
```

## Additional Resources

- [Bloc Library Documentation: Flutter Bloc Concepts / MultiRepositoryProvider](https://bloclibrary.dev/flutter-bloc-concepts/#multirepositoryprovider)
28 changes: 28 additions & 0 deletions packages/bloc_lint/doc/rules/state_base_class_suffix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
state_base_class_suffix
===
severity: WARNING

The base state class should always be suffixed by `State`.

## Example:

**BAD**:

```dart
@immutable
sealed class HomepageData {}
final class HomepageInitial extends HomepageData {}
```

**GOOD**:

```dart
sealed class HomepageState {}
final class HomepageInitial extends HomepageState {}
```

## Additional Resources

- [Bloc Library Documentation: Naming Conventions / State Conventions](https://bloclibrary.dev/naming-conventions/#state-conventions)
3 changes: 3 additions & 0 deletions packages/bloc_lint/example/analysis_option.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
analyzer:
plugins:
- custom_lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:flutter_bloc/flutter_bloc.dart';

class AvoidPublicMethodOnBlocBloc extends Bloc<int, int> {
AvoidPublicMethodOnBlocBloc(super.initialState);

// expect_lint: avoid_public_methods_on_bloc
void publicMethod() {}

void _privateMethod() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';

class TestPublicPropertiesCubit extends Cubit<int> {
TestPublicPropertiesCubit() : super(0);

// expect_lint: avoid_public_properties_on_bloc_and_cubit
int value = 0;
String _privateValue = 'abc';
}

class TestPublicPropertiesBloc extends Bloc<int, int> {
TestPublicPropertiesBloc() : super(0);

// expect_lint: avoid_public_properties_on_bloc_and_cubit
int value = 0;
String _privateValue = 'abc';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';

class EventBaseClassSuffixLintRuleTestBloc extends Bloc<
// expect_lint: event_base_class_suffix
EventBaseClassSuffixLintRuleTestError,
EventBaseClassSuffixLintRuleTestState> {
EventBaseClassSuffixLintRuleTestBloc()
: super(EventBaseClassSuffixLintRuleTestInitial()) {
on<EventBaseClassSuffixLintRuleTestError>((event, emit) {
// TODO: implement event handler
});
}
}

@immutable
sealed class EventBaseClassSuffixLintRuleTestError {}

@immutable
sealed class EventBaseClassSuffixLintRuleTestState {}

final class EventBaseClassSuffixLintRuleTestInitial
extends EventBaseClassSuffixLintRuleTestState {}
Loading

0 comments on commit 87ccd4c

Please sign in to comment.