Skip to content
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
- main
paths:
- 'docs/**'
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fix de deployment issue, because we updated the documentation directory to be doc instead of docs (pub dev requirement)

- 'doc/**'
- 'mkdocs.yml'
permissions:
contents: write
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.0.0

- 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.

## 1.0.5

- Add a warning message indicating that the keys will be renamed in the next major version
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ Create a JSON file in your project to define rules. Example:
[
{
"filePattern": "*util.dart",
"noDependsEnabled": true
"dependenciesAllowed": false
},
{
"filePattern": "*viewmodel.dart",
"justWithPatterns": ["*repository.dart"]
"exclusiveDependencies": ["*repository.dart"]
},
{
"filePattern": "*repository.dart",
"doNotWithPatterns": ["*screen.dart"]
"forbiddenDependencies": ["*screen.dart"]
}
]
```
Expand Down
47 changes: 34 additions & 13 deletions doc/1-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,43 @@

## 1. Define rules

- 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.
!!! warning "Deprecated - Only available before v2.0.0"

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.

```json
[
{
"filePattern": "*/data/model/*",
"noDependsEnabled": true
},
{
"filePattern": "*viewmodel.dart",
"doNotWithPatterns": ["*_screen.dart"]
},
{
"filePattern": "*/util/*_handler.dart",
"noDependsEnabled": true
}
]
```

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.

```json
[
{
"filePattern": "*/data/model/*",
"noDependsEnabled": true
},
{
"filePattern": "*viewmodel.dart",
"doNotWithPatterns": ["*_screen.dart"]
},
{
"filePattern": "*/util/*_handler.dart",
"noDependsEnabled": true
}
{
"filePattern": "*/data/model/*",
"dependenciesAllowed": false
},
{
"filePattern": "*viewmodel.dart",
"forbiddenDependencies": ["*_screen.dart"]
},
{
"filePattern": "*/util/*_handler.dart",
"dependenciesAllowed": false
}
]
```

Expand Down
65 changes: 50 additions & 15 deletions doc/2-existing-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,77 @@

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).

## DoNotWithRule
## Forbidden Dependencies Rule

The `DoNotWithRule` specifies that a set of file should not depend on certain files. For example:
!!! warning "Deprecated - Only available before v2.0.0"

The `DoNotWithRule` specifies that a set of file should not depend on certain files. For example:

```json
// your-project-root/eagle_eye_config.json
{
"filePattern": "*viewmodel.dart",
"doNotWithPatterns": ["*_screen.dart"]
},
```

The `Forbidden Dependencies Rule` specifies that a set of file should not depend on certain files. For example:

```json
// your-project-root/eagle_eye_config.json
{
"filePattern": "*viewmodel.dart",
"doNotWithPatterns": ["*_screen.dart"]
},
{
"filePattern": "*viewmodel.dart",
"forbiddenDependencies": ["*_screen.dart"]
},
```

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

## JustWithRule
## Exclusive Dependencies Rule

!!! warning "Deprecated - Only available before v2.0.0"

The `JustWithRule` specifies that some files should depend on certain files. For example:

The `JustWithRule` specifies that some files should depend on certain files. For example:
```json
// your-project-root/eagle_eye_config.json
{
"filePattern": "*repository.dart",
"justWithPatterns": ["*_datasources.dart"]
},
```

The `Exclusive Dependencies Rule` specifies that some files should depend only on certain files. For example:

```json
// your-project-root/eagle_eye_config.json
{
"filePattern": "*repository.dart",
"justWithPatterns": ["*_datasources.dart"]
},
{
"filePattern": "*repository.dart",
"exclusiveDependencies": ["*_datasources.dart"]
},
```

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

## NoDependencyRule
## Dependencies Allowed Rule

!!! warning "Deprecated - Only available before v2.0.0"

The `NoDependencyRule` ensures that some files should remain free of any dependencies. For example:

```json
{
"filePattern": "*util.dart",
"noDependsEnabled": true
},
```

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

```json
{
"filePattern": "*util.dart",
"noDependsEnabled": true
"dependenciesAllowed": false
},
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import 'package:eagle_eye/analyzer/regex_helper.dart';
import 'package:eagle_eye/model/error_info.dart';
import 'package:eagle_eye/model/analysis_error_info.dart';

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

/// Creates a new [JustWithRuleChecker] instance with the given [regexHelper].
JustWithRuleChecker(this.regexHelper);
/// Creates a new [ExclusiveDependenciesRuleChecker]
/// instance with the given [regexHelper].
ExclusiveDependenciesRuleChecker(this.regexHelper);

