From 0d806dd7f4acd550b1f11c7c881c29c89afca0c9 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 20:20:55 -0300 Subject: [PATCH 01/10] Support new keys --- ... exclusive_dependencies_rule_checker.dart} | 11 ++--- ... forbidden_dependencies_rule_checker.dart} | 12 ++--- lib/analyzer/eagle_eye_visitor.dart | 20 +++++---- lib/model/config_keys.dart | 6 +-- lib/model/eagle_eye_config_item.dart | 45 ++++++++++--------- ...usive_dependencies_rule_checker_test.dart} | 8 ++-- ...idden_dependencies_rule_checker_test.dart} | 8 ++-- test/model/eagle_eye_config_item_test.dart | 32 ++++++------- 8 files changed, 74 insertions(+), 68 deletions(-) rename lib/analyzer/checker/{just_with_rule_checker.dart => exclusive_dependencies_rule_checker.dart} (79%) rename lib/analyzer/checker/{do_not_with_rule_checker.dart => forbidden_dependencies_rule_checker.dart} (78%) rename test/analyzer/checker/{just_with_rule_checker_test.dart => exclusive_dependencies_rule_checker_test.dart} (75%) rename test/analyzer/checker/{do_not_with_rule_checker_test.dart => forbidden_dependencies_rule_checker_test.dart} (75%) diff --git a/lib/analyzer/checker/just_with_rule_checker.dart b/lib/analyzer/checker/exclusive_dependencies_rule_checker.dart similarity index 79% rename from lib/analyzer/checker/just_with_rule_checker.dart rename to lib/analyzer/checker/exclusive_dependencies_rule_checker.dart index fe9d709..b0479db 100644 --- a/lib/analyzer/checker/just_with_rule_checker.dart +++ b/lib/analyzer/checker/exclusive_dependencies_rule_checker.dart @@ -3,16 +3,17 @@ import 'package:eagle_eye/model/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]. diff --git a/lib/analyzer/checker/do_not_with_rule_checker.dart b/lib/analyzer/checker/forbidden_dependencies_rule_checker.dart similarity index 78% rename from lib/analyzer/checker/do_not_with_rule_checker.dart rename to lib/analyzer/checker/forbidden_dependencies_rule_checker.dart index e554d3f..30125d1 100644 --- a/lib/analyzer/checker/do_not_with_rule_checker.dart +++ b/lib/analyzer/checker/forbidden_dependencies_rule_checker.dart @@ -3,15 +3,17 @@ import 'package:eagle_eye/model/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]. diff --git a/lib/analyzer/eagle_eye_visitor.dart b/lib/analyzer/eagle_eye_visitor.dart index 282055a..9b3d6e8 100644 --- a/lib/analyzer/eagle_eye_visitor.dart +++ b/lib/analyzer/eagle_eye_visitor.dart @@ -1,7 +1,7 @@ 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/eagle_eye_config_item.dart'; import 'package:eagle_eye/model/error_info.dart'; @@ -61,17 +61,18 @@ class EagleEyeVisitor extends RecursiveAstVisitor { // (discard any third party libraries) if (importDirective?.contains(applicationName) == true) { // Check rules exclusively - if (configItem.noDependsEnabled == true) { + if (configItem.dependenciesAllowed == false) { errorCallback( ErrorInfo( 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); + ErrorInfo? errorInfo = checker.check( + noDepsWithPatterns: configItem.forbiddenDependencies!, importDirective: importDirective, filePath: filePath, ); @@ -80,10 +81,11 @@ class EagleEyeVisitor extends RecursiveAstVisitor { 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); + ErrorInfo? errorInfo = checker.check( + justWithPatterns: configItem.exclusiveDependencies!, importDirective: importDirective, filePath: filePath, ); diff --git a/lib/model/config_keys.dart b/lib/model/config_keys.dart index bab56cc..22330a8 100644 --- a/lib/model/config_keys.dart +++ b/lib/model/config_keys.dart @@ -2,13 +2,13 @@ /// file is created. class ConfigKeys { /// JSON key for enabling or disabling all dependencies in a rule item. - static const noDependsEnabledEagleItemKey = 'noDependsEnabled'; + static const dependenciesAllowedEagleItemKey = 'dependenciesAllowed'; /// JSON key for the list of forbidden dependency patterns. - static const doNotWithPatternsEagleItemKey = 'doNotWithPatterns'; + static const forbiddenDependenciesEagleItemKey = 'forbiddenDependencies'; /// JSON key for the list of allowed dependency patterns. - static const justWithPatternsEagleItemKey = 'justWithPatterns'; + static const exclusiveDependenciesEagleItemKey = 'exclusiveDependencies'; /// JSON key for the file-matching pattern. static const filePatternEagleItemKey = 'filePattern'; diff --git a/lib/model/eagle_eye_config_item.dart b/lib/model/eagle_eye_config_item.dart index ccbc6eb..18321d5 100644 --- a/lib/model/eagle_eye_config_item.dart +++ b/lib/model/eagle_eye_config_item.dart @@ -8,29 +8,29 @@ import 'package:eagle_eye/model/config_keys.dart'; /// within that scope. /// /// Configuration behavior: -/// - If [noDependsEnabled] is `true`, the file cannot import anything. -/// - If [doNotWithPatterns] is provided, the file **cannot** import +/// - If [dependenciesAllowed] is `false`, the file cannot import anything. +/// - If [forbiddenDependencies] is provided, the file **cannot** import /// any module matching those patterns. -/// - If [justWithPatterns] is provided, the file **can only** import +/// - If [exclusiveDependencies] is provided, the file **can only** import /// modules that match those patterns. class EagleEyeConfigItem { - /// If `true`, the file should not contain any import statements. - bool? noDependsEnabled = false; + /// If `false`, the file should not contain any import statements. + bool? dependenciesAllowed = true; /// List of regex or wildcard patterns representing forbidden imports. - List? doNotWithPatterns; + List? forbiddenDependencies; /// List of regex or wildcard patterns representing allowed imports. - List? justWithPatterns; + List? exclusiveDependencies; /// Pattern used to identify which files this rule applies to. String filePattern; /// Creates a new [EagleEyeConfigItem] instance with the given parameters. EagleEyeConfigItem({ - this.noDependsEnabled, - this.doNotWithPatterns, - this.justWithPatterns, + this.dependenciesAllowed, + this.forbiddenDependencies, + this.exclusiveDependencies, required this.filePattern, }); @@ -39,32 +39,33 @@ class EagleEyeConfigItem { /// Handles missing or invalid fields gracefully by assigning `null` /// where appropriate. factory EagleEyeConfigItem.fromJson(Map json) { - bool? noDependsEnabled = json[ConfigKeys.noDependsEnabledEagleItemKey]; + bool? dependenciesAllowed = + json[ConfigKeys.dependenciesAllowedEagleItemKey]; - List? doNotWithPatterns; + List? forbiddenDependencies; try { - doNotWithPatterns = List.from( - json[ConfigKeys.doNotWithPatternsEagleItemKey] as List, + forbiddenDependencies = List.from( + json[ConfigKeys.forbiddenDependenciesEagleItemKey] as List, ); } catch (e) { - doNotWithPatterns = null; + forbiddenDependencies = null; } - List? justWithPatterns; + List? exclusiveDependencies; try { - justWithPatterns = List.from( - json[ConfigKeys.justWithPatternsEagleItemKey] as List, + exclusiveDependencies = List.from( + json[ConfigKeys.exclusiveDependenciesEagleItemKey] as List, ); } catch (e) { - justWithPatterns = null; + exclusiveDependencies = null; } String filePattern = json[ConfigKeys.filePatternEagleItemKey]; return EagleEyeConfigItem( - noDependsEnabled: noDependsEnabled, - doNotWithPatterns: doNotWithPatterns, - justWithPatterns: justWithPatterns, + dependenciesAllowed: dependenciesAllowed, + forbiddenDependencies: forbiddenDependencies, + exclusiveDependencies: exclusiveDependencies, filePattern: filePattern, ); } diff --git a/test/analyzer/checker/just_with_rule_checker_test.dart b/test/analyzer/checker/exclusive_dependencies_rule_checker_test.dart similarity index 75% rename from test/analyzer/checker/just_with_rule_checker_test.dart rename to test/analyzer/checker/exclusive_dependencies_rule_checker_test.dart index a22078d..a42bad7 100644 --- a/test/analyzer/checker/just_with_rule_checker_test.dart +++ b/test/analyzer/checker/exclusive_dependencies_rule_checker_test.dart @@ -1,12 +1,12 @@ -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/regex_helper.dart'; import 'package:test/test.dart'; void main() { - group('JustWithRuleChecker', () { + group('ExclusiveDependenciesRuleChecker', () { test('returns ErrorInfo when a pattern matches', () { final regexHelper = RegexHelper(); - final checker = JustWithRuleChecker(regexHelper); + final checker = ExclusiveDependenciesRuleChecker(regexHelper); final result = checker.check( justWithPatterns: ['*repository.dart'], @@ -22,7 +22,7 @@ void main() { test('returns null when no patterns match', () { final regexHelper = RegexHelper(); - final checker = JustWithRuleChecker(regexHelper); + final checker = ExclusiveDependenciesRuleChecker(regexHelper); final result = checker.check( justWithPatterns: ['*repository.dart'], diff --git a/test/analyzer/checker/do_not_with_rule_checker_test.dart b/test/analyzer/checker/forbidden_dependencies_rule_checker_test.dart similarity index 75% rename from test/analyzer/checker/do_not_with_rule_checker_test.dart rename to test/analyzer/checker/forbidden_dependencies_rule_checker_test.dart index ce974e8..623fdf1 100644 --- a/test/analyzer/checker/do_not_with_rule_checker_test.dart +++ b/test/analyzer/checker/forbidden_dependencies_rule_checker_test.dart @@ -1,12 +1,12 @@ -import 'package:eagle_eye/analyzer/checker/do_not_with_rule_checker.dart'; +import 'package:eagle_eye/analyzer/checker/forbidden_dependencies_rule_checker.dart'; import 'package:eagle_eye/analyzer/regex_helper.dart'; import 'package:test/test.dart'; void main() { - group('DoNotWithRuleChecker', () { + group('ForbiddenDependenciesRuleChecker', () { test('returns ErrorInfo when a pattern matches', () { final regexHelper = RegexHelper(); - final checker = DoNotWithRuleChecker(regexHelper); + final checker = ForbiddenDependenciesRuleChecker(regexHelper); final result = checker.check( noDepsWithPatterns: ['*repository.dart'], @@ -22,7 +22,7 @@ void main() { test('returns null when no patterns match', () { final regexHelper = RegexHelper(); - final checker = DoNotWithRuleChecker(regexHelper); + final checker = ForbiddenDependenciesRuleChecker(regexHelper); final result = checker.check( noDepsWithPatterns: ['*repository.dart'], diff --git a/test/model/eagle_eye_config_item_test.dart b/test/model/eagle_eye_config_item_test.dart index b399474..06fee58 100644 --- a/test/model/eagle_eye_config_item_test.dart +++ b/test/model/eagle_eye_config_item_test.dart @@ -2,50 +2,50 @@ import 'package:eagle_eye/model/eagle_eye_config_item.dart'; import 'package:test/test.dart'; void main() { - test('no depends enabled - returns a valid configuration item object', () { + test('dependenciesAllowed - returns a valid configuration item object', () { final noDependsEnabled = { 'filePattern': '*/data/model/*', - 'noDependsEnabled': true + 'dependenciesAllowed': false }; final actual = EagleEyeConfigItem.fromJson(noDependsEnabled); expect( - actual.noDependsEnabled, - true, + actual.dependenciesAllowed, + false, ); expect(actual.filePattern, '*/data/model/*'); - expect(null, actual.doNotWithPatterns); - expect(null, actual.justWithPatterns); + expect(null, actual.forbiddenDependencies); + expect(null, actual.exclusiveDependencies); }); - test('do not with - returns a valid configuration item object', () { + test('forbiddenDependencies - returns a valid configuration item object', () { final doNotWith = { 'filePattern': '*viewmodel.dart', - 'doNotWithPatterns': ['*_screen.dart'] + 'forbiddenDependencies': ['*_screen.dart'] }; final actual = EagleEyeConfigItem.fromJson(doNotWith); expect( - actual.doNotWithPatterns, + actual.forbiddenDependencies, ['*_screen.dart'], ); - expect(actual.noDependsEnabled, null); + expect(actual.dependenciesAllowed, null); expect(actual.filePattern, '*viewmodel.dart'); - expect(actual.justWithPatterns, null); + expect(actual.exclusiveDependencies, null); }); - test('just with - returns a valid configuration item object', () { + test('exclusiveDependencies - returns a valid configuration item object', () { final doNotWith = { 'filePattern': '*screen.dart', - 'justWithPatterns': ['*_widget.dart'] + 'exclusiveDependencies': ['*_widget.dart'] }; final actual = EagleEyeConfigItem.fromJson(doNotWith); - expect(actual.justWithPatterns, ['*_widget.dart']); - expect(actual.doNotWithPatterns, null); - expect(actual.noDependsEnabled, null); + expect(actual.exclusiveDependencies, ['*_widget.dart']); + expect(actual.forbiddenDependencies, null); + expect(actual.dependenciesAllowed, null); expect(actual.filePattern, '*screen.dart'); }); } From 1a938461a657842ed1c5a785b84378a4ca08572e Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 20:32:14 -0300 Subject: [PATCH 02/10] Rename errorInfo data class to analysisErrorInfo --- .../checker/exclusive_dependencies_rule_checker.dart | 10 +++++----- .../checker/forbidden_dependencies_rule_checker.dart | 10 +++++----- lib/analyzer/eagle_eye_visitor.dart | 10 +++++----- lib/eagle_eye_launcher.dart | 4 ++-- .../{error_info.dart => analysis_error_info.dart} | 12 ++++++------ 5 files changed, 23 insertions(+), 23 deletions(-) rename lib/model/{error_info.dart => analysis_error_info.dart} (50%) diff --git a/lib/analyzer/checker/exclusive_dependencies_rule_checker.dart b/lib/analyzer/checker/exclusive_dependencies_rule_checker.dart index b0479db..66961b6 100644 --- a/lib/analyzer/checker/exclusive_dependencies_rule_checker.dart +++ b/lib/analyzer/checker/exclusive_dependencies_rule_checker.dart @@ -1,5 +1,5 @@ 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**. /// @@ -22,9 +22,9 @@ class ExclusiveDependenciesRuleChecker { /// - [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 justWithPatterns, required String importDirective, required String filePath, @@ -35,7 +35,7 @@ class ExclusiveDependenciesRuleChecker { justWithItem, ); if (matches == false) { - return ErrorInfo( + return AnalysisErrorInfo( filePath: filePath, errorMessage: '$filePath should depends only on $justWithPatterns', ); diff --git a/lib/analyzer/checker/forbidden_dependencies_rule_checker.dart b/lib/analyzer/checker/forbidden_dependencies_rule_checker.dart index 30125d1..91a6afc 100644 --- a/lib/analyzer/checker/forbidden_dependencies_rule_checker.dart +++ b/lib/analyzer/checker/forbidden_dependencies_rule_checker.dart @@ -1,5 +1,5 @@ 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 /// @@ -23,9 +23,9 @@ class ForbiddenDependenciesRuleChecker { /// - [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 noDepsWithPatterns, required String importDirective, required String filePath, @@ -36,7 +36,7 @@ class ForbiddenDependenciesRuleChecker { noDepsWithItem, ); if (matches == true) { - return ErrorInfo( + return AnalysisErrorInfo( filePath: filePath, errorMessage: '$filePath should not depends on $importDirective', ); diff --git a/lib/analyzer/eagle_eye_visitor.dart b/lib/analyzer/eagle_eye_visitor.dart index 9b3d6e8..34da6f3 100644 --- a/lib/analyzer/eagle_eye_visitor.dart +++ b/lib/analyzer/eagle_eye_visitor.dart @@ -3,8 +3,8 @@ import 'package:analyzer/dart/ast/visitor.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]. @@ -28,7 +28,7 @@ class EagleEyeVisitor extends RecursiveAstVisitor { 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; @@ -63,7 +63,7 @@ class EagleEyeVisitor extends RecursiveAstVisitor { // Check rules exclusively if (configItem.dependenciesAllowed == false) { errorCallback( - ErrorInfo( + AnalysisErrorInfo( filePath: filePath, errorMessage: '$filePath should not contains any import.', ), @@ -71,7 +71,7 @@ class EagleEyeVisitor extends RecursiveAstVisitor { } else if (configItem.forbiddenDependencies != null) { if (importDirective != null) { final checker = ForbiddenDependenciesRuleChecker(regexHelper); - ErrorInfo? errorInfo = checker.check( + AnalysisErrorInfo? errorInfo = checker.check( noDepsWithPatterns: configItem.forbiddenDependencies!, importDirective: importDirective, filePath: filePath, @@ -84,7 +84,7 @@ class EagleEyeVisitor extends RecursiveAstVisitor { } else if (configItem.exclusiveDependencies != null) { if (importDirective != null) { final checker = ExclusiveDependenciesRuleChecker(regexHelper); - ErrorInfo? errorInfo = checker.check( + AnalysisErrorInfo? errorInfo = checker.check( justWithPatterns: configItem.exclusiveDependencies!, importDirective: importDirective, filePath: filePath, diff --git a/lib/eagle_eye_launcher.dart b/lib/eagle_eye_launcher.dart index 1b2c2af..464a8cc 100644 --- a/lib/eagle_eye_launcher.dart +++ b/lib/eagle_eye_launcher.dart @@ -8,9 +8,9 @@ import 'package:eagle_eye/analyzer/regex_helper.dart'; import 'package:eagle_eye/data/eagle_eye_repository.dart'; import 'package:eagle_eye/data/file_helper.dart'; import 'package:eagle_eye/data/json_converter.dart'; +import 'package:eagle_eye/model/analysis_error_info.dart'; import 'package:eagle_eye/model/eagle_eye_config.dart'; import 'package:eagle_eye/model/eagle_eye_config_item.dart'; -import 'package:eagle_eye/model/error_info.dart'; import 'package:eagle_eye/util/logger_helper.dart'; /// The main launcher for Eagle Eye architecture validation. @@ -86,7 +86,7 @@ class EagleEyeLauncher { config: configFile, regexHelper: RegexHelper(), ); - List errors = []; + List errors = []; for (final file in dartFiles) { final result = parseFile( diff --git a/lib/model/error_info.dart b/lib/model/analysis_error_info.dart similarity index 50% rename from lib/model/error_info.dart rename to lib/model/analysis_error_info.dart index dd0e504..0fedc7c 100644 --- a/lib/model/error_info.dart +++ b/lib/model/analysis_error_info.dart @@ -1,18 +1,18 @@ /// Represents a violation detected by the Eagle Eye analysis. /// -/// Each [ErrorInfo] instance contains the path of the file where the violation -/// occurred ([filePath]) and a descriptive message explaining the issue -/// ([errorMessage]). -class ErrorInfo { +/// Each [AnalysisErrorInfo] instance contains the path of the file +/// where the violation occurred ([filePath]) and a descriptive message +/// explaining the issue ([errorMessage]). +class AnalysisErrorInfo { /// The path of the file where the error was detected. String filePath; /// A descriptive message explaining the violation. String errorMessage; - /// Creates a new [ErrorInfo] instance with the given [filePath] + /// Creates a new [AnalysisErrorInfo] instance with the given [filePath] /// and [errorMessage]. - ErrorInfo({ + AnalysisErrorInfo({ required this.filePath, required this.errorMessage, }); From f32925f9eafff03d2d95acdf09300cc11eeb2447 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 21:50:30 -0300 Subject: [PATCH 03/10] Refactor repository methods to return non-nullable types and improve exception handling --- lib/data/eagle_eye_repository.dart | 47 +++----- lib/data/file_helper.dart | 26 +++-- lib/eagle_eye_launcher.dart | 101 +++++++----------- .../application_name_not_found_exception.dart | 10 ++ .../config_file_not_found_exception.dart | 12 +++ lib/model/exceptions/eagle_eye_exception.dart | 8 ++ .../empty_dart_file_list_exception.dart | 10 ++ .../library_folder_not_found_exception.dart | 10 ++ 8 files changed, 125 insertions(+), 99 deletions(-) create mode 100644 lib/model/exceptions/application_name_not_found_exception.dart create mode 100644 lib/model/exceptions/config_file_not_found_exception.dart create mode 100644 lib/model/exceptions/eagle_eye_exception.dart create mode 100644 lib/model/exceptions/empty_dart_file_list_exception.dart create mode 100644 lib/model/exceptions/library_folder_not_found_exception.dart diff --git a/lib/data/eagle_eye_repository.dart b/lib/data/eagle_eye_repository.dart index 2603e33..e0f44fa 100644 --- a/lib/data/eagle_eye_repository.dart +++ b/lib/data/eagle_eye_repository.dart @@ -18,19 +18,14 @@ abstract class EagleEyeRepository { /// Retrieves and parses the Eagle Eye configuration file /// if it exists in the project root. /// - /// Returns an [EagleEyeConfig] if the file exists and is valid, - /// or `null` otherwise. - Future getAndCheckIfConfigFileExists(); + /// Returns an [EagleEyeConfig] + Future getAndCheckIfConfigFileExists(); /// Returns all Dart files found within the project’s `lib/` directory. - /// - /// Returns `null` if the directory doesn’t exist or cannot be read. - List? allDartFiles(); + List allDartFiles(); /// Returns the application’s name as defined in the project structure. - /// - /// Returns `null` if the name cannot be determined. - String? getApplicationName(); + String getApplicationName(); } // Concrete implementation of [EagleEyeRepository] that uses @@ -61,35 +56,23 @@ class EagleEyeRepositoryImpl extends EagleEyeRepository { }); @override - List? allDartFiles() { - try { - Directory libsDir = fileHelper.getAndCheckIfLibsDirectoryExists( - libsFolderName, - ); - return fileHelper.allDartFiles(libsDir); - } catch (e) { - return null; - } + List allDartFiles() { + Directory libsDir = fileHelper.getAndCheckIfLibsDirectoryExists( + libsFolderName, + ); + return fileHelper.allDartFiles(libsDir); } @override - Future getAndCheckIfConfigFileExists() async { - try { - final String configFileContent = - await fileHelper.getAndCheckIfConfigFileExists(configFileName); + Future getAndCheckIfConfigFileExists() async { + final String configFileContent = + await fileHelper.getAndCheckIfConfigFileExists(configFileName); - return jsonConverter.convert(configFileContent); - } catch (e) { - return null; - } + return jsonConverter.convert(configFileContent); } @override - String? getApplicationName() { - try { - return fileHelper.getApplicationName(); - } catch (e) { - return null; - } + String getApplicationName() { + return fileHelper.getApplicationName(); } } diff --git a/lib/data/file_helper.dart b/lib/data/file_helper.dart index 1823dd5..52d75c7 100644 --- a/lib/data/file_helper.dart +++ b/lib/data/file_helper.dart @@ -1,4 +1,8 @@ import 'dart:io'; +import 'package:eagle_eye/model/exceptions/application_name_not_found_exception.dart'; +import 'package:eagle_eye/model/exceptions/config_file_not_found_exception.dart'; +import 'package:eagle_eye/model/exceptions/empty_dart_file_list_exception.dart'; +import 'package:eagle_eye/model/exceptions/library_folder_not_found_exception.dart'; import 'package:eagle_eye/util/logger_helper.dart'; import 'package:yaml/yaml.dart'; @@ -16,10 +20,11 @@ class FileHelper { /// If the file does not exist, logs an error message via [LoggerHelper]. /// /// Returns the file content as a [String]. + /// Throws a [ConfigFileNotFoundException] if the file is not specified Future getAndCheckIfConfigFileExists(String configFile) async { final file = File(configFile); if (!file.existsSync()) { - LoggerHelper.printError('$configFile not found!'); + throw ConfigFileNotFoundException(); } final textContent = await file.readAsString(); return textContent; @@ -30,11 +35,13 @@ class FileHelper { /// If the directory does not exist, logs an error message via [LoggerHelper]. /// /// Returns the [Directory] representing the `lib/` folder. + /// Throws a [LibraryFolderNotFoundException] if the lib folder is not + /// available. Directory getAndCheckIfLibsDirectoryExists(String libsFolderName) { final projectDirectory = Directory(libsFolderName); if (!projectDirectory.existsSync()) { - LoggerHelper.printError('Folder not found: $libsFolderName'); + throw LibraryFolderNotFoundException(); } return projectDirectory; } @@ -42,22 +49,29 @@ class FileHelper { /// Returns a list of all `.dart` files found recursively in the given /// [directory]. /// - /// Only includes files that end with the `.dart` extensi + /// Return only includes files that end with the `.dart` extension + /// Throw an [EmptyDartFileListException] if there is no dart file available. List allDartFiles(Directory directory) { final dartFiles = directory .listSync(recursive: true) .whereType() .where((f) => f.path.endsWith('.dart')); - return dartFiles.toList(); + if (dartFiles.isEmpty) { + throw EmptyDartFileListException(); + } else { + return dartFiles.toList(); + } } /// Reads the `pubspec.yaml` file and returns the application’s name. /// /// Returns `null` if the `pubspec.yaml` file is missing or cannot be parsed. - String? getApplicationName() { + /// Throw an [ApplicationNameNotFoundException] if no application name was + /// provided in the pubspec.yaml + String getApplicationName() { final pubspecFile = File('pubspec.yaml'); if (!pubspecFile.existsSync()) { - return null; + throw ApplicationNameNotFoundException(); } final content = pubspecFile.readAsStringSync(); diff --git a/lib/eagle_eye_launcher.dart b/lib/eagle_eye_launcher.dart index 464a8cc..13c417d 100644 --- a/lib/eagle_eye_launcher.dart +++ b/lib/eagle_eye_launcher.dart @@ -11,6 +11,7 @@ import 'package:eagle_eye/data/json_converter.dart'; import 'package:eagle_eye/model/analysis_error_info.dart'; import 'package:eagle_eye/model/eagle_eye_config.dart'; import 'package:eagle_eye/model/eagle_eye_config_item.dart'; +import 'package:eagle_eye/model/exceptions/eagle_eye_exception.dart'; import 'package:eagle_eye/util/logger_helper.dart'; /// The main launcher for Eagle Eye architecture validation. @@ -48,77 +49,55 @@ class EagleEyeLauncher { /// - Exits the process with a non-zero code if violations are found or /// critical files are missing. Future launchEagleEye() async { - EagleEyeConfig? configFile = - await _repository.getAndCheckIfConfigFileExists(); - List? dartFiles = _repository.allDartFiles(); + try { + EagleEyeConfig configFile = + await _repository.getAndCheckIfConfigFileExists(); - LoggerHelper.printWarning( - 'Next major release will introduce changes to the ' - 'configuration file. Existing configuration keys ' - 'will be updated for better consistency.', - ); + List dartFiles = _repository.allDartFiles(); - if (configFile == null) { - LoggerHelper.printError( - '❌ Unable to load configuration file. ' - 'Please ensure that an eagle_eye_config.json file exists at the ' - 'root of your project.', - ); - exit(1); - } + String applicationName = _repository.getApplicationName(); - if (dartFiles == null) { - LoggerHelper.printError( - '❌ Unable to load the dart files of your project.', + final EagleEyeMatcher matcher = EagleEyeMatcher( + config: configFile, + regexHelper: RegexHelper(), ); - exit(1); - } - String? applicationName = _repository.getApplicationName(); - if (applicationName == null) { - LoggerHelper.printError( - '❌ Unable to find pubspec.yaml.', - ); - exit(1); - } - - final EagleEyeMatcher matcher = EagleEyeMatcher( - config: configFile, - regexHelper: RegexHelper(), - ); - List errors = []; + List errors = []; - for (final file in dartFiles) { - final result = parseFile( - path: file.path, - featureSet: FeatureSet.latestLanguageVersion(), - ); - EagleEyeConfigItem? eagleEyeItem = matcher.find(file.path); - if (eagleEyeItem != null) { - EagleEyeVisitor visitor = EagleEyeVisitor( - configItem: eagleEyeItem, - filePath: file.path, - applicationName: applicationName, - errorCallback: (error) => errors.add(error), - regexHelper: RegexHelper(), + for (final file in dartFiles) { + final result = parseFile( + path: file.path, + featureSet: FeatureSet.latestLanguageVersion(), ); - result.unit.visitChildren(visitor); + EagleEyeConfigItem? eagleEyeItem = matcher.find(file.path); + if (eagleEyeItem != null) { + EagleEyeVisitor visitor = EagleEyeVisitor( + configItem: eagleEyeItem, + filePath: file.path, + applicationName: applicationName, + errorCallback: (error) => errors.add(error), + regexHelper: RegexHelper(), + ); + result.unit.visitChildren(visitor); + } } - } - - for (var errorInfoItem in errors) { - LoggerHelper.printError( - '${errorInfoItem.errorMessage} - ${errorInfoItem.filePath}', - ); - } - if (errors.isEmpty) { - LoggerHelper.printSuccess('Verification finished'); - } else { - LoggerHelper.printError( - 'Verification failed with ${errors.length} errors', - ); + for (var errorInfoItem in errors) { + LoggerHelper.printError( + '${errorInfoItem.errorMessage} - ${errorInfoItem.filePath}', + ); + } + if (errors.isEmpty) { + LoggerHelper.printSuccess('Verification finished'); + } else { + LoggerHelper.printError( + 'Verification failed with ${errors.length} errors', + ); + exit(1); + } + } on EagleEyeException catch (e) { + LoggerHelper.printError(e.message); exit(1); } } diff --git a/lib/model/exceptions/application_name_not_found_exception.dart b/lib/model/exceptions/application_name_not_found_exception.dart new file mode 100644 index 0000000..2fa7c9b --- /dev/null +++ b/lib/model/exceptions/application_name_not_found_exception.dart @@ -0,0 +1,10 @@ +/// [ApplicationNameNotFoundException] defines an exception when +/// the application name is not specified at pubspec.yaml file. +class ApplicationNameNotFoundException implements Exception { + /// User friendly message describing the issue. + final String message = '❌ Unable to detect the name of you app. ' + 'Please define it in your pubspec.yaml.'; + + /// Creates [ApplicationNameNotFoundException] object + ApplicationNameNotFoundException(); +} diff --git a/lib/model/exceptions/config_file_not_found_exception.dart b/lib/model/exceptions/config_file_not_found_exception.dart new file mode 100644 index 0000000..33f5dc7 --- /dev/null +++ b/lib/model/exceptions/config_file_not_found_exception.dart @@ -0,0 +1,12 @@ +import 'package:eagle_eye/model/exceptions/eagle_eye_exception.dart'; + +/// [ConfigFileNotFoundException] defines an exception when +/// the configuration file is missing. +class ConfigFileNotFoundException extends EagleEyeException { + /// Create [ConfigFileNotFoundException] object + ConfigFileNotFoundException() { + super.message = '❌ Unable to load configuration file. ' + 'Please ensure that an eagle_eye_config.json file exists at the ' + 'root of your project.'; + } +} diff --git a/lib/model/exceptions/eagle_eye_exception.dart b/lib/model/exceptions/eagle_eye_exception.dart new file mode 100644 index 0000000..861a5a8 --- /dev/null +++ b/lib/model/exceptions/eagle_eye_exception.dart @@ -0,0 +1,8 @@ +/// [EagleEyeException] defines a base exception. +class EagleEyeException { + /// User friendly message describing the error + String message = 'Something went wrong'; + + /// Create [EagleEyeException] object + EagleEyeException(); +} diff --git a/lib/model/exceptions/empty_dart_file_list_exception.dart b/lib/model/exceptions/empty_dart_file_list_exception.dart new file mode 100644 index 0000000..b212494 --- /dev/null +++ b/lib/model/exceptions/empty_dart_file_list_exception.dart @@ -0,0 +1,10 @@ +import 'package:eagle_eye/model/exceptions/eagle_eye_exception.dart'; + +/// [EmptyDartFileListException] defines an exception when +/// no dart file was founded. +class EmptyDartFileListException extends EagleEyeException { + /// Creates [EmptyDartFileListException] object + EmptyDartFileListException() { + super.message = '❌ Unable to load the dart files of your project.'; + } +} diff --git a/lib/model/exceptions/library_folder_not_found_exception.dart b/lib/model/exceptions/library_folder_not_found_exception.dart new file mode 100644 index 0000000..bed642a --- /dev/null +++ b/lib/model/exceptions/library_folder_not_found_exception.dart @@ -0,0 +1,10 @@ +import 'package:eagle_eye/model/exceptions/eagle_eye_exception.dart'; + +/// [ConfigFileNotFoundException] defines an exception when +/// the configuration file is missing. +class LibraryFolderNotFoundException extends EagleEyeException { + /// Create [LibraryFolderNotFoundException] object + LibraryFolderNotFoundException() { + super.message = '❌ libs folder was not found'; + } +} From bdf548df3450dcf9175865f6429a332e447a1008 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 22:29:11 -0300 Subject: [PATCH 04/10] Create InvalidJsonKeyException to signalize the keys that are not supported --- lib/data/json_converter.dart | 24 +++++++++++++++++-- .../invalid_json_key_exception.dart | 23 ++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 lib/model/exceptions/invalid_json_key_exception.dart diff --git a/lib/data/json_converter.dart b/lib/data/json_converter.dart index d7e0a9d..4f15f4a 100644 --- a/lib/data/json_converter.dart +++ b/lib/data/json_converter.dart @@ -1,7 +1,9 @@ import 'dart:convert'; +import 'package:eagle_eye/model/config_keys.dart'; import 'package:eagle_eye/model/eagle_eye_config.dart'; import 'package:eagle_eye/model/eagle_eye_config_item.dart'; +import 'package:eagle_eye/model/exceptions/invalid_json_key_exception.dart'; /// A utility class that converts JSON configuration data /// into [EagleEyeConfig] and [EagleEyeConfigItem] objects. @@ -16,6 +18,20 @@ import 'package:eagle_eye/model/eagle_eye_config_item.dart'; /// - `justWithPatterns` — defines allowed dependency patterns /// - `filePattern` — defines which files the rule applies to class JsonConverter { + void _checkKeys(List keys) { + final validKeys = [ + ConfigKeys.filePatternEagleItemKey, + ConfigKeys.dependenciesAllowedEagleItemKey, + ConfigKeys.exclusiveDependenciesEagleItemKey, + ConfigKeys.forbiddenDependenciesEagleItemKey, + ]; + for (var key in keys.toList()) { + if (validKeys.contains(key) == false) { + throw InvalidJsonKeyException(); + } + } + } + /// Converts a JSON string ([jsonText]) into an [EagleEyeConfig] object. /// /// The JSON is expected to be an array of configuration items. @@ -24,9 +40,13 @@ class JsonConverter { List jsonData = jsonDecode(jsonText); List eagleConfigItems = []; - for (var jsonItem in jsonData) { + for (var jsonDataItem in jsonData) { + final jsonItem = jsonDataItem as Map; + + _checkKeys(jsonItem.keys.toList()); + EagleEyeConfigItem configItem = EagleEyeConfigItem.fromJson( - jsonItem as Map, + jsonItem, ); eagleConfigItems.add(configItem); } diff --git a/lib/model/exceptions/invalid_json_key_exception.dart b/lib/model/exceptions/invalid_json_key_exception.dart new file mode 100644 index 0000000..885a1f4 --- /dev/null +++ b/lib/model/exceptions/invalid_json_key_exception.dart @@ -0,0 +1,23 @@ +import 'package:eagle_eye/model/exceptions/eagle_eye_exception.dart'; + +/// [InvalidJsonKeyException] defines an error deprecated +/// keys are used: doNotWithPatterns, justWithPatterns, and +/// noDependsEnabled. +class InvalidJsonKeyException extends EagleEyeException { + /// Create [InvalidJsonKeyException] object + InvalidJsonKeyException() { + super.message = '❌ Invalid keys found in configuration file.' + '\n\n' + 'The following keys have been discontinued and are no longer supported:' + '\n' + '• doNotWithPatterns\n' + '• justWithPatterns\n' + '• noDependsEnabled\n' + '\n' + 'To fix this, please update your configuration to use the new naming ' + 'convention:\n' + ' - doNotWithPatterns → forbiddenDependencies\n' + ' - justWithPatterns → exclusiveDependencies\n' + ' - noDependsEnabled → dependenciesAllowed: false\n'; + } +} From a8b21944684a8cbfdff6929bfcff5749cc85024f Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 22:36:20 -0300 Subject: [PATCH 05/10] Bump version and add release updates --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 096a6ba..780598d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/pubspec.yaml b/pubspec.yaml index 1fda69c..e592ab8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: eagle_eye description: "EagleEye is a Dart CLI tool provided by CodandoTV for detecting architecture violations in Dart projects." homepage: "https://github.com/CodandoTV/eagle-eye" -version: 1.0.5 +version: 2.0.0 environment: sdk: ^3.5.0 From d2edf294478c4c9c5679f398021aac6592bf59a1 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 22:56:09 -0300 Subject: [PATCH 06/10] Update getting-started page --- doc/1-getting-started.md | 47 +++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/doc/1-getting-started.md b/doc/1-getting-started.md index 2dab262..b4b7f17 100644 --- a/doc/1-getting-started.md +++ b/doc/1-getting-started.md @@ -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 + } ] ``` From 12f85575dca89ffa776c20bd8a32c3bf3e73920f Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 23:02:23 -0300 Subject: [PATCH 07/10] Update documentation --- doc/2-existing-rules.md | 65 +++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/doc/2-existing-rules.md b/doc/2-existing-rules.md index 6be51ed..291b2ea 100644 --- a/doc/2-existing-rules.md +++ b/doc/2-existing-rules.md @@ -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 }, ``` From 81b7442324e179949e4793f93f2adbc4b7c3b373 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Fri, 16 Jan 2026 23:03:37 -0300 Subject: [PATCH 08/10] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 39e8d65..613fb34 100644 --- a/README.md +++ b/README.md @@ -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"] } ] ``` From 33932e0b545259b3ba4f1a34702da0414afac7e2 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Sat, 17 Jan 2026 09:49:08 -0300 Subject: [PATCH 09/10] Solve Missing type annotation issue --- lib/analyzer/eagle_eye_matcher.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/analyzer/eagle_eye_matcher.dart b/lib/analyzer/eagle_eye_matcher.dart index 58c9622..d61c603 100644 --- a/lib/analyzer/eagle_eye_matcher.dart +++ b/lib/analyzer/eagle_eye_matcher.dart @@ -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, From f8514490213cf5f8d0353624bfcd02ebe2a64e89 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Sat, 17 Jan 2026 10:33:38 -0300 Subject: [PATCH 10/10] Update pipeline trigger to deploy documentation --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 39b389a..38e5836 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -5,7 +5,7 @@ on: branches: - main paths: - - 'docs/**' + - 'doc/**' - 'mkdocs.yml' permissions: contents: write