clean_architecture_linter 1.1.1
clean_architecture_linter: ^1.1.1 copied to clipboard
A comprehensive custom lint package that automatically enforces Clean Architecture principles in Flutter projects with Riverpod state management.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased] #
1.1.1 - 2025-01-30 #
๐ฆ Dependencies #
- Updated analyzer to ^8.0.0
- Now supports analyzer 8.x versions (currently 8.1.1)
- Improved compatibility with latest Dart SDK features
- All 527 tests passing with new analyzer version
1.1.0 - 2025-01-30 #
โ ๏ธ Breaking Changes #
- Minimum Dart SDK version increased to 3.8.0
- Required for
lints ^6.0.0compatibility - Users on older Dart versions should use
clean_architecture_linter: ^1.0.6 - GitHub Actions CI now tests against Dart 3.8.0 and stable
- Required for
๐ง Fixed #
-
Fixed ObjectBox and Realm false positive warnings
- Added
package:objectbox/andpackage:realm/to allowed infrastructure imports for data layer - These local database libraries are now properly recognized as legitimate data layer dependencies
- Aligns with other database packages like SQLite, Hive, Drift, and Isar
- Added
-
Fixed database container type detection in DataSource abstraction rule
- Improved
_returnsEntitymethod to properly extract innermost generic types - Now correctly handles ObjectBox
Box<T>, HiveLazyBox<T>, IsarIsarCollection<T>container types Box<UserModel>is now correctly identified as returning Model (not Entity)Box<UserEntity>is correctly flagged as violating the rule (Entity should not be returned from DataSource)- Supports nested generics:
Future<List<TodoModel>>,Stream<Either<Failure, UserModel>> - Added proper generic type unwrapping for Result/Either types (extracts success type)
- Private methods/getters (starting with
_) are now skipped - they are internal implementation details - Allows private database helpers like
Box<Entity> get _userBoxfor internal use
- Improved
-
Fixed Model structure rule to skip local storage models
- Models with local storage annotations (
@Entity,@Collection,@HiveType, etc.) now skip Freezed requirement - ObjectBox, Isar, Hive, and Drift models require mutable classes and cannot use
@freezed - Prevents false positive warnings for models that must be stored in local databases
- Supported annotations:
@Entity(ObjectBox),@Collection(Isar),@HiveType(Hive),@UseRowClass/@DataClassName(Drift)
- Models with local storage annotations (
-
Code formatting
- Applied
dart formatto all files for consistent code style - Ensures CI formatting checks pass
- Applied
1.0.6 - 2025-10-28 #
๐ง Fixed #
- Fixed package dependencies structure
- Moved
analyzer,custom_lint_builder, andpathback todependencies - These packages are used in
lib/code and must be runtime dependencies custom_lint,lints, andtestremain indev_dependencies- Note: End users still add this package to
dev_dependenciesin their projects
- Moved
๐ฆ Dependencies #
- Runtime dependencies (used in lib/):
analyzer,custom_lint_builder,path - Dev dependencies (development only):
custom_lint,lints,test
1.0.5 - 2025-10-28 #
๐ง Changed #
- Upgraded custom_lint_builder from
0.7.6to0.8.0- Ensures compatibility with riverpod_generator 3.0.0
- Upgraded custom_lint dev dependency to
0.8.0 - All 527 tests pass successfully
- No breaking API changes required
- Maintains backward compatibility
๐ฆ Dependencies #
custom_lint_builder: ^0.7.6 โ ^0.8.0custom_lint: ^0.7.6 โ ^0.8.0 (dev dependency)
[Unreleased] #
โจ Added (2 new rules) #
-
riverpod_ref_usage rule - Enforce proper ref.watch() vs ref.read() usage in Riverpod providers
- Validates State providers in build(): use
ref.watch()for reactive dependencies - Validates UseCase providers in build(): use
ref.read()for one-time calls - Validates all providers in methods: use
ref.read()for one-time reads - Smart UseCase provider detection by naming convention and immediate function calls
- Allows
.notifieraccess withref.read() - Comprehensive error messages explaining State vs UseCase provider distinction
- 34 unit tests with 100% pass rate
- Severity: WARNING
- Validates State providers in build(): use
-
riverpod_provider_naming rule - Enforce provider function naming conventions for code generation
- Repository return type โ function name must end with "repository"
- UseCase return type โ function name must end with "usecase"
- DataSource return type โ function name must end with "datasource"
- Ensures clear provider name generation (e.g.,
getEventsUsecaseProvidervsgetEventsProvider) - Enables automatic UseCase provider detection in ref usage rules
- Auto-suggests corrected function names
- 24 unit tests with 100% pass rate
- Severity: WARNING
๐ Changed #
- Total rules: 33 (was 31 in v1.0.4)
- Added: 2 new Riverpod validation rules
- Presentation layer rules: 11 (was 9)
๐ Documentation #
-
README.md
- Added Riverpod dependency note at the top
- Updated requirements section to mention Riverpod
- Updated rule count from 29 to 33
- Added descriptions for new Riverpod rules
-
CLAUDE.md
- Added "Incorrect ref.watch() / ref.read() Usage" violation section
- Added "Provider Function Missing Type Suffix" violation section
- Comprehensive examples for both good and bad patterns
- Explained UseCase vs State provider distinction
- Provider naming conventions and code generation impact
- UseCase provider identification patterns
-
pubspec.yaml
- Updated description to mention Riverpod state management
- Added "riverpod" and "flutter" to topics
๐งช Testing #
- Added 58 new unit tests (34 + 24) for Riverpod rules
- All tests passing with comprehensive coverage
- Test files:
test/src/rules/presentation_rules/riverpod_ref_usage_rule_test.darttest/src/rules/presentation_rules/riverpod_provider_naming_rule_test.dart
1.0.4 - 2025-10-22 #
โจ Added (2 new rules) #
-
widget_no_usecase_call rule - Enforce proper Riverpod architecture: Widget โ Provider โ UseCase
- Prevents widgets from directly importing or calling UseCases
- Enforces proper separation: Widgets should only interact with Providers
- Detects UseCase imports in widget/page files
- Detects direct UseCase provider calls via
ref.read()orref.watch() - Provides comprehensive correction messages with proper Riverpod patterns
- Severity: WARNING
-
widget_ref_read_then_when rule - Prevent anti-pattern of using
.when()afterref.read()- Detects
ref.read()followed by.when()in the same function - Enforces proper patterns:
ref.watch()+.when()for UI,ref.listen()for side effects - Prevents misuse of AsyncValue state management
- Explains why this pattern is incorrect (state is already settled after operation)
- Provides three correct alternatives based on use case
- Severity: WARNING
- Detects
๐ Changed #
-
presentation_no_throw rule - Enhanced detection capabilities
- Now checks
/providers/directory in addition to/states/and/state/ - Improved State/Notifier class detection with three methods:
- Detects
@riverpodannotation (Riverpod Generator pattern) - Detects
extends AsyncNotifier/Notifier/StateNotifier/ChangeNotifier - Detects generated classes with
_$prefix
- Detects
- More robust validation of Riverpod-based state management classes
- Better coverage of modern Riverpod code generation patterns
- Now checks
-
Total rules: 31 (was 29 in v1.0.3)
- Added: 2 new presentation layer rules
- Modified: 1 rule (presentation_no_throw)
๐ Documentation #
- Enhanced CLAUDE.md with comprehensive Riverpod state management patterns
- Added 3-tier provider architecture documentation
- Documented Entity Providers (AsyncNotifier), UI State Providers (Notifier), and Computed Logic Providers
- Added detailed examples of AsyncValue.when() pattern usage
- Included common violations and their solutions
- Comprehensive Widget usage examples with proper error handling
๐ Statistics #
- Files changed: 5 files
- 2 new rule implementations
- 1 rule enhancement
- 1 test file
- 1 main registration file
- Lines added: ~600+ lines
- widget_no_usecase_call_rule.dart: 265 lines
- widget_ref_read_then_when_rule.dart: 301 lines
- Enhanced presentation_no_throw_rule.dart
- Test coverage: Comprehensive unit tests for widget_no_usecase_call rule
1.0.3 - 2025-10-17 #
โจ Added (3 new rules) #
-
model_entity_direct_access rule - Enforce
.toEntity()method usage instead of direct.entityproperty access in Data layer- Prevents direct
.entityaccess in Repository and DataSource implementations - Allows direct access inside extension methods (where conversion logic is implemented)
- Allows direct access in test files
- Provides clear architectural boundaries for Model โ Entity conversion
- Prevents direct
-
model_naming_convention rule - Enforce naming conventions for Models in Data layer
- Models must end with
Modelsuffix - Validates proper naming in
data/models/directories - Helps maintain consistent codebase structure
- Models must end with
-
presentation_no_throw rule - Enforce no exception throwing in Presentation layer
- Presentation layer should use AsyncValue for error handling
- No direct exception throws in widgets, states, or notifiers
- Aligns with Riverpod best practices
๐ Changed #
-
model_conversion_methods rule - Updated to align with Dart/Freezed best practices
- Now only requires
toEntity()method in extensions (mandatory) fromEntity()implementation is optional and should use factory constructors in the Model class- Removed extension static method pattern (not idiomatic in Dart)
- Updated error messages to guide users toward factory constructor pattern
- Now only requires
-
Total rules: 29 (was 26 in v1.0.2)
- Added: 3 new rules
- Modified: 1 rule (model_conversion_methods)
๐ Bug Fixes #
- Fixed
exception_naming_conventionrule to skipcore/directory (framework-level exceptions) - Fixed
failure_naming_conventionrule to skipcore/directory - Fixed data file detection to correctly exclude
domain/repositories/from data layer - Fixed
model_conversion_methodsrule incorrectly requiring extension static methods - Improved error severity levels across multiple rules
๐ Documentation #
- Updated CLAUDE.md with comprehensive
.entityaccess control guidelines - Updated Data Layer rules README with all 3 new rules documentation
- Enhanced Model conversion pattern examples with factory constructor approach
- Added 48 new lines of documentation in CLAUDE.md
- Added 55 new lines in Data Layer README
- Updated README.md with accurate rule count
๐ Statistics #
- Files changed: 23 files
- Lines added: ~1,237 lines
- New test coverage: 398+ lines of new tests for new rules
- Documentation improvements: 100+ lines across multiple files
1.0.2 - 2025-10-09 #
๐๏ธ Removed #
- entity_business_logic rule - Removed overly strict rule requiring all entities to have business logic methods
- Not all entities need business logic (e.g., events, DTOs, value objects)
- Users reported this as too restrictive for practical use cases
- Total rules: 27 โ 26
๐ Documentation #
- Fixed incomplete code snippet in README.md examples section
- Synchronized README_KO.md structure with README.md (removed inconsistent sections)
- Updated rule count from 27 to 26 in both English and Korean READMEs
1.0.1 - 2025-10-09 #
๐ Documentation #
- Updated README.md with accurate rule count (27 rules instead of 16+)
- Updated README_KO.md with accurate rule count and simplified structure
- Simplified configuration section, removed non-existent Core/Strict modes
- Reorganized rules documentation with clear categorization
- Removed unnecessary documentation files (VALIDATION_REPORT.md, ERROR_HANDLING_RULES_TODO.md)
๐ง CI/CD #
- Improved publish workflow to use official OIDC-based authentication
- Added quality checks (tests, analyzer, format) before publishing
- Aligned publish workflow with CI workflow for consistency
1.0.0 - 2025-10-09 #
๐ Initial Release #
A comprehensive custom lint package that automatically enforces Clean Architecture principles in Flutter/Dart projects.
โจ Added #
New Utility Infrastructure
- CleanArchitectureUtils - Centralized utility class for common Clean Architecture validations
- File path detection (isDomainFile, isDataFile, isPresentationFile)
- Component detection (isUseCaseFile, isDataSourceFile, isRepositoryFile)
- Class name validation (isUseCaseClass, isDataSourceClass, isRepositoryClass)
- Type checking (isVoidType, isResultType)
- Exception pattern recognition (isDataException, isDomainException)
- AST utilities (findParentClass, isPrivateMethod, isRethrow)
- Feature extraction (extractFeatureName)
New Mixin System
- ExceptionValidationMixin - Exception naming and validation logic
- ReturnTypeValidationMixin - Return type validation for methods
- RepositoryRuleVisitor - Repository-specific validation
๐ Changed #
Code Organization
- 170 lines removed (13.6% code reduction) through deduplication
- Consolidated 13 rules to use shared mixins and utilities
- Improved consistency across all validation logic
- Enhanced test coverage with 76 comprehensive tests
Refactored All 24 Rules
All lint rules were refactored to leverage the new utility and mixin infrastructure:
Cross-Layer Rules (4)
- LayerDependencyRule
- CircularDependencyRule
- BoundaryCrossingRule
- TestCoverageRule
Domain Layer Rules (4)
- DomainPurityRule
- DependencyInversionRule
- RepositoryInterfaceRule
- UseCaseNoResultReturnRule
- UseCaseMustConvertFailureRule
- ExceptionNamingConventionRule
- ExceptionMessageLocalizationRule
Data Layer Rules (7)
- ModelStructureRule
- DataSourceAbstractionRule
- DataSourceNoResultReturnRule
- RepositoryMustReturnResultRule
- RepositoryNoThrowRule
- DataSourceExceptionTypesRule
- FailureNamingConventionRule
Presentation Layer Rules (6)
- NoPresentationModelsRule
- ExtensionLocationRule
- FreezedUsageRule
- RiverpodGeneratorRule
- PresentationNoDataExceptionsRule
- PresentationUseAsyncValueRule
๐ Improved #
Documentation
- Added comprehensive ARCHITECTURE.md with system overview
- Created CONTRIBUTING.md with development guidelines
- Added RULE_DEVELOPMENT_GUIDE.md for contributors
- Enhanced inline documentation across all files
Testing
- 76 comprehensive tests covering all utilities and mixins
- 100% coverage of utility methods
- Extensive mixin behavior validation
Code Quality
- Eliminated 170 lines of duplicate code
- Consistent validation patterns across all rules
- Improved error messages with better context
- Enhanced maintainability through shared components
๐ง Technical Details #
Dependencies
- Dart SDK: ^3.6.0
- analyzer: ^7.6.0
- custom_lint_builder: ^0.7.6
- path: ^1.9.1