mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
- Fully migrated core cherrypick_generator and submodules to new analyzer element2 system: - Updated all GeneratorForAnnotation overrides to use Element2, ClassElement2, MethodElement2, FieldElement2 and new annotation/metadata access patterns. - Migrated signature and bodies for helpers, parsers, annotation validators, meta utils, and type parsers. - Fixed tests to use readerWriter instead of deprecated reader argument. - Refactored usage of now-absent 'metadata', 'parameters', 'fields', 'methods', 'source', and similar members to use correct *.firstFragment.* or API alternatives. - Cleaned up old imports and unused code. test(generator): update generator integration tests - Updated test calls to use correct TestReaderWriter type and bring test infra in line with current build_runner/testing API. build: update dependencies and pubspec to support latest analyzer/build ecosystem - Raised Dart SDK and package constraints as required for generated code and codegen plugins. - Updated pubspecs in root/examples as needed by build warnings. docs: add plots and assets (new files) BREAKING CHANGE: - Requires Dart 3.8+ and analyzer that supports element2. - All downstream codegen/tests depending on Element API must migrate to Element2 signatures and data model.
108 lines
4.1 KiB
Dart
108 lines
4.1 KiB
Dart
//
|
|
// Copyright 2021 Sergey Penkovsky (sergey.penkovsky@gmail.com)
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import 'package:analyzer/dart/element/element2.dart';
|
|
import 'package:build/build.dart';
|
|
import 'package:source_gen/source_gen.dart';
|
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann;
|
|
|
|
import 'src/generated_class.dart';
|
|
|
|
/// ---------------------------------------------------------------------------
|
|
/// CherryPick Module Generator — Codegen for DI modules
|
|
///
|
|
/// This generator scans Dart classes annotated with `@module()` and generates
|
|
/// boilerplate for dependency injection registration automatically. Each public
|
|
/// method in such classes can be annotated to describe how an object should be
|
|
/// bound to the DI container (singleton, factory, named, with parameters, etc).
|
|
///
|
|
/// The generated code collects all such bind methods and produces a Dart
|
|
/// companion *module registration class* with a `.bindAll()` method, which you
|
|
/// can use from your DI root to automatically register those dependencies.
|
|
///
|
|
/// ## Example
|
|
/// ```dart
|
|
/// import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
|
///
|
|
/// @module()
|
|
/// abstract class AppModule {
|
|
/// @singleton()
|
|
/// Logger logger() => Logger();
|
|
///
|
|
/// @provide()
|
|
/// ApiService api(Logger logger) => ApiService(logger);
|
|
///
|
|
/// @named('dev')
|
|
/// FakeService fake() => FakeService();
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// After codegen, you will get (simplified):
|
|
/// ```dart
|
|
/// class _\$AppModuleCherrypickModule extend AppModule {
|
|
/// static void bindAll(CherryPickScope scope, AppModule module) {
|
|
/// scope.addSingleton<Logger>(() => module.logger());
|
|
/// scope.addFactory<ApiService>(() => module.api(scope.resolve<Logger>()));
|
|
/// scope.addFactory<FakeService>(() => module.fake(), named: 'dev');
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// Use it e.g. in your bootstrap:
|
|
/// ```dart
|
|
/// final scope = CherryPick.openRootScope()..intallModules([_\$AppModuleCherrypickModule()]);
|
|
/// ```
|
|
///
|
|
/// Features supported:
|
|
/// - Singleton, factory, named, parametric, and async providers
|
|
/// - Eliminates all boilerplate for DI registration
|
|
/// - Works with abstract classes and real classes
|
|
/// - Error if @module() is applied to a non-class
|
|
///
|
|
/// See also: [@singleton], [@provide], [@named], [@module]
|
|
/// ---------------------------------------------------------------------------
|
|
|
|
class ModuleGenerator extends GeneratorForAnnotation<ann.module> {
|
|
/// Generates Dart source for a class marked with the `@module()` annotation.
|
|
///
|
|
/// Throws [InvalidGenerationSourceError] if used on anything except a class.
|
|
///
|
|
/// See file-level docs for usage and generated output example.
|
|
@override
|
|
dynamic generateForAnnotatedElement(
|
|
Element2 element,
|
|
ConstantReader annotation,
|
|
BuildStep buildStep,
|
|
) {
|
|
if (element is! ClassElement2) {
|
|
throw InvalidGenerationSourceError(
|
|
'@module() can only be applied to classes.',
|
|
element: element,
|
|
);
|
|
}
|
|
|
|
final classElement = element;
|
|
final generatedClass = GeneratedClass.fromClassElement(classElement);
|
|
return generatedClass.generate();
|
|
}
|
|
}
|
|
|
|
/// ---------------------------------------------------------------------------
|
|
/// Codegen builder entry point: register this builder in build.yaml or your package.
|
|
///
|
|
/// Used by build_runner. Generates .module.cherrypick.g.dart files for each
|
|
/// source file with an annotated @module() class.
|
|
/// ---------------------------------------------------------------------------
|
|
Builder moduleBuilder(BuilderOptions options) =>
|
|
PartBuilder([ModuleGenerator()], '.module.cherrypick.g.dart');
|