mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-05-16 10:10:43 +00:00
Compare commits
10 Commits
3331a3ee9c
...
cherrypick
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4ca6da080 | ||
|
|
4b8f5fe421 | ||
|
|
629d2ed504 | ||
|
|
9cabf98ffb | ||
|
|
8efdcbc918 | ||
|
|
d4fbbdcc1f | ||
|
|
72e1e91b96 | ||
|
|
e67ebbe2ab | ||
|
|
e47adbb7fd | ||
|
|
b7979d653e |
36
CHANGELOG.md
36
CHANGELOG.md
@@ -3,6 +3,42 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
## 2026-04-28
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`cherrypick` - `v3.0.3`](#cherrypick---v303)
|
||||||
|
- [`cherrypick_generator` - `v4.0.0-dev.1`](#cherrypick_generator---v400-dev1)
|
||||||
|
- [`cherrypick_flutter` - `v3.0.3`](#cherrypick_flutter---v303)
|
||||||
|
- [`talker_cherrypick_logger` - `v3.0.3`](#talker_cherrypick_logger---v303)
|
||||||
|
|
||||||
|
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` - `v3.0.3`
|
||||||
|
- `talker_cherrypick_logger` - `v3.0.3`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `cherrypick` - `v3.0.3`
|
||||||
|
|
||||||
|
- **DOCS**: sync references after ProviderFactory rename.
|
||||||
|
|
||||||
|
#### `cherrypick_generator` - `v4.0.0-dev.1`
|
||||||
|
|
||||||
|
- **REFACTOR**(cherrypick_generator): migrate inject codegen to code_builder.
|
||||||
|
- **FIX**: add deps.
|
||||||
|
|
||||||
|
|
||||||
## 2026-01-29
|
## 2026-01-29
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 3.0.3
|
||||||
|
|
||||||
|
- **DOCS**: sync references after ProviderFactory rename.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- **BREAKING** **REFACTOR**(binding): rename `Provider<T>` typedef to `ProviderFactory<T>` to avoid naming conflicts with `package:provider`.
|
||||||
|
|
||||||
## 3.0.2
|
## 3.0.2
|
||||||
|
|
||||||
- **FIX**(test): fix warning.
|
- **FIX**(test): fix warning.
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ class Binding<T> {
|
|||||||
/// bind<Api>().toProvide(() => ApiService());
|
/// bind<Api>().toProvide(() => ApiService());
|
||||||
/// bind<Db>().toProvide(() async => await openDb());
|
/// bind<Db>().toProvide(() async => await openDb());
|
||||||
/// ```
|
/// ```
|
||||||
Binding<T> toProvide(Provider<T> value) {
|
Binding<T> toProvide(ProviderFactory<T> value) {
|
||||||
_resolver = ProviderResolver<T>((_) => value.call(), withParams: false);
|
_resolver = ProviderResolver<T>((_) => value.call(), withParams: false);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ class Binding<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated('Use toProvide instead of toProvideAsync')
|
@Deprecated('Use toProvide instead of toProvideAsync')
|
||||||
Binding<T> toProvideAsync(Provider<T> value) {
|
Binding<T> toProvideAsync(ProviderFactory<T> value) {
|
||||||
return toProvide(value);
|
return toProvide(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ typedef Instance<T> = FutureOr<T>;
|
|||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// Provider<MyService> provider = () => MyService();
|
/// ProviderFactory<MyService> provider = () => MyService();
|
||||||
/// Provider<Api> asyncProvider = () async => await Api.connect();
|
/// ProviderFactory<Api> asyncProvider = () async => await Api.connect();
|
||||||
/// ```
|
/// ```
|
||||||
typedef Provider<T> = FutureOr<T> Function();
|
typedef ProviderFactory<T> = FutureOr<T> Function();
|
||||||
|
|
||||||
/// Provider function type that accepts a dynamic parameter, for factory/parametrized injection.
|
/// Provider function type that accepts a dynamic parameter, for factory/parametrized injection.
|
||||||
/// Returns [T] or [Future<T>].
|
/// Returns [T] or [Future<T>].
|
||||||
|
|||||||
@@ -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: 3.0.2
|
version: 3.0.3
|
||||||
homepage: https://cherrypick-di.netlify.app
|
homepage: https://cherrypick-di.netlify.app
|
||||||
documentation: https://cherrypick-di.netlify.app/docs/intro
|
documentation: https://cherrypick-di.netlify.app/docs/intro
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 3.0.3
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
## 3.0.2
|
## 3.0.2
|
||||||
|
|
||||||
- Update a dependency to the latest release.
|
- Update a dependency to the latest release.
|
||||||
|
|||||||
@@ -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: 3.0.2
|
version: 3.0.3
|
||||||
homepage: https://cherrypick-di.netlify.app
|
homepage: https://cherrypick-di.netlify.app
|
||||||
documentation: https://cherrypick-di.netlify.app/docs/intro
|
documentation: https://cherrypick-di.netlify.app/docs/intro
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
@@ -19,7 +19,7 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cherrypick: ^3.0.2
|
cherrypick: ^3.0.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
## 4.0.0-dev.1
|
||||||
|
|
||||||
|
- **REFACTOR**(cherrypick_generator): migrate inject codegen to code_builder.
|
||||||
|
- **FIX**: add deps.
|
||||||
|
|
||||||
## 4.0.0-dev.0
|
## 4.0.0-dev.0
|
||||||
|
|
||||||
> Note: This release has breaking changes.
|
> Note: This release has breaking changes.
|
||||||
|
|||||||
@@ -11,14 +11,17 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import 'package:analyzer/dart/constant/value.dart';
|
|
||||||
import 'package:analyzer/dart/element/element2.dart';
|
import 'package:analyzer/dart/element/element2.dart';
|
||||||
import 'package:analyzer/dart/element/nullability_suffix.dart';
|
|
||||||
import 'package:analyzer/dart/element/type.dart';
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
|
import 'package:code_builder/code_builder.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann;
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann;
|
||||||
|
|
||||||
|
import 'src/annotation_validator.dart';
|
||||||
|
import 'src/code_builder_emitters.dart';
|
||||||
|
import 'src/type_parser.dart';
|
||||||
|
|
||||||
/// CherryPick DI field injector generator for codegen.
|
/// CherryPick DI field injector generator for codegen.
|
||||||
///
|
///
|
||||||
/// Analyzes all Dart classes marked with `@injectable()` and generates a mixin (for example, `_$ProfileScreen`)
|
/// Analyzes all Dart classes marked with `@injectable()` and generates a mixin (for example, `_$ProfileScreen`)
|
||||||
@@ -115,24 +118,54 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
|||||||
final className = classElement.firstFragment.name2;
|
final className = classElement.firstFragment.name2;
|
||||||
final mixinName = '_\$$className';
|
final mixinName = '_\$$className';
|
||||||
|
|
||||||
final buffer = StringBuffer()
|
AnnotationValidator.validateClassAnnotations(classElement);
|
||||||
..writeln('mixin $mixinName {')
|
|
||||||
..writeln(' void _inject($className instance) {');
|
final classType = TypeParser.parseType(classElement.thisType, classElement);
|
||||||
|
|
||||||
// Collect and process all @inject fields
|
|
||||||
final injectFields = classElement.fields2
|
final injectFields = classElement.fields2
|
||||||
.where((f) => _isInjectField(f))
|
.where((f) => _isInjectField(f))
|
||||||
.map((f) => _parseInjectField(f));
|
.map(_parseInjectField)
|
||||||
|
.toList();
|
||||||
|
|
||||||
for (final parsedField in injectFields) {
|
final injectMethod = Method((b) {
|
||||||
buffer.writeln(_generateInjectionLine(parsedField));
|
b
|
||||||
|
..name = '_inject'
|
||||||
|
..returns = refer('void')
|
||||||
|
..requiredParameters.add(
|
||||||
|
Parameter((p) {
|
||||||
|
p
|
||||||
|
..name = 'instance'
|
||||||
|
..type = CodeBuilderEmitters.resolveTypeRef(classType);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
..body = Block((body) {
|
||||||
|
for (final field in injectFields) {
|
||||||
|
final scopeExpr = CodeBuilderEmitters.openScope(
|
||||||
|
scopeName: field.scopeName,
|
||||||
|
);
|
||||||
|
final resolveExpr = CodeBuilderEmitters.resolveCall(
|
||||||
|
scopeExpr: scopeExpr,
|
||||||
|
parsedType: field.parsedType,
|
||||||
|
named: field.namedValue,
|
||||||
|
);
|
||||||
|
body.statements.add(
|
||||||
|
refer(
|
||||||
|
'instance',
|
||||||
|
).property(field.fieldName).assign(resolveExpr).statement,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
buffer
|
final mixin = Mixin((b) {
|
||||||
..writeln(' }')
|
b
|
||||||
..writeln('}');
|
..name = mixinName
|
||||||
|
..methods.add(injectMethod);
|
||||||
|
});
|
||||||
|
|
||||||
return buffer.toString();
|
final library = Library((b) => b..body.add(mixin));
|
||||||
|
final emitter = DartEmitter(useNullSafetySyntax: true);
|
||||||
|
return '${library.accept(emitter)}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if a field is annotated with `@inject`.
|
/// Returns true if a field is annotated with `@inject`.
|
||||||
@@ -150,11 +183,13 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
|||||||
/// Converts Dart field declaration and all parameterizing injection-related
|
/// Converts Dart field declaration and all parameterizing injection-related
|
||||||
/// annotations into a [_ParsedInjectField] which is used for codegen.
|
/// annotations into a [_ParsedInjectField] which is used for codegen.
|
||||||
static _ParsedInjectField _parseInjectField(FieldElement2 field) {
|
static _ParsedInjectField _parseInjectField(FieldElement2 field) {
|
||||||
|
AnnotationValidator.validateFieldAnnotations(field);
|
||||||
|
|
||||||
String? scopeName;
|
String? scopeName;
|
||||||
String? namedValue;
|
String? namedValue;
|
||||||
|
|
||||||
for (final meta in field.firstFragment.metadata2.annotations) {
|
for (final meta in field.firstFragment.metadata2.annotations) {
|
||||||
final DartObject? obj = meta.computeConstantValue();
|
final obj = meta.computeConstantValue();
|
||||||
final type = obj?.type?.getDisplayString();
|
final type = obj?.type?.getDisplayString();
|
||||||
if (type == 'scope') {
|
if (type == 'scope') {
|
||||||
scopeName = obj?.getField('name')?.toStringValue();
|
scopeName = obj?.getField('name')?.toStringValue();
|
||||||
@@ -164,65 +199,15 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final DartType dartType = field.type;
|
final DartType dartType = field.type;
|
||||||
String coreTypeName;
|
final parsedType = TypeParser.parseType(dartType, field);
|
||||||
bool isFuture;
|
|
||||||
|
|
||||||
if (dartType.isDartAsyncFuture) {
|
|
||||||
final ParameterizedType paramType = dartType as ParameterizedType;
|
|
||||||
coreTypeName = paramType.typeArguments.first.getDisplayString();
|
|
||||||
isFuture = true;
|
|
||||||
} else {
|
|
||||||
coreTypeName = dartType.getDisplayString();
|
|
||||||
isFuture = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine nullability for field types like T? or Future<T?>
|
|
||||||
bool isNullable =
|
|
||||||
dartType.nullabilitySuffix == NullabilitySuffix.question ||
|
|
||||||
(dartType is ParameterizedType &&
|
|
||||||
(dartType).typeArguments.any(
|
|
||||||
(t) => t.nullabilitySuffix == NullabilitySuffix.question,
|
|
||||||
));
|
|
||||||
|
|
||||||
return _ParsedInjectField(
|
return _ParsedInjectField(
|
||||||
fieldName: field.firstFragment.name2 ?? '',
|
fieldName: field.firstFragment.name2 ?? '',
|
||||||
coreType: coreTypeName.replaceAll('?', ''), // удаляем "?" на всякий
|
parsedType: parsedType,
|
||||||
isFuture: isFuture,
|
|
||||||
isNullable: isNullable,
|
|
||||||
scopeName: scopeName,
|
scopeName: scopeName,
|
||||||
namedValue: namedValue,
|
namedValue: namedValue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates Dart code for a single dependency-injected field based on its metadata.
|
|
||||||
///
|
|
||||||
/// This code will resolve the field from the CherryPick DI container and assign it to the class instance.
|
|
||||||
/// Correctly dispatches to resolve, tryResolve, resolveAsync, or tryResolveAsync methods,
|
|
||||||
/// and applies container scoping or named resolution where required.
|
|
||||||
///
|
|
||||||
/// Returns literal Dart code as string (1 line).
|
|
||||||
///
|
|
||||||
/// Example output:
|
|
||||||
/// `instance.logger = CherryPick.openRootScope().resolve<Logger>();`
|
|
||||||
String _generateInjectionLine(_ParsedInjectField field) {
|
|
||||||
final resolveMethod = field.isFuture
|
|
||||||
? (field.isNullable
|
|
||||||
? 'tryResolveAsync<${field.coreType}>'
|
|
||||||
: 'resolveAsync<${field.coreType}>')
|
|
||||||
: (field.isNullable
|
|
||||||
? 'tryResolve<${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.$resolveMethod$params;";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal structure: describes all required information for generating the injection
|
/// Internal structure: describes all required information for generating the injection
|
||||||
@@ -233,14 +218,8 @@ class _ParsedInjectField {
|
|||||||
/// The name of the field to be injected.
|
/// The name of the field to be injected.
|
||||||
final String fieldName;
|
final String fieldName;
|
||||||
|
|
||||||
/// The Dart type to resolve (e.g. `Logger` from `Logger` or `Future<Logger>`).
|
/// Parsed type info for the field.
|
||||||
final String coreType;
|
final ParsedType parsedType;
|
||||||
|
|
||||||
/// True if the field is an async dependency (Future<...>), otherwise false.
|
|
||||||
final bool isFuture;
|
|
||||||
|
|
||||||
/// True if the field accepts null (T?), otherwise false.
|
|
||||||
final bool isNullable;
|
|
||||||
|
|
||||||
/// The scoping for DI resolution, or null to use root scope.
|
/// The scoping for DI resolution, or null to use root scope.
|
||||||
final String? scopeName;
|
final String? scopeName;
|
||||||
@@ -250,9 +229,7 @@ class _ParsedInjectField {
|
|||||||
|
|
||||||
_ParsedInjectField({
|
_ParsedInjectField({
|
||||||
required this.fieldName,
|
required this.fieldName,
|
||||||
required this.coreType,
|
required this.parsedType,
|
||||||
required this.isFuture,
|
|
||||||
required this.isNullable,
|
|
||||||
this.scopeName,
|
this.scopeName,
|
||||||
this.namedValue,
|
this.namedValue,
|
||||||
});
|
});
|
||||||
|
|||||||
80
cherrypick_generator/lib/src/code_builder_emitters.dart
Normal file
80
cherrypick_generator/lib/src/code_builder_emitters.dart
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// 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:code_builder/code_builder.dart';
|
||||||
|
|
||||||
|
import 'type_parser.dart';
|
||||||
|
|
||||||
|
/// Small helpers for building code_builder AST nodes used by generators.
|
||||||
|
class CodeBuilderEmitters {
|
||||||
|
/// Builds a CherryPick scope opener expression.
|
||||||
|
///
|
||||||
|
/// - If [scopeName] is empty or null, uses openRootScope().
|
||||||
|
/// - Otherwise uses openScope(scopeName: ...).
|
||||||
|
static Expression openScope({String? scopeName}) {
|
||||||
|
if (scopeName == null || scopeName.isEmpty) {
|
||||||
|
return refer('CherryPick').property('openRootScope').call([]);
|
||||||
|
}
|
||||||
|
return refer(
|
||||||
|
'CherryPick',
|
||||||
|
).property('openScope').call([], {'scopeName': literalString(scopeName)});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds a TypeReference appropriate for resolving a dependency.
|
||||||
|
///
|
||||||
|
/// For Future<T>, it returns the inner type reference (T).
|
||||||
|
/// Nullability and generic arguments are preserved.
|
||||||
|
static TypeReference resolveTypeRef(ParsedType parsedType) {
|
||||||
|
final target = parsedType.isFuture && parsedType.innerType != null
|
||||||
|
? parsedType.innerType!
|
||||||
|
: parsedType;
|
||||||
|
return _typeRefFromParsedType(target, stripNullability: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds a DI resolve call on [scopeExpr] using [parsedType] and [named].
|
||||||
|
///
|
||||||
|
/// The method name is derived from [ParsedType.resolveMethodName].
|
||||||
|
static Expression resolveCall({
|
||||||
|
required Expression scopeExpr,
|
||||||
|
required ParsedType parsedType,
|
||||||
|
String? named,
|
||||||
|
}) {
|
||||||
|
final typeRef = resolveTypeRef(parsedType);
|
||||||
|
final method = parsedType.resolveMethodName;
|
||||||
|
final args = <Expression>[];
|
||||||
|
final namedArgs = <String, Expression>{};
|
||||||
|
if (named != null && named.isNotEmpty) {
|
||||||
|
namedArgs['named'] = literalString(named);
|
||||||
|
}
|
||||||
|
return scopeExpr.property(method).call(args, namedArgs, [typeRef]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TypeReference _typeRefFromParsedType(
|
||||||
|
ParsedType parsedType, {
|
||||||
|
required bool stripNullability,
|
||||||
|
}) {
|
||||||
|
return TypeReference((b) {
|
||||||
|
b
|
||||||
|
..symbol = parsedType.coreType
|
||||||
|
..isNullable = stripNullability ? false : parsedType.isNullable;
|
||||||
|
if (parsedType.typeArguments.isNotEmpty) {
|
||||||
|
b.types.addAll(
|
||||||
|
parsedType.typeArguments.map(
|
||||||
|
(arg) =>
|
||||||
|
_typeRefFromParsedType(arg, stripNullability: stripNullability),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,6 +65,8 @@ class CherryPickGeneratorException extends InvalidGenerationSourceError {
|
|||||||
Element2 element,
|
Element2 element,
|
||||||
) {
|
) {
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
|
final location = _safeLocation(element);
|
||||||
|
final enclosing = _safeEnclosingDisplayName(element);
|
||||||
|
|
||||||
// Header with category
|
// Header with category
|
||||||
buffer.writeln('[$category] $message');
|
buffer.writeln('[$category] $message');
|
||||||
@@ -74,18 +76,11 @@ class CherryPickGeneratorException extends InvalidGenerationSourceError {
|
|||||||
buffer.writeln('Context:');
|
buffer.writeln('Context:');
|
||||||
buffer.writeln(' Element: ${element.displayName}');
|
buffer.writeln(' Element: ${element.displayName}');
|
||||||
buffer.writeln(' Type: ${element.runtimeType}');
|
buffer.writeln(' Type: ${element.runtimeType}');
|
||||||
buffer.writeln(
|
buffer.writeln(' Location: $location');
|
||||||
' Location: ${element.firstFragment.libraryFragment?.source.fullName ?? 'unknown'}',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Try to show enclosing element info for extra context
|
// Try to show enclosing element info for extra context
|
||||||
try {
|
|
||||||
final enclosing = (element as dynamic).enclosingElement;
|
|
||||||
if (enclosing != null) {
|
if (enclosing != null) {
|
||||||
buffer.writeln(' Enclosing: ${enclosing.displayName}');
|
buffer.writeln(' Enclosing: $enclosing');
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// Ignore if enclosingElement is not available
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrary user context
|
// Arbitrary user context
|
||||||
@@ -105,6 +100,34 @@ class CherryPickGeneratorException extends InvalidGenerationSourceError {
|
|||||||
|
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Best-effort extraction of element location for diagnostics.
|
||||||
|
///
|
||||||
|
/// Some tests use lightweight mocks for [Element2] that don't implement
|
||||||
|
/// analyzer fragment APIs, so this method must never throw.
|
||||||
|
static String _safeLocation(Element2 element) {
|
||||||
|
try {
|
||||||
|
return element.firstFragment.libraryFragment?.source.fullName ??
|
||||||
|
'unknown';
|
||||||
|
} catch (_) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Best-effort extraction of enclosing element display name.
|
||||||
|
///
|
||||||
|
/// Accessed via dynamic to stay compatible with analyzer API differences.
|
||||||
|
static String? _safeEnclosingDisplayName(Element2 element) {
|
||||||
|
try {
|
||||||
|
final enclosing = (element as dynamic).enclosingElement;
|
||||||
|
if (enclosing == null) return null;
|
||||||
|
final name = enclosing.displayName;
|
||||||
|
if (name is String && name.isNotEmpty) return name;
|
||||||
|
return enclosing.toString();
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ---------------------------------------------------------------------------
|
/// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: cherrypick_generator
|
|||||||
description: |
|
description: |
|
||||||
Source code generator for the cherrypick dependency injection system. Processes annotations to generate binding and module code for Dart & Flutter projects.
|
Source code generator for the cherrypick dependency injection system. Processes annotations to generate binding and module code for Dart & Flutter projects.
|
||||||
|
|
||||||
version: 4.0.0-dev.0
|
version: 4.0.0-dev.1
|
||||||
homepage: https://cherrypick-di.netlify.app
|
homepage: https://cherrypick-di.netlify.app
|
||||||
documentation: https://cherrypick-di.netlify.app/docs/intro
|
documentation: https://cherrypick-di.netlify.app/docs/intro
|
||||||
repository: https://github.com/pese-git/cherrypick/cherrypick_generator
|
repository: https://github.com/pese-git/cherrypick/cherrypick_generator
|
||||||
@@ -22,9 +22,12 @@ dependencies:
|
|||||||
cherrypick_annotations: ^4.0.0-dev.0
|
cherrypick_annotations: ^4.0.0-dev.0
|
||||||
analyzer: ">=8.2.9 <10.0.1"
|
analyzer: ">=8.2.9 <10.0.1"
|
||||||
dart_style: ^3.0.0
|
dart_style: ^3.0.0
|
||||||
|
code_builder: ^4.10.1
|
||||||
build: ^3.0.0
|
build: ^3.0.0
|
||||||
source_gen: ^4.2.0
|
source_gen: ^4.2.0
|
||||||
collection: ^1.18.0
|
collection: ^1.18.0
|
||||||
|
package_config: ^2.2.0
|
||||||
|
build_runner_core: ^9.3.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^6.0.0
|
lints: ^6.0.0
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// 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:test/test.dart';
|
|
||||||
|
|
||||||
// Import working test suites
|
|
||||||
import 'simple_test.dart' as simple_tests;
|
|
||||||
import 'bind_spec_test.dart' as bind_spec_tests;
|
|
||||||
import 'metadata_utils_test.dart' as metadata_utils_tests;
|
|
||||||
// Import integration test suites (now working!)
|
|
||||||
import 'module_generator_test.dart' as module_generator_tests;
|
|
||||||
import 'inject_generator_test.dart' as inject_generator_tests;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('CherryPick Generator Tests', () {
|
|
||||||
group('Simple Tests', simple_tests.main);
|
|
||||||
group('BindSpec Tests', bind_spec_tests.main);
|
|
||||||
group('MetadataUtils Tests', metadata_utils_tests.main);
|
|
||||||
group('ModuleGenerator Tests', module_generator_tests.main);
|
|
||||||
group('InjectGenerator Tests', inject_generator_tests.main);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -11,9 +11,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import 'dart:isolate';
|
||||||
|
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
import 'package:build_test/build_test.dart';
|
import 'package:build_test/build_test.dart';
|
||||||
|
import 'package:build_runner_core/build_runner_core.dart';
|
||||||
import 'package:cherrypick_generator/inject_generator.dart';
|
import 'package:cherrypick_generator/inject_generator.dart';
|
||||||
|
import 'package:package_config/package_config.dart';
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
@@ -40,8 +44,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -75,8 +79,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -113,8 +117,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -124,9 +128,8 @@ part of 'test_widget.dart';
|
|||||||
|
|
||||||
mixin _\$TestWidget {
|
mixin _\$TestWidget {
|
||||||
void _inject(TestWidget instance) {
|
void _inject(TestWidget instance) {
|
||||||
instance.service = CherryPick.openRootScope().resolve<MyService>(
|
instance.service =
|
||||||
named: 'myService',
|
CherryPick.openRootScope().resolve<MyService>(named: 'myService');
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
@@ -151,8 +154,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -162,9 +165,8 @@ part of 'test_widget.dart';
|
|||||||
|
|
||||||
mixin _\$TestWidget {
|
mixin _\$TestWidget {
|
||||||
void _inject(TestWidget instance) {
|
void _inject(TestWidget instance) {
|
||||||
instance.service = CherryPick.openRootScope().tryResolve<MyService>(
|
instance.service =
|
||||||
named: 'myService',
|
CherryPick.openRootScope().tryResolve<MyService>(named: 'myService');
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
@@ -191,8 +193,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -229,8 +231,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -240,9 +242,9 @@ part of 'test_widget.dart';
|
|||||||
|
|
||||||
mixin _\$TestWidget {
|
mixin _\$TestWidget {
|
||||||
void _inject(TestWidget instance) {
|
void _inject(TestWidget instance) {
|
||||||
instance.service = CherryPick.openScope(
|
instance.service =
|
||||||
scopeName: 'userScope',
|
CherryPick.openScope(scopeName: 'userScope')
|
||||||
).resolve<MyService>(named: 'myService');
|
.resolve<MyService>(named: 'myService');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
@@ -268,8 +270,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -303,8 +305,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -339,8 +341,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -350,9 +352,8 @@ part of 'test_widget.dart';
|
|||||||
|
|
||||||
mixin _\$TestWidget {
|
mixin _\$TestWidget {
|
||||||
void _inject(TestWidget instance) {
|
void _inject(TestWidget instance) {
|
||||||
instance.service = CherryPick.openRootScope().resolveAsync<MyService>(
|
instance.service =
|
||||||
named: 'myService',
|
CherryPick.openRootScope().resolveAsync<MyService>(named: 'myService');
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
@@ -391,8 +392,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -403,13 +404,11 @@ part of 'test_widget.dart';
|
|||||||
mixin _\$TestWidget {
|
mixin _\$TestWidget {
|
||||||
void _inject(TestWidget instance) {
|
void _inject(TestWidget instance) {
|
||||||
instance.apiService = CherryPick.openRootScope().resolve<ApiService>();
|
instance.apiService = CherryPick.openRootScope().resolve<ApiService>();
|
||||||
instance.cacheService = CherryPick.openRootScope().tryResolve<CacheService>(
|
instance.cacheService =
|
||||||
named: 'cache',
|
CherryPick.openRootScope().tryResolve<CacheService>(named: 'cache');
|
||||||
);
|
|
||||||
instance.dbService =
|
instance.dbService =
|
||||||
CherryPick.openScope(
|
CherryPick.openScope(scopeName: 'dbScope')
|
||||||
scopeName: 'dbScope',
|
.resolveAsync<DatabaseService>();
|
||||||
).resolveAsync<DatabaseService>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
@@ -439,8 +438,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -496,8 +495,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -533,8 +532,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -569,8 +568,8 @@ class TestWidget {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_widget.dart';
|
part of 'test_widget.dart';
|
||||||
|
|
||||||
@@ -593,10 +592,41 @@ mixin _\$TestWidget {
|
|||||||
|
|
||||||
/// Helper function to test code generation
|
/// Helper function to test code generation
|
||||||
Future<void> _testGeneration(String input, String expectedOutput) async {
|
Future<void> _testGeneration(String input, String expectedOutput) async {
|
||||||
await testBuilder(
|
final readerWriter = TestReaderWriter(rootPackage: 'a');
|
||||||
|
await readerWriter.testing.loadIsolateSources();
|
||||||
|
final packageConfig = await loadPackageConfigUri(
|
||||||
|
(await Isolate.packageConfig)!,
|
||||||
|
);
|
||||||
|
final outputs = expectedOutput.isEmpty
|
||||||
|
? null
|
||||||
|
: {
|
||||||
|
'a|lib/test_widget.inject.cherrypick.g.dart':
|
||||||
|
decodedMatches(_normalizedEquals(expectedOutput)),
|
||||||
|
};
|
||||||
|
final result = await testBuilder(
|
||||||
injectBuilder(BuilderOptions.empty),
|
injectBuilder(BuilderOptions.empty),
|
||||||
{'a|lib/test_widget.dart': input},
|
{'a|lib/test_widget.dart': input},
|
||||||
outputs: {'a|lib/test_widget.inject.cherrypick.g.dart': expectedOutput},
|
outputs: outputs,
|
||||||
readerWriter: TestReaderWriter(),
|
readerWriter: readerWriter,
|
||||||
|
rootPackage: 'a',
|
||||||
|
packageConfig: packageConfig,
|
||||||
|
);
|
||||||
|
if (expectedOutput.isEmpty && result.buildResult.status == BuildStatus.failure) {
|
||||||
|
throw InvalidGenerationSourceError('Build failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher _normalizedEquals(String expected) {
|
||||||
|
return predicate<String>(
|
||||||
|
(actual) => _normalize(actual) == _normalize(expected),
|
||||||
|
'matches after normalization',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _normalize(String input) {
|
||||||
|
return input
|
||||||
|
.replaceAll(RegExp(r'\s+'), '')
|
||||||
|
.replaceAll(RegExp(r',\)'), ')')
|
||||||
|
.replaceAll(RegExp(r',\]'), ']')
|
||||||
|
.replaceAll(RegExp(r',\}'), '}');
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,12 +11,16 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'dart:isolate';
|
||||||
import 'package:build_test/build_test.dart';
|
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
|
import 'package:build_test/build_test.dart';
|
||||||
|
import 'package:build_runner_core/build_runner_core.dart';
|
||||||
|
import 'package:package_config/package_config.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import 'package:cherrypick_generator/module_generator.dart';
|
|
||||||
import 'package:source_gen/source_gen.dart';
|
import 'package:source_gen/source_gen.dart';
|
||||||
|
import 'package:cherrypick_generator/module_generator.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('ModuleGenerator Tests', () {
|
group('ModuleGenerator Tests', () {
|
||||||
@@ -40,8 +44,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -75,8 +79,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -113,8 +117,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -149,8 +153,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -187,8 +191,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -224,8 +228,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -264,8 +268,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -299,8 +303,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -334,8 +338,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -374,8 +378,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -414,8 +418,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -453,8 +457,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -488,8 +492,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -541,8 +545,8 @@ abstract class TestModule extends Module {
|
|||||||
''';
|
''';
|
||||||
|
|
||||||
const expectedOutput = '''
|
const expectedOutput = '''
|
||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format width=80
|
||||||
|
|
||||||
part of 'test_module.dart';
|
part of 'test_module.dart';
|
||||||
|
|
||||||
@@ -637,10 +641,41 @@ abstract class TestModule extends Module {
|
|||||||
|
|
||||||
/// Helper function to test code generation
|
/// Helper function to test code generation
|
||||||
Future<void> _testGeneration(String input, String expectedOutput) async {
|
Future<void> _testGeneration(String input, String expectedOutput) async {
|
||||||
await testBuilder(
|
final readerWriter = TestReaderWriter(rootPackage: 'a');
|
||||||
|
await readerWriter.testing.loadIsolateSources();
|
||||||
|
final packageConfig = await loadPackageConfigUri(
|
||||||
|
(await Isolate.packageConfig)!,
|
||||||
|
);
|
||||||
|
final outputs = expectedOutput.isEmpty
|
||||||
|
? null
|
||||||
|
: {
|
||||||
|
'a|lib/test_module.module.cherrypick.g.dart':
|
||||||
|
decodedMatches(_normalizedEquals(expectedOutput)),
|
||||||
|
};
|
||||||
|
final result = await testBuilder(
|
||||||
moduleBuilder(BuilderOptions.empty),
|
moduleBuilder(BuilderOptions.empty),
|
||||||
{'a|lib/test_module.dart': input},
|
{'a|lib/test_module.dart': input},
|
||||||
outputs: {'a|lib/test_module.module.cherrypick.g.dart': expectedOutput},
|
outputs: outputs,
|
||||||
readerWriter: TestReaderWriter(),
|
readerWriter: readerWriter,
|
||||||
|
rootPackage: 'a',
|
||||||
|
packageConfig: packageConfig,
|
||||||
|
);
|
||||||
|
if (expectedOutput.isEmpty && result.buildResult.status == BuildStatus.failure) {
|
||||||
|
throw InvalidGenerationSourceError('Build failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher _normalizedEquals(String expected) {
|
||||||
|
return predicate<String>(
|
||||||
|
(actual) => _normalize(actual) == _normalize(expected),
|
||||||
|
'matches after normalization',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _normalize(String input) {
|
||||||
|
return input
|
||||||
|
.replaceAll(RegExp(r'\s+'), '')
|
||||||
|
.replaceAll(RegExp(r',\)'), ')')
|
||||||
|
.replaceAll(RegExp(r',\]'), ']')
|
||||||
|
.replaceAll(RegExp(r',\}'), '}');
|
||||||
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ packages:
|
|||||||
path: "../../cherrypick_annotations"
|
path: "../../cherrypick_annotations"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "3.0.2"
|
version: "4.0.0-dev.0"
|
||||||
cherrypick_flutter:
|
cherrypick_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -148,7 +148,7 @@ packages:
|
|||||||
path: "../../cherrypick_generator"
|
path: "../../cherrypick_generator"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "3.0.2"
|
version: "4.0.0-dev.0"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -182,14 +182,14 @@ packages:
|
|||||||
path: "../../cherrypick_annotations"
|
path: "../../cherrypick_annotations"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "3.0.2"
|
version: "4.0.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: "3.0.2"
|
version: "4.0.0-dev.0"
|
||||||
cli_launcher:
|
cli_launcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
cherrypick: any
|
cherrypick: ^3.0.3
|
||||||
cherrypick_annotations: ^4.0.0-dev.0
|
cherrypick_annotations: ^4.0.0-dev.0
|
||||||
|
|
||||||
dio: ^5.4.0
|
dio: ^5.4.0
|
||||||
@@ -27,7 +27,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
|
|
||||||
talker_flutter: ^5.0.0
|
talker_flutter: ^5.0.0
|
||||||
talker_cherrypick_logger: any
|
talker_cherrypick_logger: ^3.0.3
|
||||||
talker_dio_logger: ^5.0.0
|
talker_dio_logger: ^5.0.0
|
||||||
talker_bloc_logger: ^5.0.0
|
talker_bloc_logger: ^5.0.0
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ dev_dependencies:
|
|||||||
flutter_lints: ^6.0.0
|
flutter_lints: ^6.0.0
|
||||||
|
|
||||||
build_runner: ^2.5.0
|
build_runner: ^2.5.0
|
||||||
cherrypick_generator: ^4.0.0-dev.0
|
cherrypick_generator: ^4.0.0-dev.1
|
||||||
|
|
||||||
json_serializable: ^6.9.0
|
json_serializable: ^6.9.0
|
||||||
retrofit_generator: ^10.0.5
|
retrofit_generator: ^10.0.5
|
||||||
|
|||||||
@@ -60,8 +60,10 @@ scripts:
|
|||||||
scope: ["cherrypick_flutter"]
|
scope: ["cherrypick_flutter"]
|
||||||
|
|
||||||
codegen:
|
codegen:
|
||||||
run: |
|
description: "Run build for Flutter packages only"
|
||||||
melos exec --scope="postly" -- dart run build_runner build --delete-conflicting-outputs
|
exec: dart run build_runner build --delete-conflicting-outputs
|
||||||
|
packageFilters:
|
||||||
|
scope: ["postly"]
|
||||||
|
|
||||||
outdated:
|
outdated:
|
||||||
exec: dart pub outdated
|
exec: dart pub outdated
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 3.0.3
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
## 3.0.2
|
## 3.0.2
|
||||||
|
|
||||||
- Update a dependency to the latest release.
|
- Update a dependency to the latest release.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: talker_cherrypick_logger
|
name: talker_cherrypick_logger
|
||||||
description: A Talker logger integration for CherryPick DI to observe and log DI events and errors.
|
description: A Talker logger integration for CherryPick DI to observe and log DI events and errors.
|
||||||
version: 3.0.2
|
version: 3.0.3
|
||||||
homepage: https://cherrypick-di.netlify.app
|
homepage: https://cherrypick-di.netlify.app
|
||||||
documentation: https://cherrypick-di.netlify.app/docs/intro
|
documentation: https://cherrypick-di.netlify.app/docs/intro
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
@@ -18,7 +18,7 @@ environment:
|
|||||||
# Add regular dependencies here.
|
# Add regular dependencies here.
|
||||||
dependencies:
|
dependencies:
|
||||||
talker: ^5.0.0
|
talker: ^5.0.0
|
||||||
cherrypick: ^3.0.2
|
cherrypick: ^3.0.3
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user