Skip to content

Commit 4d2ab31

Browse files
authored
Merge pull request #26 from CodandoTV/feature/improve-configuration-file-naming-conventions
Support new configuration keys and improve error handling
2 parents e51daf4 + f851449 commit 4d2ab31

26 files changed

Lines changed: 358 additions & 223 deletions

.github/workflows/documentation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches:
66
- main
77
paths:
8-
- 'docs/**'
8+
- 'doc/**'
99
- 'mkdocs.yml'
1010
permissions:
1111
contents: write

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.0
2+
3+
- Update the configuration file structure by renaming JSON keys to improve readability. Breaking changes: renamed doNotWithPatterns to forbiddenDependencies, justWithPatterns to exclusiveDependencies, and noDependsEnabled to dependenciesAllowed.
4+
15
## 1.0.5
26

37
- Add a warning message indicating that the keys will be renamed in the next major version

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ Create a JSON file in your project to define rules. Example:
5858
[
5959
{
6060
"filePattern": "*util.dart",
61-
"noDependsEnabled": true
61+
"dependenciesAllowed": false
6262
},
6363
{
6464
"filePattern": "*viewmodel.dart",
65-
"justWithPatterns": ["*repository.dart"]
65+
"exclusiveDependencies": ["*repository.dart"]
6666
},
6767
{
6868
"filePattern": "*repository.dart",
69-
"doNotWithPatterns": ["*screen.dart"]
69+
"forbiddenDependencies": ["*screen.dart"]
7070
}
7171
]
7272
```

doc/1-getting-started.md

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,43 @@
22

33
## 1. Define rules
44

5-
- In the root level of you project, you need to create the file `eagle_eye_config.json` at the root level of your flutter/dart project.
5+
!!! warning "Deprecated - Only available before v2.0.0"
6+
7+
In the root level of you project, you need to create the file `eagle_eye_config.json` at the root level of your flutter/dart project.
8+
9+
```json
10+
[
11+
{
12+
"filePattern": "*/data/model/*",
13+
"noDependsEnabled": true
14+
},
15+
{
16+
"filePattern": "*viewmodel.dart",
17+
"doNotWithPatterns": ["*_screen.dart"]
18+
},
19+
{
20+
"filePattern": "*/util/*_handler.dart",
21+
"noDependsEnabled": true
22+
}
23+
]
24+
```
25+
26+
In the root level of you project, you need to create the file `eagle_eye_config.json` at the root level of your flutter/dart project.
627

728
```json
829
[
9-
{
10-
"filePattern": "*/data/model/*",
11-
"noDependsEnabled": true
12-
},
13-
{
14-
"filePattern": "*viewmodel.dart",
15-
"doNotWithPatterns": ["*_screen.dart"]
16-
},
17-
{
18-
"filePattern": "*/util/*_handler.dart",
19-
"noDependsEnabled": true
20-
}
30+
{
31+
"filePattern": "*/data/model/*",
32+
"dependenciesAllowed": false
33+
},
34+
{
35+
"filePattern": "*viewmodel.dart",
36+
"forbiddenDependencies": ["*_screen.dart"]
37+
},
38+
{
39+
"filePattern": "*/util/*_handler.dart",
40+
"dependenciesAllowed": false
41+
}
2142
]
2243
```
2344

doc/2-existing-rules.md

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,77 @@
22

33
We have several rules already defined in the plugin. You can create some rule too, take a look in our section about [contributions](./3-contributions.md).
44

5-
## DoNotWithRule
5+
## Forbidden Dependencies Rule
66

7-
The `DoNotWithRule` specifies that a set of file should not depend on certain files. For example:
7+
!!! warning "Deprecated - Only available before v2.0.0"
8+
9+
The `DoNotWithRule` specifies that a set of file should not depend on certain files. For example:
10+
11+
```json
12+
// your-project-root/eagle_eye_config.json
13+
{
14+
"filePattern": "*viewmodel.dart",
15+
"doNotWithPatterns": ["*_screen.dart"]
16+
},
17+
```
18+
19+
The `Forbidden Dependencies Rule` specifies that a set of file should not depend on certain files. For example:
820

921
```json
1022
// your-project-root/eagle_eye_config.json
11-
{
12-
"filePattern": "*viewmodel.dart",
13-
"doNotWithPatterns": ["*_screen.dart"]
14-
},
23+
{
24+
"filePattern": "*viewmodel.dart",
25+
"forbiddenDependencies": ["*_screen.dart"]
26+
},
1527
```
1628

1729
In this case, all files that has the suffix `viewmodel.dart` should not depend on any file whose name includes '_screen.dart'.
1830

19-
## JustWithRule
31+
## Exclusive Dependencies Rule
32+
33+
!!! warning "Deprecated - Only available before v2.0.0"
34+
35+
The `JustWithRule` specifies that some files should depend on certain files. For example:
2036

21-
The `JustWithRule` specifies that some files should depend on certain files. For example:
37+
```json
38+
// your-project-root/eagle_eye_config.json
39+
{
40+
"filePattern": "*repository.dart",
41+
"justWithPatterns": ["*_datasources.dart"]
42+
},
43+
```
44+
45+
The `Exclusive Dependencies Rule` specifies that some files should depend only on certain files. For example:
2246

2347
```json
2448
// your-project-root/eagle_eye_config.json
25-
{
26-
"filePattern": "*repository.dart",
27-
"justWithPatterns": ["*_datasources.dart"]
28-
},
49+
{
50+
"filePattern": "*repository.dart",
51+
"exclusiveDependencies": ["*_datasources.dart"]
52+
},
2953
```
3054

3155
In this case, the our repositories should depend only on data sources.
3256

33-
## NoDependencyRule
57+
## Dependencies Allowed Rule
58+
59+
!!! warning "Deprecated - Only available before v2.0.0"
60+
61+
The `NoDependencyRule` ensures that some files should remain free of any dependencies. For example:
62+
63+
```json
64+
{
65+
"filePattern": "*util.dart",
66+
"noDependsEnabled": true
67+
},
68+
```
3469

35-
The `NoDependencyRule` ensures that some files should remain free of any dependencies. For example:
70+
The `Dependencies Allowed Rule` ensures that some files should remain free of any dependencies. For example:
3671

3772
```json
3873
{
3974
"filePattern": "*util.dart",
40-
"noDependsEnabled": true
75+
"dependenciesAllowed": false
4176
},
4277
```
4378

lib/analyzer/checker/just_with_rule_checker.dart renamed to lib/analyzer/checker/exclusive_dependencies_rule_checker.dart

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import 'package:eagle_eye/analyzer/regex_helper.dart';
2-
import 'package:eagle_eye/model/error_info.dart';
2+
import 'package:eagle_eye/model/analysis_error_info.dart';
33

44
/// A rule checker that ensures a file imports **only allowed dependencies**.
55
///
6-
/// The [JustWithRuleChecker] uses a [RegexHelper] to verify that each
7-
/// import directive matches all the allowed dependency patterns.
6+
/// The [ExclusiveDependenciesRuleChecker] uses a [RegexHelper] to verify that
7+
/// each import directive matches all the allowed dependency patterns.
88
/// If an import does not match any of the patterns, an [ErrorInfo]
99
/// describing the violation is returned.
10-
class JustWithRuleChecker {
10+
class ExclusiveDependenciesRuleChecker {
1111
/// Helper class used for regex-based pattern matching.
1212
RegexHelper regexHelper;
1313

14-
/// Creates a new [JustWithRuleChecker] instance with the given [regexHelper].
15-
JustWithRuleChecker(this.regexHelper);
14+
/// Creates a new [ExclusiveDependenciesRuleChecker]
15+
/// instance with the given [regexHelper].
16+
ExclusiveDependenciesRuleChecker(this.regexHelper);
1617

1718
/// Checks if the given [importDirective] conforms to the specified
1819
/// [justWithPatterns] for the provided [filePath].
@@ -21,9 +22,9 @@ class JustWithRuleChecker {
2122
/// - [importDirective]: The import statement to validate
2223
/// - [filePath]: The path of the file being analyzed
2324
///
24-
/// Returns an [ErrorInfo] if the import does **not** match any allowed
25-
/// pattern, or `null` if it passes the validation.
26-
ErrorInfo? check({
25+
/// Returns an [AnalysisErrorInfo] if the import does **not** match any
26+
/// allowed pattern, or `null` if it passes the validation.
27+
AnalysisErrorInfo? check({
2728
required List<String> justWithPatterns,
2829
required String importDirective,
2930
required String filePath,
@@ -34,7 +35,7 @@ class JustWithRuleChecker {
3435
justWithItem,
3536
);
3637
if (matches == false) {
37-
return ErrorInfo(
38+
return AnalysisErrorInfo(
3839
filePath: filePath,
3940
errorMessage: '$filePath should depends only on $justWithPatterns',
4041
);

lib/analyzer/checker/do_not_with_rule_checker.dart renamed to lib/analyzer/checker/forbidden_dependencies_rule_checker.dart

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import 'package:eagle_eye/analyzer/regex_helper.dart';
2-
import 'package:eagle_eye/model/error_info.dart';
2+
import 'package:eagle_eye/model/analysis_error_info.dart';
33

44
/// A rule checker that validates whether a file imports disallowed dependencies
55
///
6-
/// The [DoNotWithRuleChecker] uses a [RegexHelper] to test import directives
7-
/// against a list of forbidden dependency patterns. If a match is found,
6+
/// The [ForbiddenDependenciesRuleChecker] uses a [RegexHelper] to test import
7+
/// directives against a list of forbidden dependency patterns.
8+
/// If a match is found,
89
/// an [ErrorInfo] is returned describing the violation.
9-
class DoNotWithRuleChecker {
10+
class ForbiddenDependenciesRuleChecker {
1011
/// Helper class used for regex-based pattern matching
1112
RegexHelper regexHelper;
1213

13-
/// Creates a new [DoNotWithRuleChecker] instance with the given [regexHelper]
14-
DoNotWithRuleChecker(this.regexHelper);
14+
/// Creates a new [ForbiddenDependenciesRuleChecker] instance with the
15+
/// given [regexHelper]
16+
ForbiddenDependenciesRuleChecker(this.regexHelper);
1517

1618
/// Checks if the given [importDirective] violates any of the provided
1719
/// [noDepsWithPatterns] for the specified [filePath].
@@ -21,9 +23,9 @@ class DoNotWithRuleChecker {
2123
/// - [importDirective]: The import statement to validate.
2224
/// - [filePath]: The path of the file containing the import.
2325
///
24-
/// Returns an [ErrorInfo] if the import violates a rule, or `null` if all
25-
/// checks pass.
26-
ErrorInfo? check({
26+
/// Returns an [AnalysisErrorInfo] if the import violates a rule, or `null`
27+
/// if all checks pass.
28+
AnalysisErrorInfo? check({
2729
required List<String> noDepsWithPatterns,
2830
required String importDirective,
2931
required String filePath,
@@ -34,7 +36,7 @@ class DoNotWithRuleChecker {
3436
noDepsWithItem,
3537
);
3638
if (matches == true) {
37-
return ErrorInfo(
39+
return AnalysisErrorInfo(
3840
filePath: filePath,
3941
errorMessage: '$filePath should not depends on $importDirective',
4042
);

lib/analyzer/eagle_eye_matcher.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class EagleEyeMatcher {
2929
///
3030
/// Returns the matching [EagleEyeConfigItem] if found,
3131
/// or `null` if no configuration item matches.
32-
EagleEyeConfigItem? find(filePath) {
32+
EagleEyeConfigItem? find(String filePath) {
3333
for (var configurationItem in config.items) {
3434
bool configItemFounded = regexHelper.matchesPattern(
3535
filePath,

lib/analyzer/eagle_eye_visitor.dart

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import 'package:analyzer/dart/ast/ast.dart';
22
import 'package:analyzer/dart/ast/visitor.dart';
3-
import 'package:eagle_eye/analyzer/checker/do_not_with_rule_checker.dart';
4-
import 'package:eagle_eye/analyzer/checker/just_with_rule_checker.dart';
3+
import 'package:eagle_eye/analyzer/checker/exclusive_dependencies_rule_checker.dart';
4+
import 'package:eagle_eye/analyzer/checker/forbidden_dependencies_rule_checker.dart';
55
import 'package:eagle_eye/analyzer/regex_helper.dart';
6+
import 'package:eagle_eye/model/analysis_error_info.dart';
67
import 'package:eagle_eye/model/eagle_eye_config_item.dart';
7-
import 'package:eagle_eye/model/error_info.dart';
88

99
/// A visitor that analyzes import directives to validate architectural rules
1010
/// defined in an [EagleEyeConfigItem].
@@ -28,7 +28,7 @@ class EagleEyeVisitor extends RecursiveAstVisitor<void> {
2828
final String filePath;
2929

3030
/// Callback used to report detected rule violations.
31-
final Function(ErrorInfo) errorCallback;
31+
final Function(AnalysisErrorInfo) errorCallback;
3232

3333
/// Helper used for regex-based pattern matching.
3434
final RegexHelper regexHelper;
@@ -61,17 +61,18 @@ class EagleEyeVisitor extends RecursiveAstVisitor<void> {
6161
// (discard any third party libraries)
6262
if (importDirective?.contains(applicationName) == true) {
6363
// Check rules exclusively
64-
if (configItem.noDependsEnabled == true) {
64+
if (configItem.dependenciesAllowed == false) {
6565
errorCallback(
66-
ErrorInfo(
66+
AnalysisErrorInfo(
6767
filePath: filePath,
6868
errorMessage: '$filePath should not contains any import.',
6969
),
7070
);
71-
} else if (configItem.doNotWithPatterns != null) {
71+
} else if (configItem.forbiddenDependencies != null) {
7272
if (importDirective != null) {
73-
ErrorInfo? errorInfo = DoNotWithRuleChecker(regexHelper).check(
74-
noDepsWithPatterns: configItem.doNotWithPatterns!,
73+
final checker = ForbiddenDependenciesRuleChecker(regexHelper);
74+
AnalysisErrorInfo? errorInfo = checker.check(
75+
noDepsWithPatterns: configItem.forbiddenDependencies!,
7576
importDirective: importDirective,
7677
filePath: filePath,
7778
);
@@ -80,10 +81,11 @@ class EagleEyeVisitor extends RecursiveAstVisitor<void> {
8081
errorCallback(errorInfo);
8182
}
8283
}
83-
} else if (configItem.justWithPatterns != null) {
84+
} else if (configItem.exclusiveDependencies != null) {
8485
if (importDirective != null) {
85-
ErrorInfo? errorInfo = JustWithRuleChecker(regexHelper).check(
86-
justWithPatterns: configItem.justWithPatterns!,
86+
final checker = ExclusiveDependenciesRuleChecker(regexHelper);
87+
AnalysisErrorInfo? errorInfo = checker.check(
88+
justWithPatterns: configItem.exclusiveDependencies!,
8789
importDirective: importDirective,
8890
filePath: filePath,
8991
);

0 commit comments

Comments
 (0)