cherrypick_generator 3.0.1
cherrypick_generator: ^3.0.1 copied to clipboard
Source code generator for the cherrypick dependency injection system. Processes annotations to generate binding and module code for Dart & Flutter projects.
Cherrypick Generator #
Cherrypick Generator is a Dart code generation library for automating dependency injection (DI) boilerplate. It processes classes and fields annotated with cherrypick_annotations and generates registration code for services, modules, and field injection for classes marked as @injectable. It supports advanced DI features such as scopes, named bindings, parameters, and asynchronous dependencies.
Features #
-
Automatic Field Injection:
Detects classes annotated with@injectable(), and generates mixins to inject all fields annotated with@inject(), supporting scope and named qualifiers. -
Module and Service Registration:
For classes annotated with@module(), generates service registration code for methods using annotations such as@provide,@instance,@singleton,@named, and@params. -
Scope & Named Qualifier Support:
Supports advanced DI features:
• Field-level scoping with@scope('scopename')
• Named dependencies via@named('value') -
Synchronous & Asynchronous Support:
Handles both synchronous and asynchronous services (includingFuture<T>) for both field injection and module registration. -
Parameters and Runtime Arguments:
Recognizes and wires both injected dependencies and runtime parameters using@params. -
Error Handling:
Validates annotations at generation time. Provides helpful errors for incorrect usage (e.g., using@injectableon non-class elements).
How It Works #
1. Annotate your code #
Use annotations from cherrypick_annotations:
@injectable()— on classes to enable field injection@inject()— on fields to specify they should be injected@scope(),@named()— on fields or parameters for advanced wiring@module()— on classes to mark as DI modules@provide,@instance,@singleton,@params— on methods and parameters for module-based DI
2. Run the generator #
Use build_runner to process your code and generate .module.cherrypick.g.dart and .inject.cherrypick.g.dart files.
3. Use the output in your application #
- For modules: Register DI providers using the generated
$YourModuleclass. - For services: Enable field injection on classes using the generated mixin.
Field Injection Example #
Given the following:
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
@injectable()
class MyWidget with _$MyWidget {
@inject()
late final AuthService auth;
@inject()
@scope('profile')
late final ProfileManager manager;
@inject()
@named('special')
late final ApiClient specialApi;
}
The generator will output (simplified):
mixin _$MyWidget {
void _inject(MyWidget instance) {
instance.auth = CherryPick.openRootScope().resolve<AuthService>();
instance.manager = CherryPick.openScope(scopeName: 'profile').resolve<ProfileManager>();
instance.specialApi = CherryPick.openRootScope().resolve<ApiClient>(named: 'special');
}
}
You can then mix this into your widget to enable automatic DI at runtime.
Module Registration Example #
Given:
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
@module()
class MyModule {
@singleton
@instance
AuthService provideAuth(Api api);
@provide
@named('logging')
Future<Logger> provideLogger(@params Map<String, dynamic> args);
}
The generator will output (simplified):
final class $MyModule extends MyModule {
@override
void builder(Scope currentScope) {
bind<AuthService>()
.toInstance(provideAuth(currentScope.resolve<Api>()))
.singleton();
bind<Logger>()
.toProvideAsyncWithParams((args) => provideLogger(args))
.withName('logging');
}
}
Key Points #
- Rich Annotation Support: Mix and match field, parameter, and method annotations for maximum flexibility.
- Scope and Named Resolution:
Use
@scope('...')and@named('...')to precisely control where and how dependencies are wired. - Async/Synchronous:
The generator distinguishes between sync (resolve<T>) and async (resolveAsync<T>) dependencies. - Automatic Mixins:
For classes with@injectable(), a mixin is generated that injects all relevant fields (using constructor or setter). - Comprehensive Error Checking:
Misapplied annotations (e.g.,@injectable()on non-class) produce clear build-time errors.
Usage #
-
Add dependencies
dependencies: cherrypick_annotations: ^latest dev_dependencies: cherrypick_generator: ^latest build_runner: ^2.1.0 -
Annotate your classes and modules as above
-
Run the generator
dart run build_runner build # or, if using Flutter: flutter pub run build_runner build -
Use generated code
- Import the generated
.inject.cherrypick.g.dartor.cherrypick.g.dartfiles where needed
- Import the generated
Advanced Usage #
- Combining Modules and Field Injection:
It's possible to mix both style of DI — modules for binding, and field injection for consuming services. - Parameter and Named Injection:
Use@namedon both provider and parameter for named registration and lookup; use@paramsto pass runtime arguments. - Async Factories:
Methods returning Future
Developer Notes #
- The generator relies on the Dart analyzer,
source_gen, andbuildpackages. - All classes and methods are parsed for annotations.
- Improper annotation usage will result in generator errors.
License #
Licensed under the Apache License, Version 2.0
Contribution #
Pull requests and issues are welcome! Please open GitHub issues or submit improvements.