Skip to content

Commit 7770a13

Browse files
authored
Make it possible to exclude extensions, entities and mixins from prefer_match_file_name rule (#206)
1 parent 76546be commit 7770a13

File tree

12 files changed

+180
-9
lines changed

12 files changed

+180
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
## 0.4.0
22

33
- Added `allow_with_comments` parameter for `no_empty_block` lint.
4+
- Added `exclude_entity` parameter for `prefer_match_file_name` lint.
5+
It is now possible to configure this lint to ignore `enum`,
6+
`extension` and `mixin` declarations via `analysis_options.yaml`.
47

58
## 0.3.0
69

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import 'package:analyzer/dart/ast/ast.dart';
2+
3+
/// A model representing "exclude_entity" parameters for linting, defining
4+
/// identifiers (classes, mixins, enums, extensions) to be ignored during
5+
/// analysis.
6+
/// Supported entities:
7+
/// - mixin
8+
/// - extension
9+
/// - enum
10+
class ExcludedEntitiesListParameter {
11+
/// The parameter model
12+
final Set<String> excludedEntityNames;
13+
14+
/// A common parameter key for analysis_options.yaml
15+
static const String excludeEntityKey = 'exclude_entity';
16+
17+
/// Constructor for [ExcludedEntitiesListParameter] class
18+
ExcludedEntitiesListParameter({
19+
required this.excludedEntityNames,
20+
});
21+
22+
/// Method for creating from json data
23+
factory ExcludedEntitiesListParameter.fromJson(Map<String, dynamic> json) {
24+
final raw = json['exclude_entity'];
25+
if (raw is List) {
26+
return ExcludedEntitiesListParameter(
27+
excludedEntityNames: Set<String>.from(raw),
28+
);
29+
}
30+
31+
return ExcludedEntitiesListParameter(
32+
excludedEntityNames: {},
33+
);
34+
}
35+
36+
/// Returns whether the target node should be ignored during analysis.
37+
bool shouldIgnoreEntity(Declaration node) {
38+
if (excludedEntityNames.isEmpty) return false;
39+
40+
if (node is MixinDeclaration && excludedEntityNames.contains('mixin')) {
41+
return true;
42+
} else if (node is EnumDeclaration &&
43+
excludedEntityNames.contains('enum')) {
44+
return true;
45+
} else if (node is ExtensionDeclaration &&
46+
excludedEntityNames.contains('extension')) {
47+
return true;
48+
}
49+
50+
return false;
51+
}
52+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'package:solid_lints/src/common/parameters/excluded_entities_list_parameter.dart';
2+
3+
/// A data model class that represents the "prefer match file name" input
4+
/// parameters
5+
class PreferMatchFileNameParameters {
6+
/// A list of entities that should be excluded from the lint.
7+
final ExcludedEntitiesListParameter excludeEntity;
8+
9+
/// Constructor for [PreferMatchFileNameParameters] model
10+
const PreferMatchFileNameParameters({
11+
required this.excludeEntity,
12+
});
13+
14+
/// Method for creating from json data
15+
factory PreferMatchFileNameParameters.fromJson(Map<String, Object?> json) =>
16+
PreferMatchFileNameParameters(
17+
excludeEntity: ExcludedEntitiesListParameter.fromJson(json),
18+
);
19+
}

lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:analyzer/error/listener.dart';
22
import 'package:custom_lint_builder/custom_lint_builder.dart';
33
import 'package:path/path.dart' as p;
4+
import 'package:solid_lints/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart';
45
import 'package:solid_lints/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart';
56
import 'package:solid_lints/src/models/rule_config.dart';
67
import 'package:solid_lints/src/models/solid_lint_rule.dart';
@@ -48,7 +49,8 @@ import 'package:solid_lints/src/utils/node_utils.dart';
4849
/// class SomethingPublic {} // OK
4950
/// ```
5051
///
51-
class PreferMatchFileNameRule extends SolidLintRule {
52+
class PreferMatchFileNameRule
53+
extends SolidLintRule<PreferMatchFileNameParameters> {
5254
/// This lint rule represents the error if iterable
5355
/// access can be simplified.
5456
static const String lintName = 'prefer_match_file_name';
@@ -62,6 +64,7 @@ class PreferMatchFileNameRule extends SolidLintRule {
6264
final config = RuleConfig(
6365
configs: configs,
6466
name: lintName,
67+
paramsParser: PreferMatchFileNameParameters.fromJson,
6568
problemMessage: (value) =>
6669
'File name does not match with first declared element name.',
6770
);
@@ -76,7 +79,11 @@ class PreferMatchFileNameRule extends SolidLintRule {
7679
CustomLintContext context,
7780
) {
7881
context.registry.addCompilationUnit((node) {
79-
final visitor = PreferMatchFileNameVisitor();
82+
final excludedEntities = config.parameters.excludeEntity;
83+
84+
final visitor = PreferMatchFileNameVisitor(
85+
excludedEntities: excludedEntities,
86+
);
8087

8188
node.accept(visitor);
8289

lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
11
import 'package:analyzer/dart/ast/ast.dart';
22
import 'package:analyzer/dart/ast/visitor.dart';
3+
import 'package:solid_lints/src/common/parameters/excluded_entities_list_parameter.dart';
34
import 'package:solid_lints/src/lints/prefer_match_file_name/models/declaration_token_info.dart';
45

56
/// The AST visitor that will collect all Class, Enum, Extension and Mixin
67
/// declarations
78
class PreferMatchFileNameVisitor extends RecursiveAstVisitor<void> {
89
final _declarations = <DeclarationTokenInfo>[];
910

11+
/// Iterable that contains the name of entity (or entities) that should
12+
/// be ignored
13+
final ExcludedEntitiesListParameter excludedEntities;
14+
15+
/// Constructor of [PreferMatchFileNameVisitor] class
16+
PreferMatchFileNameVisitor({
17+
required this.excludedEntities,
18+
});
19+
1020
/// List of all declarations
11-
Iterable<DeclarationTokenInfo> get declarations => _declarations
12-
..sort(
13-
// partition into public and private
14-
// put public ones first
15-
// each partition sorted by declaration order
16-
(a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b),
17-
);
21+
Iterable<DeclarationTokenInfo> get declarations => _declarations.where(
22+
(declaration) {
23+
if (declaration.parent is Declaration) {
24+
return !excludedEntities
25+
.shouldIgnoreEntity(declaration.parent as Declaration);
26+
}
27+
return true;
28+
},
29+
).toList()
30+
..sort(
31+
(a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b),
32+
);
1833

1934
@override
2035
void visitClassDeclaration(ClassDeclaration node) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
analyzer:
2+
plugins:
3+
- ../../../custom_lint
4+
5+
custom_lint:
6+
rules:
7+
- prefer_match_file_name:
8+
exclude_entity:
9+
- enum
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// ignore_for_file: unused_element, unused_field
2+
3+
/// `prefer_match_file_name` rule will be ignored by this enttiy because of
4+
/// exclude_entity:
5+
/// - enum
6+
/// in analysis_options.yaml
7+
enum Ignored { _ }
8+
9+
enum IgnoredAgain { _ }
10+
11+
// expect_lint: prefer_match_file_name
12+
abstract class WrongNamedClass {}
13+
14+
/// Only first public element declaration is checked
15+
class PreferMatchFileNameIgnoreExtensions {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
analyzer:
2+
plugins:
3+
- ../../../custom_lint
4+
5+
custom_lint:
6+
rules:
7+
- prefer_match_file_name:
8+
exclude_entity:
9+
- extension
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// ignore_for_file: unused_element, unused_field
2+
3+
/// `prefer_match_file_name` rule will be ignored by this extension because of
4+
/// exclude_entity:
5+
/// - extension
6+
/// in analysis_options.yaml
7+
extension Ignored on String {}
8+
9+
extension IgnoredAgain on String {}
10+
11+
// expect_lint: prefer_match_file_name
12+
abstract class WrongNamedClass {}
13+
14+
/// Only first public element declaration is checked
15+
class PreferMatchFileNameIgnoreExtensions {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
analyzer:
2+
plugins:
3+
- ../../../custom_lint
4+
5+
custom_lint:
6+
rules:
7+
- prefer_match_file_name:
8+
exclude_entity:
9+
- mixin

0 commit comments

Comments
 (0)