/// Checks if the given [importDirective] conforms to the specified
/// [justWithPatterns] for the provided [filePath].
Expand All @@ -21,9 +22,9 @@ class JustWithRuleChecker {
/// - [importDirective]: The import statement to validate
/// - [filePath]: The path of the file being analyzed
///
/// Returns an [ErrorInfo] if the import does **not** match any allowed
/// pattern, or `null` if it passes the validation.
ErrorInfo? check({
/// Returns an [AnalysisErrorInfo] if the import does **not** match any
/// allowed pattern, or `null` if it passes the validation.
AnalysisErrorInfo? check({
required List<String> justWithPatterns,
required String importDirective,
required String filePath,
Expand All @@ -34,7 +35,7 @@ class JustWithRuleChecker {
justWithItem,
);
if (matches == false) {
return ErrorInfo(
return AnalysisErrorInfo(
filePath: filePath,
errorMessage: '$filePath should depends only on $justWithPatterns',
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import 'package:eagle_eye/analyzer/regex_helper.dart';
import 'package:eagle_eye/model/error_info.dart';
import 'package:eagle_eye/model/analysis_error_info.dart';

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

/// Creates a new [DoNotWithRuleChecker] instance with the given [regexHelper]
DoNotWithRuleChecker(this.regexHelper);
/// Creates a new [ForbiddenDependenciesRuleChecker] instance with the
/// given [regexHelper]
ForbiddenDependenciesRuleChecker(this.regexHelper);

/// Checks if the given [importDirective] violates any of the provided
/// [noDepsWithPatterns] for the specified [filePath].
Expand All @@ -21,9 +23,9 @@ class DoNotWithRuleChecker {
/// - [importDirective]: The import statement to validate.
/// - [filePath]: The path of the file containing the import.
///
/// Returns an [ErrorInfo] if the import violates a rule, or `null` if all
/// checks pass.
ErrorInfo? check({
/// Returns an [AnalysisErrorInfo] if the import violates a rule, or `null`
/// if all checks pass.
AnalysisErrorInfo? check({
required List<String> noDepsWithPatterns,
required String importDirective,
required String filePath,
Expand All @@ -34,7 +36,7 @@ class DoNotWithRuleChecker {
noDepsWithItem,
);
if (matches == true) {
return ErrorInfo(
return AnalysisErrorInfo(
filePath: filePath,
errorMessage: '$filePath should not depends on $importDirective',
);
Expand Down
2 changes: 1 addition & 1 deletion lib/analyzer/eagle_eye_matcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class EagleEyeMatcher {
///
/// Returns the matching [EagleEyeConfigItem] if found,
/// or `null` if no configuration item matches.
EagleEyeConfigItem? find(filePath) {
EagleEyeConfigItem? find(String filePath) {
for (var configurationItem in config.items) {
bool configItemFounded = regexHelper.matchesPattern(
filePath,
Expand Down
26 changes: 14 additions & 12 deletions lib/analyzer/eagle_eye_visitor.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:eagle_eye/analyzer/checker/do_not_with_rule_checker.dart';
import 'package:eagle_eye/analyzer/checker/just_with_rule_checker.dart';
import 'package:eagle_eye/analyzer/checker/exclusive_dependencies_rule_checker.dart';
import 'package:eagle_eye/analyzer/checker/forbidden_dependencies_rule_checker.dart';
import 'package:eagle_eye/analyzer/regex_helper.dart';
import 'package:eagle_eye/model/analysis_error_info.dart';
import 'package:eagle_eye/model/eagle_eye_config_item.dart';
import 'package:eagle_eye/model/error_info.dart';

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

/// Callback used to report detected rule violations.
final Function(ErrorInfo) errorCallback;
final Function(AnalysisErrorInfo) errorCallback;

/// Helper used for regex-based pattern matching.
final RegexHelper regexHelper;
Expand Down Expand Up @@ -61,17 +61,18 @@ class EagleEyeVisitor extends RecursiveAstVisitor<void> {
// (discard any third party libraries)
if (importDirective?.contains(applicationName) == true) {
// Check rules exclusively
if (configItem.noDependsEnabled == true) {
if (configItem.dependenciesAllowed == false) {
errorCallback(
ErrorInfo(
AnalysisErrorInfo(
filePath: filePath,
errorMessage: '$filePath should not contains any import.',
),
);
} else if (configItem.doNotWithPatterns != null) {
} else if (configItem.forbiddenDependencies != null) {
if (importDirective != null) {
ErrorInfo? errorInfo = DoNotWithRuleChecker(regexHelper).check(
noDepsWithPatterns: configItem.doNotWithPatterns!,
final checker = ForbiddenDependenciesRuleChecker(regexHelper);
AnalysisErrorInfo? errorInfo = checker.check(
noDepsWithPatterns: configItem.forbiddenDependencies!,
importDirective: importDirective,
filePath: filePath,
);
Expand All @@ -80,10 +81,11 @@ class EagleEyeVisitor extends RecursiveAstVisitor<void> {
errorCallback(errorInfo);
}
}
} else if (configItem.justWithPatterns != null) {
} else if (configItem.exclusiveDependencies != null) {
if (importDirective != null) {
ErrorInfo? errorInfo = JustWithRuleChecker(regexHelper).check(
justWithPatterns: configItem.justWithPatterns!,
final checker = ExclusiveDependenciesRuleChecker(regexHelper);
AnalysisErrorInfo? errorInfo = checker.check(
justWithPatterns: configItem.exclusiveDependencies!,
importDirective: importDirective,
filePath: filePath,
);
Expand Down
Loading