Skip to content
This repository has been archived by the owner on Dec 11, 2024. It is now read-only.

Commit

Permalink
feat(lint): implement event_base_class_suffix rule
Browse files Browse the repository at this point in the history
Implements: #7
  • Loading branch information
vmichalak committed Nov 10, 2024
1 parent a0169e9 commit 0f47f2b
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The example folder contains a dart project to unit test the rules. (see custom_l

- [avoid_public_methods_on_bloc](docs/rules/avoid_public_methods_on_bloc.md)
- [avoid_public_properties_on_bloc_and_cubit](docs/rules/avoid_public_properties_on_bloc_and_cubit.md)
- [event_base_class_suffix](docs/rules/event_base_class_suffix.md)
- [prefer_multi_bloc_listener](docs/rules/prefer_multi_bloc_listener.md)
- [prefer_multi_bloc_provider](docs/rules/prefer_multi_bloc_provider.md)
- [prefer_multi_repository_provider](docs/rules/prefer_multi_repository_provider.md)
Expand Down
29 changes: 29 additions & 0 deletions docs/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)
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 {}
2 changes: 2 additions & 0 deletions lib/bloc_lint.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:bloc_lint/lint_rules/avoid_public_methods_on_bloc_lint_rule.dart';
import 'package:bloc_lint/lint_rules/avoid_public_properties_on_bloc_and_cubit_lint_rule.dart';
import 'package:bloc_lint/lint_rules/event_base_class_suffix.dart';
import 'package:bloc_lint/lint_rules/prefer_multi_bloc_listener_lint_rule.dart';
import 'package:bloc_lint/lint_rules/prefer_multi_bloc_provider_lint_rule.dart';
import 'package:bloc_lint/lint_rules/prefer_multi_repository_provider_lint_rule.dart';
Expand All @@ -13,6 +14,7 @@ class _BlocLintPlugin extends PluginBase {
List<LintRule> getLintRules(CustomLintConfigs configs) => [
const AvoidPublicMethodsOnBlocLintRule(),
const AvoidPublicPropertiesOnBlocAndCubitLintRule(),
const EventBaseClassSuffix(),
const PreferMultiBlocListenerLintRule(),
const PreferMultiBlocProviderLintRule(),
const PreferMultiRepositoryProviderLintRule(),
Expand Down
56 changes: 56 additions & 0 deletions lib/lint_rules/event_base_class_suffix.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:bloc_lint/bloc_lint_constants.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

class EventBaseClassSuffix extends DartLintRule {
const EventBaseClassSuffix()
: super(
code: const LintCode(
name: 'event_base_class_suffix',
problemMessage:
'''The base event class should always be suffixed by 'Event'.''',
errorSeverity: ErrorSeverity.WARNING,
),
);

static const _ignoredType = [
'int',
'double',
'num',
'String',
'bool',
'List',
'Set',
'Map',
];

@override
void run(
CustomLintResolver resolver,
ErrorReporter reporter,
CustomLintContext context,
) {
context.registry.addExtendsClause((node) {
final superClass = node.superclass;
TypeAnnotation? stateNode;

if (superClass.element?.name == BlocLintConstants.blocClass) {
stateNode = superClass.typeArguments?.arguments[0];
}
if (stateNode == null) {
return;
}
final stateType = stateNode.type as InterfaceType?;
if (stateType == null || _ignoredType.contains(stateType.element.name)) {
return;
}

if (stateType.element.name.endsWith('Event') == false) {
reporter.atNode(stateNode, code);
}
});
}
}

0 comments on commit 0f47f2b

Please sign in to comment.