mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-24 05:25:19 +00:00
Compare commits
18 Commits
cherrypick
...
cherrypick
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21955640d9 | ||
|
|
a62052daa5 | ||
|
|
7dbaa59c01 | ||
|
|
8438697107 | ||
|
|
9c42ba4cef | ||
|
|
1f6ee172a1 | ||
|
|
161e9085f4 | ||
|
|
ef49595627 | ||
|
|
0fd10488f3 | ||
|
|
46c2939125 | ||
|
|
6d5537f068 | ||
|
|
2480757797 | ||
|
|
f8340c6a84 | ||
|
|
62a1655728 | ||
|
|
fc941c0041 | ||
|
|
5161fa19b6 | ||
|
|
8093f077b1 | ||
|
|
45b93db6f5 |
80
CHANGELOG.md
80
CHANGELOG.md
@@ -3,6 +3,86 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## 2025-05-23
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`cherrypick_annotations` - `v1.1.0-dev.1`](#cherrypick_annotations---v110-dev1)
|
||||||
|
- [`cherrypick_generator` - `v1.1.0-dev.3`](#cherrypick_generator---v110-dev3)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `cherrypick_annotations` - `v1.1.0-dev.1`
|
||||||
|
|
||||||
|
- **FEAT**: implement InjectGenerator.
|
||||||
|
|
||||||
|
#### `cherrypick_generator` - `v1.1.0-dev.3`
|
||||||
|
|
||||||
|
- **FEAT**: implement InjectGenerator.
|
||||||
|
|
||||||
|
|
||||||
|
## 2025-05-23
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`cherrypick_generator` - `v1.1.0-dev.2`](#cherrypick_generator---v110-dev2)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `cherrypick_generator` - `v1.1.0-dev.2`
|
||||||
|
|
||||||
|
- **FIX**: update instance generator code.
|
||||||
|
|
||||||
|
|
||||||
|
## 2025-05-22
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`cherrypick` - `v2.2.0-dev.1`](#cherrypick---v220-dev1)
|
||||||
|
- [`cherrypick_generator` - `v1.1.0-dev.1`](#cherrypick_generator---v110-dev1)
|
||||||
|
- [`cherrypick_flutter` - `v1.1.2-dev.1`](#cherrypick_flutter---v112-dev1)
|
||||||
|
|
||||||
|
Packages with dependency updates only:
|
||||||
|
|
||||||
|
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||||
|
|
||||||
|
- `cherrypick_flutter` - `v1.1.2-dev.1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `cherrypick` - `v2.2.0-dev.1`
|
||||||
|
|
||||||
|
- **FIX**: fix warnings.
|
||||||
|
|
||||||
|
#### `cherrypick_generator` - `v1.1.0-dev.1`
|
||||||
|
|
||||||
|
- **FIX**: optimize code.
|
||||||
|
|
||||||
|
|
||||||
## 2025-05-22
|
## 2025-05-22
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 2.2.0-dev.1
|
||||||
|
|
||||||
|
- **FIX**: fix warnings.
|
||||||
|
|
||||||
## 2.2.0-dev.0
|
## 2.2.0-dev.0
|
||||||
|
|
||||||
- **FEAT**: Add async dependency resolution and enhance example.
|
- **FEAT**: Add async dependency resolution and enhance example.
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
|
|
||||||
class AppModule extends Module {
|
class AppModule extends Module {
|
||||||
@@ -95,21 +94,19 @@ class NetworkDataRepository implements DataRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class ApiClient {
|
abstract class ApiClient {
|
||||||
Future sendRequest({@required String url, String token, Map requestBody});
|
Future sendRequest({String url, String token, Map requestBody});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiClientMock implements ApiClient {
|
class ApiClientMock implements ApiClient {
|
||||||
@override
|
@override
|
||||||
Future sendRequest(
|
Future sendRequest({String? url, String? token, Map? requestBody}) async {
|
||||||
{@required String? url, String? token, Map? requestBody}) async {
|
|
||||||
return 'Local Data';
|
return 'Local Data';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiClientImpl implements ApiClient {
|
class ApiClientImpl implements ApiClient {
|
||||||
@override
|
@override
|
||||||
Future sendRequest(
|
Future sendRequest({String? url, String? token, Map? requestBody}) async {
|
||||||
{@required String? url, String? token, Map? requestBody}) async {
|
|
||||||
return 'Network data';
|
return 'Network data';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: cherrypick
|
name: cherrypick
|
||||||
description: Cherrypick is a small dependency injection (DI) library for dart/flutter projects.
|
description: Cherrypick is a small dependency injection (DI) library for dart/flutter projects.
|
||||||
version: 2.2.0-dev.0
|
version: 2.2.0-dev.1
|
||||||
homepage: https://pese-git.github.io/cherrypick-site/
|
homepage: https://pese-git.github.io/cherrypick-site/
|
||||||
documentation: https://github.com/pese-git/cherrypick/wiki
|
documentation: https://github.com/pese-git/cherrypick/wiki
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.1.0-dev.1
|
||||||
|
|
||||||
|
- **FEAT**: implement InjectGenerator.
|
||||||
|
|
||||||
## 1.1.0-dev.0
|
## 1.1.0-dev.0
|
||||||
|
|
||||||
- **FEAT**: implement generator for dynamic params.
|
- **FEAT**: implement generator for dynamic params.
|
||||||
|
|||||||
@@ -19,3 +19,6 @@ export 'src/instance.dart';
|
|||||||
export 'src/singleton.dart';
|
export 'src/singleton.dart';
|
||||||
export 'src/named.dart';
|
export 'src/named.dart';
|
||||||
export 'src/params.dart';
|
export 'src/params.dart';
|
||||||
|
export 'src/inject.dart';
|
||||||
|
export 'src/injectable.dart';
|
||||||
|
export 'src/scope.dart';
|
||||||
|
|||||||
20
cherrypick_annotations/lib/src/inject.dart
Normal file
20
cherrypick_annotations/lib/src/inject.dart
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
// http://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:meta/meta.dart';
|
||||||
|
|
||||||
|
@experimental
|
||||||
|
// ignore: camel_case_types
|
||||||
|
final class inject {
|
||||||
|
const inject();
|
||||||
|
}
|
||||||
20
cherrypick_annotations/lib/src/injectable.dart
Normal file
20
cherrypick_annotations/lib/src/injectable.dart
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
// http://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:meta/meta.dart';
|
||||||
|
|
||||||
|
@experimental
|
||||||
|
// ignore: camel_case_types
|
||||||
|
final class injectable {
|
||||||
|
const injectable();
|
||||||
|
}
|
||||||
@@ -11,11 +11,12 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// An annotation to specify that a method or class provides a new instance
|
/// ENGLISH:
|
||||||
/// each time it is requested.
|
/// Annotation to specify that a new instance should be provided on each request.
|
||||||
///
|
///
|
||||||
/// This is typically used to indicate that the annotated binding should
|
/// Use the `@instance()` annotation for methods or classes in your DI module
|
||||||
/// not be a singleton and a new object is created for every injection.
|
/// to declare that the DI container must create a new object every time
|
||||||
|
/// the dependency is injected (i.e., no singleton behavior).
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
@@ -35,6 +36,32 @@
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// RUSSIAN (Русский):
|
||||||
|
/// Аннотация для создания нового экземпляра при каждом запросе.
|
||||||
|
///
|
||||||
|
/// Используйте `@instance()` для методов или классов в DI-модуле,
|
||||||
|
/// чтобы указать, что контейнер внедрения зависимостей должен создавать
|
||||||
|
/// новый объект при каждом обращении к зависимости (то есть, не синглтон).
|
||||||
|
///
|
||||||
|
/// Пример:
|
||||||
|
/// ```dart
|
||||||
|
/// @module()
|
||||||
|
/// abstract class AppModule extends Module {
|
||||||
|
/// @instance()
|
||||||
|
/// Foo foo() => Foo();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Будет сгенерирован следующий код:
|
||||||
|
/// ```dart
|
||||||
|
/// final class $AppModule extends AppModule {
|
||||||
|
/// @override
|
||||||
|
/// void builder(Scope currentScope) {
|
||||||
|
/// bind<Foo>().toInstance(() => foo());
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
// ignore: camel_case_types
|
// ignore: camel_case_types
|
||||||
final class instance {
|
final class instance {
|
||||||
const instance();
|
const instance();
|
||||||
|
|||||||
@@ -11,25 +11,57 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// An annotation used to mark a Dart class or library as a module.
|
/// ENGLISH:
|
||||||
|
/// Annotation for marking Dart classes or libraries as modules.
|
||||||
///
|
///
|
||||||
/// This annotation can be used for tooling, code generation,
|
/// Use the `@module()` annotation on abstract classes (or on a library)
|
||||||
/// or to provide additional metadata about the module.
|
/// to indicate that the class represents a DI (Dependency Injection) module.
|
||||||
|
/// This is commonly used in code generation tools to automatically register
|
||||||
|
/// and configure dependencies defined within the module.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// @module()
|
/// @module()
|
||||||
/// abstract class AppModule extends Module {
|
/// abstract class AppModule extends Module {
|
||||||
|
/// // Dependency definitions go here.
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// Сгенерирует код:
|
///
|
||||||
|
/// Generates code like:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final class $AppModule extends AppModule {
|
/// final class $AppModule extends AppModule {
|
||||||
/// @override
|
/// @override
|
||||||
/// void builder(Scope currentScope) {
|
/// void builder(Scope currentScope) {
|
||||||
///
|
/// // Dependency registration...
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// RUSSIAN (Русский):
|
||||||
|
/// Аннотация для пометки классов или библиотек Dart как модуля.
|
||||||
|
///
|
||||||
|
/// Используйте `@module()` для абстрактных классов (или библиотек), чтобы
|
||||||
|
/// показать, что класс реализует DI-модуль (Dependency Injection).
|
||||||
|
/// Обычно используется генераторами кода для автоматической регистрации
|
||||||
|
/// и конфигурирования зависимостей, определённых в модуле.
|
||||||
|
///
|
||||||
|
/// Пример:
|
||||||
|
/// ```dart
|
||||||
|
/// @module()
|
||||||
|
/// abstract class AppModule extends Module {
|
||||||
|
/// // Определения зависимостей
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Будет сгенерирован код:
|
||||||
|
/// ```dart
|
||||||
|
/// final class $AppModule extends AppModule {
|
||||||
|
/// @override
|
||||||
|
/// void builder(Scope currentScope) {
|
||||||
|
/// // Регистрация зависимостей...
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
// ignore: camel_case_types
|
// ignore: camel_case_types
|
||||||
final class module {
|
final class module {
|
||||||
/// Creates a [module] annotation.
|
/// Creates a [module] annotation.
|
||||||
|
|||||||
@@ -11,10 +11,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// An annotation to assign a name or identifier to a class, method, or other element.
|
/// ENGLISH:
|
||||||
|
/// Annotation to assign a name or identifier to a class, method, or other element.
|
||||||
///
|
///
|
||||||
/// This can be useful for code generation, dependency injection,
|
/// The `@named('value')` annotation allows you to specify a string name
|
||||||
/// or providing metadata within a framework.
|
/// for a dependency, factory, or injectable. This is useful for distinguishing
|
||||||
|
/// between multiple registrations of the same type in dependency injection,
|
||||||
|
/// code generation, and for providing human-readable metadata.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
@@ -25,7 +28,33 @@
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Сгенерирует код:
|
/// This will generate:
|
||||||
|
/// ```dart
|
||||||
|
/// final class $AppModule extends AppModule {
|
||||||
|
/// @override
|
||||||
|
/// void builder(Scope currentScope) {
|
||||||
|
/// bind<Dio>().toProvide(() => dio()).withName('dio').singleton();
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// RUSSIAN (Русский):
|
||||||
|
/// Аннотация для задания имени или идентификатора классу, методу или другому элементу.
|
||||||
|
///
|
||||||
|
/// Аннотация `@named('значение')` позволяет указать строковое имя для зависимости,
|
||||||
|
/// фабрики или внедряемого значения. Это удобно для различения нескольких
|
||||||
|
/// регистраций одного типа в DI, генерации кода.
|
||||||
|
///
|
||||||
|
/// Пример:
|
||||||
|
/// ```dart
|
||||||
|
/// @module()
|
||||||
|
/// abstract class AppModule extends Module {
|
||||||
|
/// @named('dio')
|
||||||
|
/// Dio dio() => Dio();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Будет сгенерирован следующий код:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final class $AppModule extends AppModule {
|
/// final class $AppModule extends AppModule {
|
||||||
/// @override
|
/// @override
|
||||||
@@ -36,9 +65,13 @@
|
|||||||
/// ```
|
/// ```
|
||||||
// ignore: camel_case_types
|
// ignore: camel_case_types
|
||||||
final class named {
|
final class named {
|
||||||
/// The assigned name or identifier.
|
/// EN: The assigned name or identifier for the element.
|
||||||
|
///
|
||||||
|
/// RU: Назначенное имя или идентификатор для элемента.
|
||||||
final String value;
|
final String value;
|
||||||
|
|
||||||
/// Creates a [named] annotation with the given [value].
|
/// EN: Creates a [named] annotation with the given [value].
|
||||||
|
///
|
||||||
|
/// RU: Создаёт аннотацию [named] с заданным значением [value].
|
||||||
const named(this.value);
|
const named(this.value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,14 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// An annotation to indicate that a parameter is to be injected with run-time provided arguments.
|
/// ENGLISH:
|
||||||
|
/// Annotation to mark a method parameter for injection with run-time arguments.
|
||||||
///
|
///
|
||||||
/// Use this annotation to mark a method parameter that should receive arguments
|
/// Use the `@params()` annotation to specify that a particular parameter of a
|
||||||
/// passed during the resolution of a dependency (for example, through the
|
/// provider method should be assigned a value supplied at resolution time,
|
||||||
/// `.withParams(...)` method in the generated code).
|
/// rather than during static dependency graph creation. This is useful in DI
|
||||||
|
/// when a dependency must receive dynamic data passed by the consumer
|
||||||
|
/// (via `.withParams(...)` in the generated code).
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
@@ -27,6 +30,26 @@
|
|||||||
/// ```dart
|
/// ```dart
|
||||||
/// bind<String>().toProvideWithParams((args) => greet(args));
|
/// bind<String>().toProvideWithParams((args) => greet(args));
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// RUSSIAN (Русский):
|
||||||
|
/// Аннотация для пометки параметра метода, который будет внедряться со значением во время выполнения.
|
||||||
|
///
|
||||||
|
/// Используйте `@params()` чтобы указать, что конкретный параметр метода-провайдера
|
||||||
|
/// должен получать значение, передаваемое в момент обращения к зависимости,
|
||||||
|
/// а не на этапе построения графа зависимостей. Это полезно, если зависимость
|
||||||
|
/// должна получать данные динамически от пользователя или другого процесса
|
||||||
|
/// через `.withParams(...)` в сгенерированном коде.
|
||||||
|
///
|
||||||
|
/// Пример:
|
||||||
|
/// ```dart
|
||||||
|
/// @provide()
|
||||||
|
/// String greet(@params() dynamic params) => 'Hello $params';
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Будет сгенерировано:
|
||||||
|
/// ```dart
|
||||||
|
/// bind<String>().toProvideWithParams((args) => greet(args));
|
||||||
|
/// ```
|
||||||
// ignore: camel_case_types
|
// ignore: camel_case_types
|
||||||
final class params {
|
final class params {
|
||||||
const params();
|
const params();
|
||||||
|
|||||||
@@ -11,28 +11,56 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// An annotation to indicate that a method provides a dependency to the module.
|
/// ENGLISH:
|
||||||
|
/// Annotation to declare a factory/provider method or class as a singleton.
|
||||||
///
|
///
|
||||||
/// This annotation is typically used in conjunction with dependency injection,
|
/// Use the `@singleton()` annotation on methods in your DI module to specify
|
||||||
/// marking methods whose return value should be registered as a provider.
|
/// that only one instance of the resulting object should be created and shared
|
||||||
/// The annotated method can optionally declare dependencies as parameters,
|
/// for all consumers. This is especially useful in dependency injection
|
||||||
/// which will be resolved and injected automatically.
|
/// frameworks and service locators.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// @module()
|
/// @module()
|
||||||
/// abstract class AppModule extends Module {
|
/// abstract class AppModule extends Module {
|
||||||
/// @provide()
|
/// @singleton()
|
||||||
/// Foo foo(Bar bar) => Foo(bar);
|
/// Dio dio() => Dio();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This will generate:
|
/// This generates the following code:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final class $AppModule extends AppModule {
|
/// final class $AppModule extends AppModule {
|
||||||
/// @override
|
/// @override
|
||||||
/// void builder(Scope currentScope) {
|
/// void builder(Scope currentScope) {
|
||||||
/// bind<Foo>().toProvide(() => foo(currentScope.resolve<Bar>()));
|
/// bind<Dio>().toProvide(() => dio()).singleton();
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// RUSSIAN (Русский):
|
||||||
|
/// Аннотация для объявления фабричного/провайдерного метода или класса синглтоном.
|
||||||
|
///
|
||||||
|
/// Используйте `@singleton()` для методов внутри DI-модуля, чтобы указать,
|
||||||
|
/// что соответствующий объект (экземпляр класса) должен быть создан только один раз
|
||||||
|
/// и использоваться всеми компонентами приложения (единый общий экземпляр).
|
||||||
|
/// Это характерно для систем внедрения зависимостей и сервис-локаторов.
|
||||||
|
///
|
||||||
|
/// Пример:
|
||||||
|
/// ```dart
|
||||||
|
/// @module()
|
||||||
|
/// abstract class AppModule extends Module {
|
||||||
|
/// @singleton()
|
||||||
|
/// Dio dio() => Dio();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Будет сгенерирован следующий код:
|
||||||
|
/// ```dart
|
||||||
|
/// final class $AppModule extends AppModule {
|
||||||
|
/// @override
|
||||||
|
/// void builder(Scope currentScope) {
|
||||||
|
/// bind<Dio>().toProvide(() => dio()).singleton();
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|||||||
21
cherrypick_annotations/lib/src/scope.dart
Normal file
21
cherrypick_annotations/lib/src/scope.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
// http://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:meta/meta.dart';
|
||||||
|
|
||||||
|
@experimental
|
||||||
|
// ignore: camel_case_types
|
||||||
|
final class scope {
|
||||||
|
final String? name;
|
||||||
|
const scope(this.name);
|
||||||
|
}
|
||||||
@@ -11,11 +11,14 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// An annotation to declare a class as a singleton.
|
/// ENGLISH:
|
||||||
|
/// Annotation to declare a dependency as a singleton.
|
||||||
///
|
///
|
||||||
/// This can be used to indicate that only one instance of the class
|
/// Use the `@singleton()` annotation on provider methods inside a module
|
||||||
/// should be created, which is often useful in dependency injection
|
/// to indicate that only a single instance of this dependency should be
|
||||||
/// frameworks or service locators.
|
/// created and shared throughout the application's lifecycle. This is
|
||||||
|
/// typically used in dependency injection frameworks or service locators
|
||||||
|
/// to guarantee a single shared instance.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
@@ -25,7 +28,36 @@
|
|||||||
/// Dio dio() => Dio();
|
/// Dio dio() => Dio();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// Сгенерирует код:
|
///
|
||||||
|
/// This will generate code like:
|
||||||
|
/// ```dart
|
||||||
|
/// final class $AppModule extends AppModule {
|
||||||
|
/// @override
|
||||||
|
/// void builder(Scope currentScope) {
|
||||||
|
/// bind<Dio>().toProvide(() => dio()).singleton();
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// RUSSIAN (Русский):
|
||||||
|
/// Аннотация для объявления зависимости как синглтона.
|
||||||
|
///
|
||||||
|
/// Используйте `@singleton()` для методов-провайдеров внутри модуля,
|
||||||
|
/// чтобы указать, что соответствующий объект должен быть создан
|
||||||
|
/// единожды и использоваться во всём приложении (общий синглтон).
|
||||||
|
/// Это характерно для систем внедрения зависимостей и сервис-локаторов,
|
||||||
|
/// чтобы гарантировать один общий экземпляр.
|
||||||
|
///
|
||||||
|
/// Пример:
|
||||||
|
/// ```dart
|
||||||
|
/// @module()
|
||||||
|
/// abstract class AppModule extends Module {
|
||||||
|
/// @singleton()
|
||||||
|
/// Dio dio() => Dio();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Будет сгенерирован следующий код:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final class $AppModule extends AppModule {
|
/// final class $AppModule extends AppModule {
|
||||||
/// @override
|
/// @override
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
name: cherrypick_annotations
|
name: cherrypick_annotations
|
||||||
description: A starting point for Dart libraries or applications.
|
description: |
|
||||||
version: 1.1.0-dev.0
|
Set of annotations for CherryPick dependency injection library. Enables code generation and declarative DI for Dart & Flutter projects.
|
||||||
|
version: 1.1.0-dev.1
|
||||||
documentation: https://github.com/pese-git/cherrypick/wiki
|
documentation: https://github.com/pese-git/cherrypick/wiki
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick/cherrypick_annotations
|
||||||
issue_tracker: https://github.com/pese-git/cherrypick/issues
|
issue_tracker: https://github.com/pese-git/cherrypick/issues
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.1.2-dev.1
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
## 1.1.2-dev.0
|
## 1.1.2-dev.0
|
||||||
|
|
||||||
- **FIX**: fix warning.
|
- **FIX**: fix warning.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: cherrypick_flutter
|
name: cherrypick_flutter
|
||||||
description: "Flutter library that allows access to the root scope through the context using `CherryPickProvider`."
|
description: "Flutter library that allows access to the root scope through the context using `CherryPickProvider`."
|
||||||
version: 1.1.2-dev.0
|
version: 1.1.2-dev.1
|
||||||
homepage: https://pese-git.github.io/cherrypick-site/
|
homepage: https://pese-git.github.io/cherrypick-site/
|
||||||
documentation: https://github.com/pese-git/cherrypick/wiki
|
documentation: https://github.com/pese-git/cherrypick/wiki
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
@@ -13,7 +13,7 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cherrypick: ^2.2.0-dev.0
|
cherrypick: ^2.2.0-dev.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
## 1.1.0-dev.3
|
||||||
|
|
||||||
|
- **FEAT**: implement InjectGenerator.
|
||||||
|
|
||||||
|
## 1.1.0-dev.2
|
||||||
|
|
||||||
|
- **FIX**: update instance generator code.
|
||||||
|
|
||||||
|
## 1.1.0-dev.1
|
||||||
|
|
||||||
|
- **FIX**: optimize code.
|
||||||
|
|
||||||
## 1.1.0-dev.0
|
## 1.1.0-dev.0
|
||||||
|
|
||||||
- **FIX**: fix warning conflict with names.
|
- **FIX**: fix warning conflict with names.
|
||||||
|
|||||||
@@ -7,10 +7,21 @@ builders:
|
|||||||
required_inputs: ["lib/**"]
|
required_inputs: ["lib/**"]
|
||||||
runs_before: []
|
runs_before: []
|
||||||
build_to: source
|
build_to: source
|
||||||
|
inject_generator:
|
||||||
|
import: "package:cherrypick_generator/inject_generator.dart"
|
||||||
|
builder_factories: ["injectBuilder"]
|
||||||
|
build_extensions: {".dart": [".cherrypick.g.dart"]}
|
||||||
|
auto_apply: dependents
|
||||||
|
required_inputs: ["lib/**"]
|
||||||
|
runs_before: []
|
||||||
|
build_to: source
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
$default:
|
$default:
|
||||||
builders:
|
builders:
|
||||||
cherrypick_generator|module_generator:
|
cherrypick_generator|module_generator:
|
||||||
|
generate_for:
|
||||||
|
- lib/**.dart
|
||||||
|
cherrypick_generator|inject_generator:
|
||||||
generate_for:
|
generate_for:
|
||||||
- lib/**.dart
|
- lib/**.dart
|
||||||
@@ -14,3 +14,4 @@ library;
|
|||||||
//
|
//
|
||||||
|
|
||||||
export 'module_generator.dart';
|
export 'module_generator.dart';
|
||||||
|
export 'inject_generator.dart';
|
||||||
|
|||||||
186
cherrypick_generator/lib/inject_generator.dart
Normal file
186
cherrypick_generator/lib/inject_generator.dart
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
// http://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 'dart:async';
|
||||||
|
import 'package:analyzer/dart/constant/value.dart';
|
||||||
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
|
import 'package:build/build.dart';
|
||||||
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann;
|
||||||
|
|
||||||
|
/// InjectGenerator generates a mixin for a class marked with @injectable()
|
||||||
|
/// and injects all fields annotated with @inject(), using CherryPick DI.
|
||||||
|
///
|
||||||
|
/// For Future<T> fields it calls .resolveAsync<T>(),
|
||||||
|
/// otherwise .resolve<T>() is used. Scope and named qualifiers are supported.
|
||||||
|
///
|
||||||
|
/// ---
|
||||||
|
///
|
||||||
|
/// InjectGenerator генерирует миксин для класса с аннотацией @injectable()
|
||||||
|
/// и внедряет все поля, помеченные @inject(), используя DI-фреймворк CherryPick.
|
||||||
|
///
|
||||||
|
/// Для Future<T> полей вызывается .resolveAsync<T>(),
|
||||||
|
/// для остальных — .resolve<T>(). Поддерживаются scope и named qualifier.
|
||||||
|
///
|
||||||
|
class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||||
|
const InjectGenerator();
|
||||||
|
|
||||||
|
/// The main entry point for code generation.
|
||||||
|
///
|
||||||
|
/// Checks class validity, collects injectable fields, and produces injection code.
|
||||||
|
///
|
||||||
|
/// Основная точка входа генератора. Проверяет класс, собирает инъектируемые поля и создает код внедрения зависимостей.
|
||||||
|
@override
|
||||||
|
FutureOr<String> generateForAnnotatedElement(
|
||||||
|
Element element,
|
||||||
|
ConstantReader annotation,
|
||||||
|
BuildStep buildStep,
|
||||||
|
) {
|
||||||
|
if (element is! ClassElement) {
|
||||||
|
throw InvalidGenerationSourceError(
|
||||||
|
'@injectable() can only be applied to classes.',
|
||||||
|
element: element,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final classElement = element;
|
||||||
|
final className = classElement.name;
|
||||||
|
final mixinName = '_\$$className';
|
||||||
|
|
||||||
|
final buffer = StringBuffer()
|
||||||
|
..writeln('mixin $mixinName {')
|
||||||
|
..writeln(' void _inject($className instance) {');
|
||||||
|
|
||||||
|
// Collect and process all @inject fields.
|
||||||
|
// Собираем и обрабатываем все поля с @inject.
|
||||||
|
final injectFields =
|
||||||
|
classElement.fields.where(_isInjectField).map(_parseInjectField);
|
||||||
|
|
||||||
|
for (final parsedField in injectFields) {
|
||||||
|
buffer.writeln(_generateInjectionLine(parsedField));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer
|
||||||
|
..writeln(' }')
|
||||||
|
..writeln('}');
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if a field has the @inject annotation.
|
||||||
|
///
|
||||||
|
/// Проверяет, отмечено ли поле аннотацией @inject.
|
||||||
|
static bool _isInjectField(FieldElement field) {
|
||||||
|
return field.metadata.any(
|
||||||
|
(m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses the field for scope/named qualifiers and determines its type.
|
||||||
|
/// Returns a [_ParsedInjectField] describing injection information.
|
||||||
|
///
|
||||||
|
/// Разбирает поле на наличие модификаторов scope/named и выясняет его тип.
|
||||||
|
/// Возвращает [_ParsedInjectField] с информацией о внедрении.
|
||||||
|
static _ParsedInjectField _parseInjectField(FieldElement field) {
|
||||||
|
String? scopeName;
|
||||||
|
String? namedValue;
|
||||||
|
|
||||||
|
for (final meta in field.metadata) {
|
||||||
|
final DartObject? obj = meta.computeConstantValue();
|
||||||
|
final type = obj?.type?.getDisplayString();
|
||||||
|
if (type == 'scope') {
|
||||||
|
scopeName = obj?.getField('name')?.toStringValue();
|
||||||
|
} else if (type == 'named') {
|
||||||
|
namedValue = obj?.getField('value')?.toStringValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final DartType dartType = field.type;
|
||||||
|
String coreTypeName;
|
||||||
|
bool isFuture;
|
||||||
|
|
||||||
|
if (dartType.isDartAsyncFuture) {
|
||||||
|
final ParameterizedType paramType = dartType as ParameterizedType;
|
||||||
|
coreTypeName = paramType.typeArguments.first.getDisplayString();
|
||||||
|
isFuture = true;
|
||||||
|
} else {
|
||||||
|
coreTypeName = dartType.getDisplayString();
|
||||||
|
isFuture = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ParsedInjectField(
|
||||||
|
fieldName: field.name,
|
||||||
|
coreType: coreTypeName,
|
||||||
|
isFuture: isFuture,
|
||||||
|
scopeName: scopeName,
|
||||||
|
namedValue: namedValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a line of code that performs the dependency injection for a field.
|
||||||
|
/// Handles resolve/resolveAsync, scoping, and named qualifiers.
|
||||||
|
///
|
||||||
|
/// Генерирует строку кода, которая внедряет зависимость для поля.
|
||||||
|
/// Учитывает resolve/resolveAsync, scoping и named qualifier.
|
||||||
|
String _generateInjectionLine(_ParsedInjectField field) {
|
||||||
|
final methodName = field.isFuture
|
||||||
|
? 'resolveAsync<${field.coreType}>'
|
||||||
|
: 'resolve<${field.coreType}>';
|
||||||
|
final openCall = (field.scopeName != null && field.scopeName!.isNotEmpty)
|
||||||
|
? "CherryPick.openScope(scopeName: '${field.scopeName}')"
|
||||||
|
: "CherryPick.openRootScope()";
|
||||||
|
final params = (field.namedValue != null && field.namedValue!.isNotEmpty)
|
||||||
|
? "(named: '${field.namedValue}')"
|
||||||
|
: '()';
|
||||||
|
|
||||||
|
return " instance.${field.fieldName} = $openCall.$methodName$params;";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Data structure representing all information required to generate
|
||||||
|
/// injection code for a field.
|
||||||
|
///
|
||||||
|
/// Структура данных, содержащая всю информацию,
|
||||||
|
/// необходимую для генерации кода внедрения для поля.
|
||||||
|
class _ParsedInjectField {
|
||||||
|
/// The name of the field / Имя поля.
|
||||||
|
final String fieldName;
|
||||||
|
|
||||||
|
/// The base type name (T or Future<T>) / Базовый тип (T или тип из Future<T>).
|
||||||
|
final String coreType;
|
||||||
|
|
||||||
|
/// True if the field type is Future<T>; false otherwise
|
||||||
|
/// Истина, если поле — Future<T>, иначе — ложь.
|
||||||
|
final bool isFuture;
|
||||||
|
|
||||||
|
/// Optional scope annotation argument / Опциональное имя scope.
|
||||||
|
final String? scopeName;
|
||||||
|
|
||||||
|
/// Optional named annotation argument / Опциональное имя named.
|
||||||
|
final String? namedValue;
|
||||||
|
|
||||||
|
_ParsedInjectField({
|
||||||
|
required this.fieldName,
|
||||||
|
required this.coreType,
|
||||||
|
required this.isFuture,
|
||||||
|
this.scopeName,
|
||||||
|
this.namedValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder factory. Used by build_runner.
|
||||||
|
///
|
||||||
|
/// Фабрика билдера. Используется build_runner.
|
||||||
|
Builder injectBuilder(BuilderOptions options) =>
|
||||||
|
PartBuilder([InjectGenerator()], '.inject.cherrypick.g.dart');
|
||||||
@@ -90,4 +90,4 @@ class ModuleGenerator extends GeneratorForAnnotation<ann.module> {
|
|||||||
/// файлов, где встречается @module().
|
/// файлов, где встречается @module().
|
||||||
/// ---------------------------------------------------------------------------
|
/// ---------------------------------------------------------------------------
|
||||||
Builder moduleBuilder(BuilderOptions options) =>
|
Builder moduleBuilder(BuilderOptions options) =>
|
||||||
PartBuilder([ModuleGenerator()], '.cherrypick.g.dart');
|
PartBuilder([ModuleGenerator()], '.module.cherrypick.g.dart');
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ import 'package:source_gen/source_gen.dart';
|
|||||||
import 'bind_parameters_spec.dart';
|
import 'bind_parameters_spec.dart';
|
||||||
import 'metadata_utils.dart';
|
import 'metadata_utils.dart';
|
||||||
|
|
||||||
|
enum BindingType {
|
||||||
|
instance,
|
||||||
|
provide;
|
||||||
|
}
|
||||||
|
|
||||||
/// ---------------------------------------------------------------------------
|
/// ---------------------------------------------------------------------------
|
||||||
/// BindSpec -- describes a binding specification generated for a dependency.
|
/// BindSpec -- describes a binding specification generated for a dependency.
|
||||||
///
|
///
|
||||||
@@ -59,7 +64,7 @@ class BindSpec {
|
|||||||
final List<BindParameterSpec> parameters;
|
final List<BindParameterSpec> parameters;
|
||||||
|
|
||||||
/// Binding type: 'instance' or 'provide' (@instance or @provide)
|
/// Binding type: 'instance' or 'provide' (@instance or @provide)
|
||||||
final String bindingType; // 'instance' | 'provide'
|
final BindingType bindingType; // 'instance' | 'provide'
|
||||||
|
|
||||||
/// True if the method is asynchronous and uses instance binding (Future)
|
/// True if the method is asynchronous and uses instance binding (Future)
|
||||||
final bool isAsyncInstance;
|
final bool isAsyncInstance;
|
||||||
@@ -116,16 +121,16 @@ class BindSpec {
|
|||||||
String _generateWithParamsProvideClause(int indent) {
|
String _generateWithParamsProvideClause(int indent) {
|
||||||
// Safe variable name for parameters.
|
// Safe variable name for parameters.
|
||||||
const paramVar = 'args';
|
const paramVar = 'args';
|
||||||
final fnArgs = parameters
|
final fnArgs = parameters.map((p) => p.generateArg(paramVar)).join(', ');
|
||||||
.map((p) => p.isParams ? paramVar : p.generateArg(paramVar))
|
|
||||||
.join(', ');
|
|
||||||
final multiLine = fnArgs.length > 60 || fnArgs.contains('\n');
|
final multiLine = fnArgs.length > 60 || fnArgs.contains('\n');
|
||||||
switch (bindingType) {
|
switch (bindingType) {
|
||||||
case 'instance':
|
case BindingType.instance:
|
||||||
return isAsyncInstance
|
throw StateError(
|
||||||
? '.toInstanceAsync(($fnArgs) => $methodName($fnArgs))'
|
'Internal error: _generateWithParamsProvideClause called for @instance binding with @params.');
|
||||||
: '.toInstance(($fnArgs) => $methodName($fnArgs))';
|
//return isAsyncInstance
|
||||||
case 'provide':
|
// ? '.toInstanceAsync(($fnArgs) => $methodName($fnArgs))'
|
||||||
|
// : '.toInstance(($fnArgs) => $methodName($fnArgs))';
|
||||||
|
case BindingType.provide:
|
||||||
default:
|
default:
|
||||||
if (isAsyncProvide) {
|
if (isAsyncProvide) {
|
||||||
return multiLine
|
return multiLine
|
||||||
@@ -144,11 +149,11 @@ class BindSpec {
|
|||||||
final argsStr = parameters.map((p) => p.generateArg()).join(', ');
|
final argsStr = parameters.map((p) => p.generateArg()).join(', ');
|
||||||
final multiLine = argsStr.length > 60 || argsStr.contains('\n');
|
final multiLine = argsStr.length > 60 || argsStr.contains('\n');
|
||||||
switch (bindingType) {
|
switch (bindingType) {
|
||||||
case 'instance':
|
case BindingType.instance:
|
||||||
return isAsyncInstance
|
return isAsyncInstance
|
||||||
? '.toInstanceAsync($methodName($argsStr))'
|
? '.toInstanceAsync($methodName($argsStr))'
|
||||||
: '.toInstance($methodName($argsStr))';
|
: '.toInstance($methodName($argsStr))';
|
||||||
case 'provide':
|
case BindingType.provide:
|
||||||
default:
|
default:
|
||||||
if (isAsyncProvide) {
|
if (isAsyncProvide) {
|
||||||
return multiLine
|
return multiLine
|
||||||
@@ -212,7 +217,17 @@ class BindSpec {
|
|||||||
element: method,
|
element: method,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final bindingType = hasInstance ? 'instance' : 'provide';
|
final bindingType =
|
||||||
|
hasInstance ? BindingType.instance : BindingType.provide;
|
||||||
|
|
||||||
|
// PROHIBIT @params with @instance bindings!
|
||||||
|
if (bindingType == BindingType.instance && hasParams) {
|
||||||
|
throw InvalidGenerationSourceError(
|
||||||
|
'@params() (runtime arguments) cannot be used together with @instance() on method $methodName. '
|
||||||
|
'Use @provide() instead if you want runtime arguments.',
|
||||||
|
element: method,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// -- Extract inner type for Future<T> and set async flags.
|
// -- Extract inner type for Future<T> and set async flags.
|
||||||
bool isAsyncInstance = false;
|
bool isAsyncInstance = false;
|
||||||
@@ -220,8 +235,8 @@ class BindSpec {
|
|||||||
final futureInnerType = _extractFutureInnerType(returnType);
|
final futureInnerType = _extractFutureInnerType(returnType);
|
||||||
if (futureInnerType != null) {
|
if (futureInnerType != null) {
|
||||||
returnType = futureInnerType;
|
returnType = futureInnerType;
|
||||||
if (bindingType == 'instance') isAsyncInstance = true;
|
if (bindingType == BindingType.instance) isAsyncInstance = true;
|
||||||
if (bindingType == 'provide') isAsyncProvide = true;
|
if (bindingType == BindingType.provide) isAsyncProvide = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BindSpec(
|
return BindSpec(
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
name: cherrypick_generator
|
name: cherrypick_generator
|
||||||
description: Code generator for cherrypick annotations
|
description: |
|
||||||
version: 1.1.0-dev.0
|
Source code generator for the cherrypick dependency injection system. Processes annotations to generate binding and module code for Dart & Flutter projects.
|
||||||
|
|
||||||
|
version: 1.1.0-dev.3
|
||||||
documentation: https://github.com/pese-git/cherrypick/wiki
|
documentation: https://github.com/pese-git/cherrypick/wiki
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick/cherrypick_generator
|
||||||
issue_tracker: https://github.com/pese-git/cherrypick/issues
|
issue_tracker: https://github.com/pese-git/cherrypick/issues
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
@@ -10,14 +12,15 @@ environment:
|
|||||||
|
|
||||||
# Add regular dependencies here.
|
# Add regular dependencies here.
|
||||||
dependencies:
|
dependencies:
|
||||||
cherrypick_annotations: ^1.1.0-dev.0
|
cherrypick_annotations: ^1.1.0-dev.1
|
||||||
analyzer: any
|
analyzer: ^6.7.0
|
||||||
dart_style: any
|
dart_style: ^2.3.7
|
||||||
build: any
|
build: ^2.4.1
|
||||||
build_runner: any
|
build_runner: ^2.4.13
|
||||||
source_gen: any
|
source_gen: ^1.5.0
|
||||||
|
collection: ^1.18.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^5.0.0
|
lints: ^5.0.0
|
||||||
mockito: any
|
mockito: ^5.4.4
|
||||||
test: ^1.25.8
|
test: ^1.25.8
|
||||||
|
|||||||
@@ -132,28 +132,28 @@ packages:
|
|||||||
path: "../../cherrypick"
|
path: "../../cherrypick"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "2.1.0"
|
version: "2.2.0-dev.1"
|
||||||
cherrypick_annotations:
|
cherrypick_annotations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "../../cherrypick_annotations"
|
path: "../../cherrypick_annotations"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.0"
|
version: "1.1.0-dev.0"
|
||||||
cherrypick_flutter:
|
cherrypick_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "../../cherrypick_flutter"
|
path: "../../cherrypick_flutter"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.1.1"
|
version: "1.1.2-dev.1"
|
||||||
cherrypick_generator:
|
cherrypick_generator:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
path: "../../cherrypick_generator"
|
path: "../../cherrypick_generator"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.0"
|
version: "1.1.0-dev.2"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -243,10 +243,10 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
|
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "5.0.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -344,10 +344,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
|
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "5.0.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cherrypick: ^2.2.0-dev.0
|
cherrypick: ^2.2.0-dev.1
|
||||||
cherrypick_flutter: ^1.1.2-dev.0
|
cherrypick_flutter: ^1.1.2-dev.1
|
||||||
|
|
||||||
cherrypick_annotations: ^1.1.0-dev.0
|
cherrypick_annotations: ^1.1.0-dev.1
|
||||||
|
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
|
|
||||||
@@ -22,10 +22,10 @@ dev_dependencies:
|
|||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
flutter_lints: ^4.0.0
|
flutter_lints: ^5.0.0
|
||||||
|
|
||||||
cherrypick_generator: ^1.1.0-dev.0
|
cherrypick_generator: ^1.1.0-dev.3
|
||||||
build_runner: any
|
build_runner: ^2.4.13
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|||||||
35
examples/postly/lib/app.dart
Normal file
35
examples/postly/lib/app.dart
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import 'domain/repository/post_repository.dart';
|
||||||
|
import 'presentation/bloc/post_bloc.dart';
|
||||||
|
import 'router/app_router.dart';
|
||||||
|
|
||||||
|
part 'app.inject.cherrypick.g.dart';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
class MyApp extends StatelessWidget with _$MyApp {
|
||||||
|
final _appRouter = AppRouter();
|
||||||
|
|
||||||
|
@named('repo')
|
||||||
|
@inject()
|
||||||
|
late final PostRepository repository;
|
||||||
|
|
||||||
|
MyApp({super.key}) {
|
||||||
|
_inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (_) => PostBloc(repository),
|
||||||
|
child: MaterialApp.router(
|
||||||
|
routeInformationParser: _appRouter.defaultRouteParser(),
|
||||||
|
routerDelegate: _appRouter.delegate(),
|
||||||
|
theme: ThemeData.light(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import '../data/network/json_placeholder_api.dart';
|
|||||||
import '../data/post_repository_impl.dart';
|
import '../data/post_repository_impl.dart';
|
||||||
import '../domain/repository/post_repository.dart';
|
import '../domain/repository/post_repository.dart';
|
||||||
|
|
||||||
part 'app_module.cherrypick.g.dart';
|
part 'app_module.module.cherrypick.g.dart';
|
||||||
|
|
||||||
@module()
|
@module()
|
||||||
abstract class AppModule extends Module {
|
abstract class AppModule extends Module {
|
||||||
|
|||||||
@@ -1,36 +1,9 @@
|
|||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:postly/app.dart';
|
||||||
import 'di/app_module.dart';
|
import 'di/app_module.dart';
|
||||||
import 'domain/repository/post_repository.dart';
|
|
||||||
import 'presentation/bloc/post_bloc.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'router/app_router.dart';
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final scope = CherryPick.openRootScope();
|
CherryPick.openRootScope().installModules([$AppModule()]);
|
||||||
scope.installModules([$AppModule()]);
|
runApp(MyApp());
|
||||||
|
|
||||||
runApp(MyApp(scope: scope));
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
|
||||||
final Scope scope;
|
|
||||||
final _appRouter = AppRouter();
|
|
||||||
|
|
||||||
MyApp({super.key, required this.scope});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// Получаем репозиторий через injector
|
|
||||||
final repository = scope.resolve<PostRepository>(named: 'repo');
|
|
||||||
|
|
||||||
return BlocProvider(
|
|
||||||
create: (_) => PostBloc(repository),
|
|
||||||
child: MaterialApp.router(
|
|
||||||
routeInformationParser: _appRouter.defaultRouteParser(),
|
|
||||||
routerDelegate: _appRouter.delegate(),
|
|
||||||
theme: ThemeData.light(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:auto_route/auto_route.dart';
|
|||||||
import 'app_router.gr.dart';
|
import 'app_router.gr.dart';
|
||||||
|
|
||||||
@AutoRouterConfig()
|
@AutoRouterConfig()
|
||||||
class AppRouter extends $AppRouter {
|
class AppRouter extends RootStackRouter {
|
||||||
@override
|
@override
|
||||||
List<AutoRoute> get routes => [
|
List<AutoRoute> get routes => [
|
||||||
AutoRoute(page: PostsRoute.page, initial: true),
|
AutoRoute(page: PostsRoute.page, initial: true),
|
||||||
|
|||||||
@@ -42,26 +42,26 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: auto_route
|
name: auto_route
|
||||||
sha256: eb33554581a0a4aa7e6da0f13a44291a55bf71359012f1d9feb41634ff908ff8
|
sha256: "1d1bd908a1fec327719326d5d0791edd37f16caff6493c01003689fb03315ad7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.9.2"
|
version: "9.3.0+1"
|
||||||
auto_route_generator:
|
auto_route_generator:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: auto_route_generator
|
name: auto_route_generator
|
||||||
sha256: "11067a3bcd643812518fe26c0c9ec073990286cabfd9d74b6da9ef9b913c4d22"
|
sha256: c9086eb07271e51b44071ad5cff34e889f3156710b964a308c2ab590769e79e6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.3.2"
|
version: "9.0.0"
|
||||||
bloc:
|
bloc:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: bloc
|
name: bloc
|
||||||
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
|
sha256: "52c10575f4445c61dd9e0cafcc6356fdd827c4c64dd7945ef3c4105f6b6ac189"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.4"
|
version: "9.0.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -156,21 +156,21 @@ packages:
|
|||||||
path: "../../cherrypick"
|
path: "../../cherrypick"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "2.1.0"
|
version: "2.2.0-dev.1"
|
||||||
cherrypick_annotations:
|
cherrypick_annotations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "../../cherrypick_annotations"
|
path: "../../cherrypick_annotations"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.0"
|
version: "1.1.0-dev.0"
|
||||||
cherrypick_generator:
|
cherrypick_generator:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
path: "../../cherrypick_generator"
|
path: "../../cherrypick_generator"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.0"
|
version: "1.1.0-dev.2"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -284,18 +284,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_bloc
|
name: flutter_bloc
|
||||||
sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
|
sha256: cf51747952201a455a1c840f8171d273be009b932c75093020f9af64f2123e38
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.6"
|
version: "9.1.1"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
|
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "5.0.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -417,10 +417,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
|
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "5.0.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -553,10 +553,10 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: retrofit_generator
|
name: retrofit_generator
|
||||||
sha256: "8dfc406cdfa171f33cbd21bf5bd8b6763548cc217de19cdeaa07a76727fac4ca"
|
sha256: f76fdb2b66854690d5a332e7364d7561fc9dc2b3c924d7956ab8070495e21f6a
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.2.1"
|
version: "9.1.5"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -658,14 +658,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
tuple:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: tuple
|
|
||||||
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
cherrypick: ^2.2.0-dev.0
|
cherrypick: ^2.2.0-dev.1
|
||||||
cherrypick_annotations: ^1.1.0-dev.0
|
cherrypick_annotations: ^1.1.0-dev.1
|
||||||
|
|
||||||
dio: ^5.4.0
|
dio: ^5.4.0
|
||||||
retrofit: ^4.0.3
|
retrofit: ^4.0.3
|
||||||
freezed_annotation: ^2.0.0
|
freezed_annotation: ^2.3.2
|
||||||
dartz: ^0.10.1
|
dartz: ^0.10.1
|
||||||
flutter_bloc: ^8.1.2
|
flutter_bloc: ^9.1.1
|
||||||
auto_route: ^7.8.4
|
auto_route: ^9.3.0+1
|
||||||
|
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
|
|
||||||
@@ -28,15 +28,15 @@ dev_dependencies:
|
|||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
flutter_lints: ^4.0.0
|
flutter_lints: ^5.0.0
|
||||||
|
|
||||||
cherrypick_generator: ^1.1.0-dev.0
|
cherrypick_generator: ^1.1.0-dev.3
|
||||||
build_runner: any
|
build_runner: 2.4.13
|
||||||
|
|
||||||
retrofit_generator: ^8.0.4
|
retrofit_generator: ^9.1.5
|
||||||
freezed: ^2.3.2
|
freezed: ^2.3.2
|
||||||
json_serializable: any
|
json_serializable: ^6.9.0
|
||||||
auto_route_generator: ^7.3.2
|
auto_route_generator: ^9.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,11 @@ scripts:
|
|||||||
run: |
|
run: |
|
||||||
melos exec --scope="postly" -- dart run build_runner build --delete-conflicting-outputs
|
melos exec --scope="postly" -- dart run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
|
outdated:
|
||||||
|
exec: dart pub outdated
|
||||||
|
|
||||||
upgrade:
|
upgrade:
|
||||||
exec: darp pub upgrade
|
exec: dart pub upgrade --major-versions
|
||||||
|
|
||||||
drop:
|
drop:
|
||||||
exec: flutter clean
|
exec: flutter clean
|
||||||
|
|||||||
Reference in New Issue
Block a user