Compare commits

..

3 Commits

Author SHA1 Message Date
Sergey Penkovsky
25ae208ea1 fix(test): fix warning 2025-10-20 16:20:20 +03:00
Sergey Penkovsky
685c0ae49c fix(scope): properly clear binding and module references on dispose
Add memory leak/finalizer test to ensure no strong references remain after closing and disposing a scope.
2025-10-13 17:32:10 +03:00
Sergey Penkovsky
98d81b13a8 freeze deps 2025-10-13 17:26:39 +03:00
35 changed files with 432 additions and 492 deletions

2
.fvmrc
View File

@@ -1,3 +1,3 @@
{ {
"flutter": "3.32.0" "flutter": "3.27.0"
} }

View File

@@ -3,32 +3,6 @@
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-09-09
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`cherrypick_annotations` - `v3.0.2-dev.0`](#cherrypick_annotations---v302-dev0)
- [`cherrypick_generator` - `v3.0.2-dev.0`](#cherrypick_generator---v302-dev0)
---
#### `cherrypick_annotations` - `v3.0.2-dev.0`
- **REFACTOR**(generator): migrate cherrypick_generator to analyzer element2 API.
#### `cherrypick_generator` - `v3.0.2-dev.0`
- **REFACTOR**(generator): migrate cherrypick_generator to analyzer element2 API.
## 2025-09-09 ## 2025-09-09
### Changes ### Changes

View File

@@ -47,7 +47,7 @@ packages:
path: "../cherrypick" path: "../cherrypick"
relative: true relative: true
source: path source: path
version: "3.0.0" version: "3.0.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:

View File

@@ -498,5 +498,10 @@ class Scope with CycleDetectionMixin, GlobalCycleDetectionMixin {
await d.dispose(); await d.dispose();
} }
_disposables.clear(); _disposables.clear();
// Clear modules
_modulesList.clear();
// Clear binding-index
_bindingResolvers.clear();
} }
} }

View File

@@ -0,0 +1,65 @@
import 'dart:async';
import 'package:cherrypick/cherrypick.dart';
import 'package:test/test.dart';
class HeavyService implements Disposable {
static int instanceCount = 0;
HeavyService() {
instanceCount++;
print('HeavyService created. Instance count: '
'\u001b[32m$instanceCount\u001b[0m');
}
@override
void dispose() {
instanceCount--;
print('HeavyService disposed. Instance count: '
'\u001b[31m$instanceCount\u001b[0m');
}
static final Finalizer<String> _finalizer = Finalizer((msg) {
print('GC FINALIZED HeavyService: $msg');
});
void registerFinalizer() => _finalizer.attach(this, toString(), detach: this);
}
class HeavyModule extends Module {
@override
void builder(Scope scope) {
bind<HeavyService>().toProvide(() => HeavyService());
}
}
void main() {
test('Binding memory is cleared after closing and reopening scope', () async {
final root = CherryPick.openRootScope();
for (int i = 0; i < 10; i++) {
print('\nIteration $i -------------------------------');
final subScope = root.openSubScope('leak-test-scope');
subScope.installModules([HeavyModule()]);
final service = subScope.resolve<HeavyService>();
expect(service, isNotNull);
await root.closeSubScope('leak-test-scope');
// Dart GC не сразу удаляет освобождённые объекты, добавляем паузу и вызываем GC.
await Future.delayed(const Duration(milliseconds: 200));
}
// Если dispose не вызвался, instanceCount > 0 => утечка.
expect(HeavyService.instanceCount, equals(0));
});
test('Service is finalized after scope is closed/cleaned', () async {
final root = CherryPick.openRootScope();
HeavyService? ref;
{
final sub = root.openSubScope('s');
sub.installModules([HeavyModule()]);
ref = sub.resolve<HeavyService>();
ref.registerFinalizer();
expect(HeavyService.instanceCount, 1);
await root.closeSubScope('s');
}
await Future.delayed(const Duration(seconds: 2));
expect(HeavyService.instanceCount, 0);
});
}

View File

@@ -1,7 +1,3 @@
## 3.0.2-dev.0
- **REFACTOR**(generator): migrate cherrypick_generator to analyzer element2 API.
## 3.0.1 ## 3.0.1
- **DOCS**: add Netlify deployment status badge to README files. - **DOCS**: add Netlify deployment status badge to README files.

View File

@@ -1,7 +1,7 @@
name: cherrypick_annotations name: cherrypick_annotations
description: | description: |
Set of annotations for CherryPick dependency injection library. Enables code generation and declarative DI for Dart & Flutter projects. Set of annotations for CherryPick dependency injection library. Enables code generation and declarative DI for Dart & Flutter projects.
version: 3.0.2-dev.0 version: 3.0.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_annotations repository: https://github.com/pese-git/cherrypick/cherrypick_annotations
@@ -14,7 +14,7 @@ topics:
- inversion-of-control - inversion-of-control
environment: environment:
sdk: ">=3.8.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"
# Add regular dependencies here. # Add regular dependencies here.
dependencies: dependencies:
@@ -22,5 +22,5 @@ dependencies:
# path: ^1.8.0 # path: ^1.8.0
dev_dependencies: dev_dependencies:
lints: ^6.0.0 lints: ^5.0.0
test: ^1.25.8 test: ^1.25.8

View File

@@ -1,7 +1,3 @@
## 3.0.2-dev.0
- **REFACTOR**(generator): migrate cherrypick_generator to analyzer element2 API.
## 3.0.1 ## 3.0.1
- **DOCS**: add Netlify deployment status badge to README files. - **DOCS**: add Netlify deployment status badge to README files.

View File

@@ -11,12 +11,13 @@
// limitations under the License. // limitations under the License.
// //
import 'dart:async';
import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/nullability_suffix.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:source_gen/source_gen.dart'; import 'package:source_gen/source_gen.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann; import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann;
/// CherryPick DI field injector generator for codegen. /// CherryPick DI field injector generator for codegen.
@@ -99,12 +100,12 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
/// } /// }
/// ``` /// ```
@override @override
dynamic generateForAnnotatedElement( FutureOr<String> generateForAnnotatedElement(
Element2 element, Element element,
ConstantReader annotation, ConstantReader annotation,
BuildStep buildStep, BuildStep buildStep,
) { ) {
if (element is! ClassElement2) { if (element is! ClassElement) {
throw InvalidGenerationSourceError( throw InvalidGenerationSourceError(
'@injectable() can only be applied to classes.', '@injectable() can only be applied to classes.',
element: element, element: element,
@@ -112,7 +113,7 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
} }
final classElement = element; final classElement = element;
final className = classElement.firstFragment.name2; final className = classElement.name;
final mixinName = '_\$$className'; final mixinName = '_\$$className';
final buffer = StringBuffer() final buffer = StringBuffer()
@@ -120,9 +121,8 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
..writeln(' void _inject($className instance) {'); ..writeln(' void _inject($className instance) {');
// Collect and process all @inject fields // Collect and process all @inject fields
final injectFields = classElement.fields2 final injectFields =
.where((f) => _isInjectField(f)) classElement.fields.where(_isInjectField).map(_parseInjectField);
.map((f) => _parseInjectField(f));
for (final parsedField in injectFields) { for (final parsedField in injectFields) {
buffer.writeln(_generateInjectionLine(parsedField)); buffer.writeln(_generateInjectionLine(parsedField));
@@ -138,8 +138,8 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
/// Returns true if a field is annotated with `@inject`. /// Returns true if a field is annotated with `@inject`.
/// ///
/// Used to detect which fields should be processed for injection. /// Used to detect which fields should be processed for injection.
static bool _isInjectField(FieldElement2 field) { static bool _isInjectField(FieldElement field) {
return field.firstFragment.metadata2.annotations.any( return field.metadata.any(
(m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject', (m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject',
); );
} }
@@ -149,11 +149,11 @@ 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(FieldElement field) {
String? scopeName; String? scopeName;
String? namedValue; String? namedValue;
for (final meta in field.firstFragment.metadata2.annotations) { for (final meta in field.metadata) {
final DartObject? obj = meta.computeConstantValue(); final DartObject? obj = meta.computeConstantValue();
final type = obj?.type?.getDisplayString(); final type = obj?.type?.getDisplayString();
if (type == 'scope') { if (type == 'scope') {
@@ -177,15 +177,15 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
} }
// Determine nullability for field types like T? or Future<T?> // Determine nullability for field types like T? or Future<T?>
bool isNullable = bool isNullable = dartType.nullabilitySuffix ==
dartType.nullabilitySuffix == NullabilitySuffix.question || NullabilitySuffix.question ||
(dartType is ParameterizedType && (dartType is ParameterizedType &&
(dartType).typeArguments.any( (dartType)
(t) => t.nullabilitySuffix == NullabilitySuffix.question, .typeArguments
)); .any((t) => t.nullabilitySuffix == NullabilitySuffix.question));
return _ParsedInjectField( return _ParsedInjectField(
fieldName: field.firstFragment.name2 ?? '', fieldName: field.name,
coreType: coreTypeName.replaceAll('?', ''), // удаляем "?" на всякий coreType: coreTypeName.replaceAll('?', ''), // удаляем "?" на всякий
isFuture: isFuture, isFuture: isFuture,
isNullable: isNullable, isNullable: isNullable,
@@ -207,11 +207,11 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
String _generateInjectionLine(_ParsedInjectField field) { String _generateInjectionLine(_ParsedInjectField field) {
final resolveMethod = field.isFuture final resolveMethod = field.isFuture
? (field.isNullable ? (field.isNullable
? 'tryResolveAsync<${field.coreType}>' ? 'tryResolveAsync<${field.coreType}>'
: 'resolveAsync<${field.coreType}>') : 'resolveAsync<${field.coreType}>')
: (field.isNullable : (field.isNullable
? 'tryResolve<${field.coreType}>' ? 'tryResolve<${field.coreType}>'
: 'resolve<${field.coreType}>'); : 'resolve<${field.coreType}>');
final openCall = (field.scopeName != null && field.scopeName!.isNotEmpty) final openCall = (field.scopeName != null && field.scopeName!.isNotEmpty)
? "CherryPick.openScope(scopeName: '${field.scopeName}')" ? "CherryPick.openScope(scopeName: '${field.scopeName}')"

View File

@@ -11,7 +11,7 @@
// limitations under the License. // limitations under the License.
// //
import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart'; import 'package:build/build.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;
@@ -79,12 +79,12 @@ class ModuleGenerator extends GeneratorForAnnotation<ann.module> {
/// ///
/// See file-level docs for usage and generated output example. /// See file-level docs for usage and generated output example.
@override @override
dynamic generateForAnnotatedElement( String generateForAnnotatedElement(
Element2 element, Element element,
ConstantReader annotation, ConstantReader annotation,
BuildStep buildStep, BuildStep buildStep,
) { ) {
if (element is! ClassElement2) { if (element is! ClassElement) {
throw InvalidGenerationSourceError( throw InvalidGenerationSourceError(
'@module() can only be applied to classes.', '@module() can only be applied to classes.',
element: element, element: element,

View File

@@ -12,7 +12,6 @@
// //
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'exceptions.dart'; import 'exceptions.dart';
import 'metadata_utils.dart'; import 'metadata_utils.dart';
@@ -53,10 +52,8 @@ class AnnotationValidator {
/// - Parameter validation for method arguments. /// - Parameter validation for method arguments.
/// ///
/// Throws [AnnotationValidationException] on any violation. /// Throws [AnnotationValidationException] on any violation.
static void validateMethodAnnotations(MethodElement2 method) { static void validateMethodAnnotations(MethodElement method) {
final annotations = _getAnnotationNames( final annotations = _getAnnotationNames(method.metadata);
method.firstFragment.metadata2.annotations,
);
_validateMutuallyExclusiveAnnotations(method, annotations); _validateMutuallyExclusiveAnnotations(method, annotations);
_validateAnnotationCombinations(method, annotations); _validateAnnotationCombinations(method, annotations);
@@ -71,10 +68,8 @@ class AnnotationValidator {
/// - Correct scope naming if present. /// - Correct scope naming if present.
/// ///
/// Throws [AnnotationValidationException] if checks fail. /// Throws [AnnotationValidationException] if checks fail.
static void validateFieldAnnotations(FieldElement2 field) { static void validateFieldAnnotations(FieldElement field) {
final annotations = _getAnnotationNames( final annotations = _getAnnotationNames(field.metadata);
field.firstFragment.metadata2.annotations,
);
_validateInjectFieldAnnotations(field, annotations); _validateInjectFieldAnnotations(field, annotations);
} }
@@ -87,10 +82,8 @@ class AnnotationValidator {
/// - Provides helpful context for error/warning reporting. /// - Provides helpful context for error/warning reporting.
/// ///
/// Throws [AnnotationValidationException] if checks fail. /// Throws [AnnotationValidationException] if checks fail.
static void validateClassAnnotations(ClassElement2 classElement) { static void validateClassAnnotations(ClassElement classElement) {
final annotations = _getAnnotationNames( final annotations = _getAnnotationNames(classElement.metadata);
classElement.firstFragment.metadata2.annotations,
);
_validateModuleClassAnnotations(classElement, annotations); _validateModuleClassAnnotations(classElement, annotations);
_validateInjectableClassAnnotations(classElement, annotations); _validateInjectableClassAnnotations(classElement, annotations);
@@ -111,7 +104,7 @@ class AnnotationValidator {
/// ///
/// For example, `@instance` and `@provide` cannot both be present. /// For example, `@instance` and `@provide` cannot both be present.
static void _validateMutuallyExclusiveAnnotations( static void _validateMutuallyExclusiveAnnotations(
MethodElement2 method, MethodElement method,
List<String> annotations, List<String> annotations,
) { ) {
// @instance and @provide are mutually exclusive // @instance and @provide are mutually exclusive
@@ -134,7 +127,7 @@ class AnnotationValidator {
/// - One of `@instance` or `@provide` must be present for a registration method /// - One of `@instance` or `@provide` must be present for a registration method
/// - Validates singleton usage /// - Validates singleton usage
static void _validateAnnotationCombinations( static void _validateAnnotationCombinations(
MethodElement2 method, MethodElement method,
List<String> annotations, List<String> annotations,
) { ) {
// @params can only be used with @provide // @params can only be used with @provide
@@ -172,7 +165,7 @@ class AnnotationValidator {
/// Singleton-specific method annotation checks. /// Singleton-specific method annotation checks.
static void _validateSingletonUsage( static void _validateSingletonUsage(
MethodElement2 method, MethodElement method,
List<String> annotations, List<String> annotations,
) { ) {
// Singleton with params might not make sense in some contexts // Singleton with params might not make sense in some contexts
@@ -188,17 +181,18 @@ class AnnotationValidator {
'Singleton methods cannot return void', 'Singleton methods cannot return void',
element: method, element: method,
suggestion: 'Remove @singleton annotation or change return type', suggestion: 'Remove @singleton annotation or change return type',
context: {'method_name': method.displayName, 'return_type': returnType}, context: {
'method_name': method.displayName,
'return_type': returnType,
},
); );
} }
} }
/// Validates extra requirements or syntactic rules for annotation arguments, like @named. /// Validates extra requirements or syntactic rules for annotation arguments, like @named.
static void _validateAnnotationParameters(MethodElement2 method) { static void _validateAnnotationParameters(MethodElement method) {
// Validate @named annotation parameters // Validate @named annotation parameters
final namedValue = MetadataUtils.getNamedValue( final namedValue = MetadataUtils.getNamedValue(method.metadata);
method.firstFragment.metadata2.annotations,
);
if (namedValue != null) { if (namedValue != null) {
if (namedValue.isEmpty) { if (namedValue.isEmpty) {
throw AnnotationValidationException( throw AnnotationValidationException(
@@ -228,10 +222,8 @@ class AnnotationValidator {
} }
// Validate method parameters for @params usage // Validate method parameters for @params usage
for (final param in method.formalParameters) { for (final param in method.parameters) {
final paramAnnotations = _getAnnotationNames( final paramAnnotations = _getAnnotationNames(param.metadata);
param.firstFragment.metadata2.annotations,
);
if (paramAnnotations.contains('params')) { if (paramAnnotations.contains('params')) {
_validateParamsParameter(param, method); _validateParamsParameter(param, method);
} }
@@ -240,9 +232,7 @@ class AnnotationValidator {
/// Checks that @params is used with compatible parameter type. /// Checks that @params is used with compatible parameter type.
static void _validateParamsParameter( static void _validateParamsParameter(
FormalParameterElement param, ParameterElement param, MethodElement method) {
MethodElement2 method,
) {
// @params parameter should typically be dynamic or Map<String, dynamic> // @params parameter should typically be dynamic or Map<String, dynamic>
final paramType = param.type.getDisplayString(); final paramType = param.type.getDisplayString();
if (paramType != 'dynamic' && if (paramType != 'dynamic' &&
@@ -266,7 +256,7 @@ class AnnotationValidator {
/// Checks field-level annotation for valid injectable fields. /// Checks field-level annotation for valid injectable fields.
static void _validateInjectFieldAnnotations( static void _validateInjectFieldAnnotations(
FieldElement2 field, FieldElement field,
List<String> annotations, List<String> annotations,
) { ) {
if (!annotations.contains('inject')) { if (!annotations.contains('inject')) {
@@ -280,12 +270,15 @@ class AnnotationValidator {
'Cannot inject void type', 'Cannot inject void type',
element: field, element: field,
suggestion: 'Use a concrete type instead of void', suggestion: 'Use a concrete type instead of void',
context: {'field_name': field.displayName, 'field_type': fieldType}, context: {
'field_name': field.displayName,
'field_type': fieldType,
},
); );
} }
// Validate scope annotation if present // Validate scope annotation if present
for (final meta in field.firstFragment.metadata2.annotations) { for (final meta in field.metadata) {
final obj = meta.computeConstantValue(); final obj = meta.computeConstantValue();
final type = obj?.type?.getDisplayString(); final type = obj?.type?.getDisplayString();
if (type == 'scope') { if (type == 'scope') {
@@ -297,7 +290,7 @@ class AnnotationValidator {
/// Checks @module usage: must have at least one DI method, each with DI-annotation. /// Checks @module usage: must have at least one DI method, each with DI-annotation.
static void _validateModuleClassAnnotations( static void _validateModuleClassAnnotations(
ClassElement2 classElement, ClassElement classElement,
List<String> annotations, List<String> annotations,
) { ) {
if (!annotations.contains('module')) { if (!annotations.contains('module')) {
@@ -305,9 +298,8 @@ class AnnotationValidator {
} }
// Check if class has public methods // Check if class has public methods
final publicMethods = classElement.methods2 final publicMethods =
.where((m) => m.isPublic) classElement.methods.where((m) => m.isPublic).toList();
.toList();
if (publicMethods.isEmpty) { if (publicMethods.isEmpty) {
throw AnnotationValidationException( throw AnnotationValidationException(
'Module class must have at least one public method', 'Module class must have at least one public method',
@@ -322,9 +314,7 @@ class AnnotationValidator {
// Validate that public methods have appropriate annotations // Validate that public methods have appropriate annotations
for (final method in publicMethods) { for (final method in publicMethods) {
final methodAnnotations = _getAnnotationNames( final methodAnnotations = _getAnnotationNames(method.metadata);
method.firstFragment.metadata2.annotations,
);
if (!methodAnnotations.contains('instance') && if (!methodAnnotations.contains('instance') &&
!methodAnnotations.contains('provide')) { !methodAnnotations.contains('provide')) {
throw AnnotationValidationException( throw AnnotationValidationException(
@@ -342,7 +332,7 @@ class AnnotationValidator {
/// Checks @injectable usage on classes and their fields. /// Checks @injectable usage on classes and their fields.
static void _validateInjectableClassAnnotations( static void _validateInjectableClassAnnotations(
ClassElement2 classElement, ClassElement classElement,
List<String> annotations, List<String> annotations,
) { ) {
if (!annotations.contains('injectable')) { if (!annotations.contains('injectable')) {
@@ -350,10 +340,8 @@ class AnnotationValidator {
} }
// Check if class has injectable fields // Check if class has injectable fields
final injectFields = classElement.fields2.where((f) { final injectFields = classElement.fields.where((f) {
final fieldAnnotations = _getAnnotationNames( final fieldAnnotations = _getAnnotationNames(f.metadata);
f.firstFragment.metadata2.annotations,
);
return fieldAnnotations.contains('inject'); return fieldAnnotations.contains('inject');
}).toList(); }).toList();

View File

@@ -11,7 +11,7 @@
// limitations under the License. // limitations under the License.
// //
import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/element.dart';
import 'bind_parameters_spec.dart'; import 'bind_parameters_spec.dart';
import 'metadata_utils.dart'; import 'metadata_utils.dart';
@@ -25,7 +25,7 @@ enum BindingType {
instance, instance,
/// Provider/factory function (@provide). /// Provider/factory function (@provide).
provide, provide;
} }
/// --------------------------------------------------------------------------- /// ---------------------------------------------------------------------------
@@ -155,8 +155,7 @@ class BindSpec {
switch (bindingType) { switch (bindingType) {
case BindingType.instance: case BindingType.instance:
throw StateError( throw StateError(
'Internal error: _generateWithParamsProvideClause called for @instance binding with @params.', 'Internal error: _generateWithParamsProvideClause called for @instance binding with @params.');
);
//return isAsyncInstance //return isAsyncInstance
// ? '.toInstanceAsync(($fnArgs) => $methodName($fnArgs))' // ? '.toInstanceAsync(($fnArgs) => $methodName($fnArgs))'
// : '.toInstance(($fnArgs) => $methodName($fnArgs))'; // : '.toInstance(($fnArgs) => $methodName($fnArgs))';
@@ -190,24 +189,20 @@ class BindSpec {
case BindingType.provide: case BindingType.provide:
if (isAsyncProvide) { if (isAsyncProvide) {
if (needsMultiline) { if (needsMultiline) {
final lambdaIndent = (isSingleton || named != null) final lambdaIndent =
? indent + 6 (isSingleton || named != null) ? indent + 6 : indent + 2;
: indent + 2; final closingIndent =
final closingIndent = (isSingleton || named != null) (isSingleton || named != null) ? indent + 4 : indent;
? indent + 4
: indent;
return '.toProvideAsync(\n${' ' * lambdaIndent}() => $methodName($argsStr),\n${' ' * closingIndent})'; return '.toProvideAsync(\n${' ' * lambdaIndent}() => $methodName($argsStr),\n${' ' * closingIndent})';
} else { } else {
return '.toProvideAsync(() => $methodName($argsStr))'; return '.toProvideAsync(() => $methodName($argsStr))';
} }
} else { } else {
if (needsMultiline) { if (needsMultiline) {
final lambdaIndent = (isSingleton || named != null) final lambdaIndent =
? indent + 6 (isSingleton || named != null) ? indent + 6 : indent + 2;
: indent + 2; final closingIndent =
final closingIndent = (isSingleton || named != null) (isSingleton || named != null) ? indent + 4 : indent;
? indent + 4
: indent;
return '.toProvide(\n${' ' * lambdaIndent}() => $methodName($argsStr),\n${' ' * closingIndent})'; return '.toProvide(\n${' ' * lambdaIndent}() => $methodName($argsStr),\n${' ' * closingIndent})';
} else { } else {
return '.toProvide(() => $methodName($argsStr))'; return '.toProvide(() => $methodName($argsStr))';
@@ -251,7 +246,7 @@ class BindSpec {
/// print(bindSpec.returnType); // e.g., 'Logger' /// print(bindSpec.returnType); // e.g., 'Logger'
/// ``` /// ```
/// Throws [AnnotationValidationException] or [CodeGenerationException] if invalid. /// Throws [AnnotationValidationException] or [CodeGenerationException] if invalid.
static BindSpec fromMethod(MethodElement2 method) { static BindSpec fromMethod(MethodElement method) {
try { try {
// Validate method annotations // Validate method annotations
AnnotationValidator.validateMethodAnnotations(method); AnnotationValidator.validateMethodAnnotations(method);
@@ -259,44 +254,28 @@ class BindSpec {
// Parse return type using improved type parser // Parse return type using improved type parser
final parsedReturnType = TypeParser.parseType(method.returnType, method); final parsedReturnType = TypeParser.parseType(method.returnType, method);
final methodName = method.firstFragment.name2 ?? ''; final methodName = method.displayName;
// Check for @singleton annotation. // Check for @singleton annotation.
final isSingleton = MetadataUtils.anyMeta( final isSingleton = MetadataUtils.anyMeta(method.metadata, 'singleton');
method.firstFragment.metadata2.annotations,
'singleton',
);
// Get @named value if present. // Get @named value if present.
final named = MetadataUtils.getNamedValue( final named = MetadataUtils.getNamedValue(method.metadata);
method.firstFragment.metadata2.annotations,
);
// Parse each method parameter. // Parse each method parameter.
final params = <BindParameterSpec>[]; final params = <BindParameterSpec>[];
bool hasParams = false; bool hasParams = false;
for (final p in method.formalParameters) { for (final p in method.parameters) {
final typeStr = p.type.getDisplayString(); final typeStr = p.type.getDisplayString();
final paramNamed = MetadataUtils.getNamedValue( final paramNamed = MetadataUtils.getNamedValue(p.metadata);
p.firstFragment.metadata2.annotations, final isParams = MetadataUtils.anyMeta(p.metadata, 'params');
);
final isParams = MetadataUtils.anyMeta(
p.firstFragment.metadata2.annotations,
'params',
);
if (isParams) hasParams = true; if (isParams) hasParams = true;
params.add(BindParameterSpec(typeStr, paramNamed, isParams: isParams)); params.add(BindParameterSpec(typeStr, paramNamed, isParams: isParams));
} }
// Determine bindingType: @instance or @provide. // Determine bindingType: @instance or @provide.
final hasInstance = MetadataUtils.anyMeta( final hasInstance = MetadataUtils.anyMeta(method.metadata, 'instance');
method.firstFragment.metadata2.annotations, final hasProvide = MetadataUtils.anyMeta(method.metadata, 'provide');
'instance',
);
final hasProvide = MetadataUtils.anyMeta(
method.firstFragment.metadata2.annotations,
'provide',
);
if (!hasInstance && !hasProvide) { if (!hasInstance && !hasProvide) {
throw AnnotationValidationException( throw AnnotationValidationException(
@@ -311,9 +290,8 @@ class BindSpec {
); );
} }
final bindingType = hasInstance final bindingType =
? BindingType.instance hasInstance ? BindingType.instance : BindingType.provide;
: BindingType.provide;
// PROHIBIT @params with @instance bindings! // PROHIBIT @params with @instance bindings!
if (bindingType == BindingType.instance && hasParams) { if (bindingType == BindingType.instance && hasParams) {

View File

@@ -11,7 +11,7 @@
// limitations under the License. // limitations under the License.
// //
import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:source_gen/source_gen.dart'; import 'package:source_gen/source_gen.dart';
/// --------------------------------------------------------------------------- /// ---------------------------------------------------------------------------
@@ -48,21 +48,21 @@ class CherryPickGeneratorException extends InvalidGenerationSourceError {
CherryPickGeneratorException( CherryPickGeneratorException(
String message, { String message, {
required Element2 element, required Element element,
required this.category, required this.category,
this.suggestion, this.suggestion,
this.context, this.context,
}) : super( }) : super(
_formatMessage(message, category, suggestion, context, element), _formatMessage(message, category, suggestion, context, element),
element: element, element: element,
); );
static String _formatMessage( static String _formatMessage(
String message, String message,
String category, String category,
String? suggestion, String? suggestion,
Map<String, dynamic>? context, Map<String, dynamic>? context,
Element2 element, Element element,
) { ) {
final buffer = StringBuffer(); final buffer = StringBuffer();
@@ -74,9 +74,7 @@ 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: ${element.source?.fullName ?? 'unknown'}');
' 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 { try {

View File

@@ -12,7 +12,6 @@
// //
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'bind_spec.dart'; import 'bind_spec.dart';
/// --------------------------------------------------------------------------- /// ---------------------------------------------------------------------------
@@ -76,11 +75,14 @@ class GeneratedClass {
/// final gen = GeneratedClass.fromClassElement(classElement); /// final gen = GeneratedClass.fromClassElement(classElement);
/// print(gen.generatedClassName); // e.g. $AppModule /// print(gen.generatedClassName); // e.g. $AppModule
/// ``` /// ```
static GeneratedClass fromClassElement(ClassElement2 element) { static GeneratedClass fromClassElement(ClassElement element) {
final className = element.firstFragment.name2 ?? ''; final className = element.displayName;
// Generated class name with '$' prefix (standard for generated Dart code).
final generatedClassName = r'$' + className; final generatedClassName = r'$' + className;
final sourceFile = element.firstFragment.libraryFragment.source.shortName; // Get source file name
final binds = element.methods2 final sourceFile = element.source.shortName;
// Collect bindings for all non-abstract methods.
final binds = element.methods
.where((m) => !m.isAbstract) .where((m) => !m.isAbstract)
.map(BindSpec.fromMethod) .map(BindSpec.fromMethod)
.toList(); .toList();

View File

@@ -41,16 +41,14 @@ class MetadataUtils {
/// bool isSingleton = MetadataUtils.anyMeta(myMethod.metadata, 'singleton'); /// bool isSingleton = MetadataUtils.anyMeta(myMethod.metadata, 'singleton');
/// ``` /// ```
static bool anyMeta(List<ElementAnnotation> meta, String typeName) { static bool anyMeta(List<ElementAnnotation> meta, String typeName) {
return meta.any( return meta.any((m) =>
(m) => m
m .computeConstantValue()
.computeConstantValue() ?.type
?.type ?.getDisplayString()
?.getDisplayString() .toLowerCase()
.toLowerCase() .contains(typeName.toLowerCase()) ??
.contains(typeName.toLowerCase()) ?? false);
false,
);
} }
/// Extracts the string value from a `@named('value')` annotation if present in [meta]. /// Extracts the string value from a `@named('value')` annotation if present in [meta].

View File

@@ -11,7 +11,7 @@
// limitations under the License. // limitations under the License.
// //
import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type.dart';
import 'exceptions.dart'; import 'exceptions.dart';
@@ -45,7 +45,7 @@ class TypeParser {
/// final parsed = TypeParser.parseType(field.type, field); /// final parsed = TypeParser.parseType(field.type, field);
/// if (parsed.isNullable) print('Field is nullable'); /// if (parsed.isNullable) print('Field is nullable');
/// ``` /// ```
static ParsedType parseType(DartType dartType, Element2 context) { static ParsedType parseType(DartType dartType, Element context) {
try { try {
return _parseTypeInternal(dartType, context); return _parseTypeInternal(dartType, context);
} catch (e) { } catch (e) {
@@ -61,7 +61,7 @@ class TypeParser {
} }
} }
static ParsedType _parseTypeInternal(DartType dartType, Element2 context) { static ParsedType _parseTypeInternal(DartType dartType, Element context) {
final displayString = dartType.getDisplayString(); final displayString = dartType.getDisplayString();
final isNullable = dartType.nullabilitySuffix == NullabilitySuffix.question; final isNullable = dartType.nullabilitySuffix == NullabilitySuffix.question;
@@ -87,10 +87,7 @@ class TypeParser {
} }
static ParsedType _parseFutureType( static ParsedType _parseFutureType(
DartType dartType, DartType dartType, Element context, bool isNullable) {
Element2 context,
bool isNullable,
) {
if (dartType is! ParameterizedType || dartType.typeArguments.isEmpty) { if (dartType is! ParameterizedType || dartType.typeArguments.isEmpty) {
throw TypeParsingException( throw TypeParsingException(
'Future type must have a type argument', 'Future type must have a type argument',
@@ -115,10 +112,7 @@ class TypeParser {
} }
static ParsedType _parseGenericType( static ParsedType _parseGenericType(
ParameterizedType dartType, ParameterizedType dartType, Element context, bool isNullable) {
Element2 context,
bool isNullable,
) {
final typeArguments = dartType.typeArguments final typeArguments = dartType.typeArguments
.map((arg) => _parseTypeInternal(arg, context)) .map((arg) => _parseTypeInternal(arg, context))
.toList(); .toList();
@@ -144,7 +138,7 @@ class TypeParser {
/// final parsed = TypeParser.parseType(field.type, field); /// final parsed = TypeParser.parseType(field.type, field);
/// TypeParser.validateInjectableType(parsed, field); /// TypeParser.validateInjectableType(parsed, field);
/// ``` /// ```
static void validateInjectableType(ParsedType parsedType, Element2 context) { static void validateInjectableType(ParsedType parsedType, Element context) {
// Check for void type // Check for void type
if (parsedType.coreType == 'void') { if (parsedType.coreType == 'void') {
throw TypeParsingException( throw TypeParsingException(

View File

@@ -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: 3.0.2-dev.0 version: 3.0.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
@@ -15,20 +15,20 @@ topics:
- inversion-of-control - inversion-of-control
environment: environment:
sdk: ">=3.8.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"
# Add regular dependencies here. # Add regular dependencies here.
dependencies: dependencies:
cherrypick_annotations: ^3.0.2-dev.0 cherrypick_annotations: ^3.0.1
analyzer: ">=7.5.9 <8.0.0" analyzer: ^7.7.1
dart_style: ^3.0.0 dart_style: ^3.0.0
build: ^3.0.0 build: ^2.4.1
source_gen: ^3.1.0 source_gen: ^2.0.0
collection: ^1.18.0 collection: ^1.18.0
dev_dependencies: dev_dependencies:
lints: ^6.0.0 lints: ^5.1.1
mockito: ^5.4.5 mockito: ^5.4.5
test: ^1.25.8 test: ^1.25.8
build_test: ^3.0.0 build_test: ^2.1.7
build_runner: ^2.5.0 build_runner: ^2.4.13

View File

@@ -480,10 +480,9 @@ void notAClass() {}
); );
}); });
test( test('should generate empty mixin for class without @inject fields',
'should generate empty mixin for class without @inject fields', () async {
() async { const input = '''
const input = '''
import 'package:cherrypick_annotations/cherrypick_annotations.dart'; import 'package:cherrypick_annotations/cherrypick_annotations.dart';
part 'test_widget.inject.cherrypick.g.dart'; part 'test_widget.inject.cherrypick.g.dart';
@@ -495,7 +494,7 @@ class TestWidget {
} }
'''; ''';
const expectedOutput = ''' const expectedOutput = '''
// dart format width=80 // dart format width=80
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
@@ -510,9 +509,8 @@ mixin _\$TestWidget {
} }
'''; ''';
await _testGeneration(input, expectedOutput); await _testGeneration(input, expectedOutput);
}, });
);
}); });
group('Edge Cases', () { group('Edge Cases', () {
@@ -595,8 +593,12 @@ mixin _\$TestWidget {
Future<void> _testGeneration(String input, String expectedOutput) async { Future<void> _testGeneration(String input, String expectedOutput) async {
await testBuilder( await testBuilder(
injectBuilder(BuilderOptions.empty), injectBuilder(BuilderOptions.empty),
{'a|lib/test_widget.dart': input}, {
outputs: {'a|lib/test_widget.inject.cherrypick.g.dart': expectedOutput}, 'a|lib/test_widget.dart': input,
readerWriter: TestReaderWriter(), },
outputs: {
'a|lib/test_widget.inject.cherrypick.g.dart': expectedOutput,
},
reader: await PackageAssetReader.currentIsolate(),
); );
} }

View File

@@ -590,10 +590,9 @@ void notAClass() {}
); );
}); });
test( test('should throw error for method without @instance or @provide',
'should throw error for method without @instance or @provide', () async {
() async { const input = '''
const input = '''
import 'package:cherrypick_annotations/cherrypick_annotations.dart'; import 'package:cherrypick_annotations/cherrypick_annotations.dart';
import 'package:cherrypick/cherrypick.dart'; import 'package:cherrypick/cherrypick.dart';
@@ -605,12 +604,11 @@ abstract class TestModule extends Module {
} }
'''; ''';
await expectLater( await expectLater(
() => _testGeneration(input, ''), () => _testGeneration(input, ''),
throwsA(isA<InvalidGenerationSourceError>()), throwsA(isA<InvalidGenerationSourceError>()),
); );
}, });
);
test('should throw error for @params with @instance', () async { test('should throw error for @params with @instance', () async {
const input = ''' const input = '''
@@ -639,8 +637,12 @@ abstract class TestModule extends Module {
Future<void> _testGeneration(String input, String expectedOutput) async { Future<void> _testGeneration(String input, String expectedOutput) async {
await testBuilder( await testBuilder(
moduleBuilder(BuilderOptions.empty), moduleBuilder(BuilderOptions.empty),
{'a|lib/test_module.dart': input}, {
outputs: {'a|lib/test_module.module.cherrypick.g.dart': expectedOutput}, 'a|lib/test_module.dart': input,
readerWriter: TestReaderWriter(), },
outputs: {
'a|lib/test_module.module.cherrypick.g.dart': expectedOutput,
},
reader: await PackageAssetReader.currentIsolate(),
); );
} }

View File

@@ -1,6 +1,7 @@
import 'package:analyzer/dart/element/element2.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source.dart';
import 'package:cherrypick_generator/src/type_parser.dart'; import 'package:cherrypick_generator/src/type_parser.dart';
import 'package:cherrypick_generator/src/exceptions.dart'; import 'package:cherrypick_generator/src/exceptions.dart';
@@ -41,9 +42,7 @@ void main() {
expect( expect(
() => TypeParser.validateInjectableType( () => TypeParser.validateInjectableType(
parsedType, parsedType, _createMockElement()),
_createMockElement(),
),
throwsA(isA<TypeParsingException>()), throwsA(isA<TypeParsingException>()),
); );
}); });
@@ -60,9 +59,7 @@ void main() {
expect( expect(
() => TypeParser.validateInjectableType( () => TypeParser.validateInjectableType(
parsedType, parsedType, _createMockElement()),
_createMockElement(),
),
throwsA(isA<TypeParsingException>()), throwsA(isA<TypeParsingException>()),
); );
}); });
@@ -79,9 +76,7 @@ void main() {
expect( expect(
() => TypeParser.validateInjectableType( () => TypeParser.validateInjectableType(
parsedType, parsedType, _createMockElement()),
_createMockElement(),
),
returnsNormally, returnsNormally,
); );
}); });
@@ -164,21 +159,19 @@ void main() {
expect(parsedType.resolveMethodName, equals('resolveAsync')); expect(parsedType.resolveMethodName, equals('resolveAsync'));
}); });
test( test('should return correct resolveMethodName for nullable async types',
'should return correct resolveMethodName for nullable async types', () {
() { final parsedType = ParsedType(
final parsedType = ParsedType( displayString: 'Future<String?>',
displayString: 'Future<String?>', coreType: 'String',
coreType: 'String', isNullable: true,
isNullable: true, isFuture: true,
isFuture: true, isGeneric: false,
isGeneric: false, typeArguments: [],
typeArguments: [], );
);
expect(parsedType.resolveMethodName, equals('tryResolveAsync')); expect(parsedType.resolveMethodName, equals('tryResolveAsync'));
}, });
);
test('should implement equality correctly', () { test('should implement equality correctly', () {
final parsedType1 = ParsedType( final parsedType1 = ParsedType(
@@ -223,19 +216,19 @@ void main() {
} }
// Mock element for testing // Mock element for testing
Element2 _createMockElement() { Element _createMockElement() {
return _MockElement(); return _MockElement();
} }
class _MockElement implements Element2 { class _MockElement implements Element {
@override @override
String get displayName => 'MockElement'; String get displayName => 'MockElement';
//@override @override
//String get name => 'MockElement'; String get name => 'MockElement';
//
//@override @override
//Source? get source => null; Source? get source => null;
@override @override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

View File

@@ -9,7 +9,11 @@ void main() {
// Создаем модуль, который будет предоставлять UseCase // Создаем модуль, который будет предоставлять UseCase
]); ]);
runApp(const CherryPickProvider(child: MyApp())); runApp(
const CherryPickProvider(
child: MyApp(),
),
);
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@@ -17,6 +21,10 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CherryPickProvider(child: MaterialApp(home: MyHomePage())); return CherryPickProvider(
child: MaterialApp(
home: MyHomePage(),
),
);
} }
} }

View File

@@ -11,8 +11,12 @@ class MyHomePage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
//_inject(context); // Make sure this function is called in context //_inject(context); // Make sure this function is called in context
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Example App')), appBar: AppBar(
body: Center(child: Text(useCase.fetchData())), title: const Text('Example App'),
),
body: Center(
child: Text(useCase.fetchData()),
),
); );
} }
} }

View File

@@ -45,18 +45,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: ce76b1d48875e3233fde17717c23d1f60a91cc631597e49a400c89b475395b1d sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "2.4.2"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.1.2"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
@@ -69,26 +69,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
sha256: d1d57f7807debd7349b4726a19fd32ec8bc177c71ad0febf91a20f84cd2d4b46 sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "2.4.4"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: b24597fceb695969d47025c958f3837f9f0122e237c6a22cb082a5ac66c3ca30 sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.7.1" version: "2.4.15"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "066dda7f73d8eb48ba630a55acb50c4a84a2e6b453b1cb4567f581729e794f7b" sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.3.1" version: "8.0.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@@ -117,38 +117,38 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.3"
cherrypick: cherrypick:
dependency: "direct main" dependency: "direct main"
description: description:
path: "../../cherrypick" path: "../../cherrypick"
relative: true relative: true
source: path source: path
version: "3.0.0" version: "3.0.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: "3.0.0" version: "3.0.1"
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: "3.0.0" version: "3.0.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: "3.0.0" version: "3.0.1"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@@ -201,10 +201,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.0.1"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@@ -238,10 +238,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "5.0.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -271,6 +271,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.3.2"
http:
dependency: transitive
description:
name: http
sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007
url: "https://pub.dev"
source: hosted
version: "1.5.0"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
@@ -295,6 +303,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "1.0.5"
js:
dependency: transitive
description:
name: js
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.7.1"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
@@ -331,10 +347,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "5.1.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@@ -440,10 +456,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: "7b19d6ba131c6eb98bfcbf8d56c1a7002eba438af2e7ae6f8398b2b0f4f381e3" sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "2.0.0"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@@ -573,5 +589,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.8.0 <4.0.0" dart: ">=3.7.0-0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54" flutter: ">=3.18.0-18.0.pre.54"

View File

@@ -5,7 +5,7 @@ publish_to: 'none'
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=3.8.0 <4.0.0" sdk: ">=3.5.2 <4.0.0"
dependencies: dependencies:
@@ -25,11 +25,11 @@ dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^6.0.0 flutter_lints: ^5.0.0
cherrypick_generator: cherrypick_generator:
path: ../../cherrypick_generator path: ../../cherrypick_generator
build_runner: ^2.5.0 build_runner: ^2.4.15
# 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

View File

@@ -4,7 +4,7 @@ part 'post_model.freezed.dart';
part 'post_model.g.dart'; part 'post_model.g.dart';
@freezed @freezed
abstract class PostModel with _$PostModel { class PostModel with _$PostModel {
const factory PostModel({ const factory PostModel({
required int id, required int id,
required String title, required String title,

View File

@@ -12,9 +12,9 @@ class PostRepositoryImpl implements PostRepository {
Future<Either<Exception, List<Post>>> getPosts() async { Future<Either<Exception, List<Post>>> getPosts() async {
try { try {
final posts = await api.getPosts(); final posts = await api.getPosts();
return Right( return Right(posts
posts.map((e) => Post(id: e.id, title: e.title, body: e.body)).toList(), .map((e) => Post(id: e.id, title: e.title, body: e.body))
); .toList());
} catch (e) { } catch (e) {
return Left(Exception(e.toString())); return Left(Exception(e.toString()));
} }

View File

@@ -15,17 +15,16 @@ abstract class AppModule extends Module {
@provide() @provide()
@singleton() @singleton()
TalkerDioLoggerSettings talkerDioLoggerSettings() => TalkerDioLoggerSettings( TalkerDioLoggerSettings talkerDioLoggerSettings() => TalkerDioLoggerSettings(
printRequestHeaders: true, printRequestHeaders: true,
printResponseHeaders: true, printResponseHeaders: true,
printResponseMessage: true, printResponseMessage: true,
); );
@provide() @provide()
@singleton() @singleton()
TalkerDioLogger talkerDioLogger( TalkerDioLogger talkerDioLogger(
Talker talker, Talker talker, TalkerDioLoggerSettings settings) =>
TalkerDioLoggerSettings settings, TalkerDioLogger(talker: talker, settings: settings);
) => TalkerDioLogger(talker: talker, settings: settings);
@instance() @instance()
int timeout() => 1000; int timeout() => 1000;
@@ -76,14 +75,12 @@ abstract class AppModule extends Module {
@provide() @provide()
@named('TestProvideWithParams1') @named('TestProvideWithParams1')
String testProvideWithParams1( String testProvideWithParams1(
@named('baseUrl') String baseUrl, @named('baseUrl') String baseUrl, @params() dynamic params) =>
@params() dynamic params, "hello $params";
) => "hello $params";
@provide() @provide()
@named('TestProvideAsyncWithParams1') @named('TestProvideAsyncWithParams1')
Future<String> testProvideAsyncWithParams1( Future<String> testProvideAsyncWithParams1(
@named('baseUrl') String baseUrl, @named('baseUrl') String baseUrl, @params() dynamic params) async =>
@params() dynamic params, "hello $params";
) async => "hello $params";
} }

View File

@@ -3,7 +3,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'post.freezed.dart'; part 'post.freezed.dart';
@freezed @freezed
abstract class Post with _$Post { class Post with _$Post {
const factory Post({ const factory Post({
required int id, required int id,
required String title, required String title,

View File

@@ -23,10 +23,10 @@ void main() {
} }
// Используем safe root scope для гарантии защиты // Используем safe root scope для гарантии защиты
CherryPick.openRootScope().installModules([ CherryPick.openRootScope()
CoreModule(talker: talker), .installModules([CoreModule(talker: talker), $AppModule()]);
$AppModule(),
]);
runApp(MyApp(talker: talker)); runApp(MyApp(
talker: talker,
));
} }

View File

@@ -12,7 +12,10 @@ class PostDetailsPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('Post #${post.id}')), appBar: AppBar(title: Text('Post #${post.id}')),
body: Padding(padding: const EdgeInsets.all(16), child: Text(post.body)), body: Padding(
padding: const EdgeInsets.all(16),
child: Text(post.body),
),
); );
} }
} }

View File

@@ -38,9 +38,8 @@ class PostsPage extends StatelessWidget {
title: Text(posts[i].title), title: Text(posts[i].title),
subtitle: Text(posts[i].body), subtitle: Text(posts[i].body),
onTap: () { onTap: () {
AutoRouter.of( AutoRouter.of(context)
context, .push(PostDetailsRoute(post: posts[i]));
).push(PostDetailsRoute(post: posts[i]));
}, },
), ),
), ),

View File

@@ -5,8 +5,8 @@ import 'app_router.gr.dart';
class AppRouter extends RootStackRouter { 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),
AutoRoute(page: PostDetailsRoute.page), AutoRoute(page: PostDetailsRoute.page),
AutoRoute(page: LogsRoute.page), AutoRoute(page: LogsRoute.page),
]; ];
} }

View File

@@ -53,18 +53,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: auto_route name: auto_route
sha256: c820e918863a03544aac68eaf61e17c8a6126b663d7cad24a8fd3657a1e6be61 sha256: b8c036fa613a98a759cf0fdcba26e62f4985dcbff01a5e760ab411e8554bbaf0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.1.2" version: "10.1.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: ed4b65e85b4b2b00b06ef1e44c8623985c52c32d05d72147e3201257aa70a115 sha256: "8e622d26dc6be4bf496d47969e3e9ba555c3abcf2290da6abfa43cbd4f57fa52"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.2.4" version: "10.0.1"
bloc: bloc:
dependency: transitive dependency: transitive
description: description:
@@ -85,18 +85,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: ce76b1d48875e3233fde17717c23d1f60a91cc631597e49a400c89b475395b1d sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "2.4.2"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.1.2"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
@@ -109,26 +109,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
sha256: d1d57f7807debd7349b4726a19fd32ec8bc177c71ad0febf91a20f84cd2d4b46 sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "2.4.4"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: b24597fceb695969d47025c958f3837f9f0122e237c6a22cb082a5ac66c3ca30 sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.7.1" version: "2.4.15"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "066dda7f73d8eb48ba630a55acb50c4a84a2e6b453b1cb4567f581729e794f7b" sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.3.1" version: "8.0.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@@ -165,47 +165,39 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.3"
cherrypick: cherrypick:
dependency: "direct main" dependency: "direct main"
description: description:
path: "../../cherrypick" path: "../../cherrypick"
relative: true relative: true
source: path source: path
version: "3.0.0" version: "3.0.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: "3.0.0" version: "3.0.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: "3.0.0" version: "3.0.1"
cli_config:
dependency: transitive
description:
name: cli_config
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
url: "https://pub.dev"
source: hosted
version: "0.2.0"
cli_launcher: cli_launcher:
dependency: transitive dependency: transitive
description: description:
name: cli_launcher name: cli_launcher
sha256: "17d2744fb9a254c49ec8eda582536abe714ea0131533e24389843a4256f82eac" sha256: "67d89e0a1c07b103d1253f6b953a43d3f502ee36805c8cfc21196282c9ddf177"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.2+1" version: "0.3.2"
cli_util: cli_util:
dependency: transitive dependency: transitive
description: description:
@@ -242,10 +234,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: conventional_commit name: conventional_commit
sha256: c40b1b449ce2a63fa2ce852f35e3890b1e182f5951819934c0e4a66254bc0dc3 sha256: fad254feb6fb8eace2be18855176b0a4b97e0d50e416ff0fe590d5ba83735d34
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.1+1" version: "0.6.1"
convert: convert:
dependency: transitive dependency: transitive
description: description:
@@ -254,14 +246,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
url: "https://pub.dev"
source: hosted
version: "1.15.0"
cross_file: cross_file:
dependency: transitive dependency: transitive
description: description:
@@ -290,10 +274,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.0.1"
dartz: dartz:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -330,10 +314,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.3"
file: file:
dependency: transitive dependency: transitive
description: description:
@@ -367,10 +351,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "5.0.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -385,18 +369,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: freezed name: freezed
sha256: da32f8ba8cfcd4ec71d9decc8cbf28bd2c31b5283d9887eb51eb4a0659d8110c sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.0" version: "2.5.8"
freezed_annotation: freezed_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
name: freezed_annotation name: freezed_annotation
sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "2.4.4"
frontend_server_client: frontend_server_client:
dependency: transitive dependency: transitive
description: description:
@@ -429,14 +413,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.4" version: "5.3.4"
hotreloader:
dependency: transitive
description:
name: hotreloader
sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b
url: "https://pub.dev"
source: hosted
version: "4.3.0"
http: http:
dependency: transitive dependency: transitive
description: description:
@@ -461,6 +437,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.2" version: "4.1.2"
intl:
dependency: transitive
description:
name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.19.0"
io: io:
dependency: transitive dependency: transitive
description: description:
@@ -473,12 +457,12 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: js name: js
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.2" version: "0.7.1"
json_annotation: json_annotation:
dependency: "direct main" dependency: transitive
description: description:
name: json_annotation name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
@@ -489,10 +473,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
sha256: "33a040668b31b320aafa4822b7b1e177e163fc3c1e835c6750319d4ab23aa6fe" sha256: c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.11.1" version: "6.9.5"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@@ -517,22 +501,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
lean_builder:
dependency: transitive
description:
name: lean_builder
sha256: "3d3a04c9dda8ced6b2a48d23aaf98ef5aa32f68f9c62da1b6c6d45bf03aa8164"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
lints: lints:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "5.1.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@@ -561,10 +537,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: melos name: melos
sha256: "4280dc46bd5b741887cce1e67e5c1a6aaf3c22310035cf5bd33dceeeda62ed22" sha256: "3f3ab3f902843d1e5a1b1a4dd39a4aca8ba1056f2d32fd8995210fa2843f646f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.3" version: "6.3.2"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@@ -597,14 +573,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@@ -633,18 +601,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.18" version: "2.2.17"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.4.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@@ -669,6 +637,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@@ -713,10 +689,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: protobuf name: protobuf
sha256: de9c9eb2c33f8e933a42932fe1dc504800ca45ebc3d673e6ed7f39754ee4053e sha256: "579fe5557eae58e3adca2e999e38f02441d8aa908703854a9e0a0f47fa857731"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.0" version: "4.1.0"
provider: provider:
dependency: transitive dependency: transitive
description: description:
@@ -737,10 +713,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pub_updater name: pub_updater
sha256: "739a0161d73a6974c0675b864fb0cf5147305f7b077b7f03a58fa7a9ab3e7e7d" sha256: "54e8dc865349059ebe7f163d6acce7c89eb958b8047e6d6e80ce93b13d7c9e60"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.4.0"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
@@ -753,18 +729,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: retrofit name: retrofit
sha256: "699cf44ec6c7fc7d248740932eca75d334e36bdafe0a8b3e9ff93100591c8a25" sha256: "84d70114a5b6bae5f4c1302335f9cb610ebeb1b02023d5e7e87697aaff52926a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.2" version: "4.6.0"
retrofit_generator: retrofit_generator:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: retrofit_generator name: retrofit_generator
sha256: "4a2ac0364eb7d5975f71450dfd553b1591ecffad96438a01ce88494a266bceb4" sha256: e48c5a7ac362621b74976c64c540500dc7a54b8b5b074616a96a4854a2e5bb5b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.5" version: "9.6.0"
share_plus: share_plus:
dependency: transitive dependency: transitive
description: description:
@@ -789,22 +765,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.2" version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@@ -822,34 +782,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: "7b19d6ba131c6eb98bfcbf8d56c1a7002eba438af2e7ae6f8398b2b0f4f381e3" sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "2.0.0"
source_helper: source_helper:
dependency: transitive dependency: transitive
description: description:
name: source_helper name: source_helper
sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" sha256: a447acb083d3a5ef17f983dd36201aeea33fedadb3228fa831f2f0c92f0f3aca
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.8" version: "1.3.7"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
url: "https://pub.dev"
source: hosted
version: "0.10.13"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@@ -920,7 +864,7 @@ packages:
path: "../../talker_cherrypick_logger" path: "../../talker_cherrypick_logger"
relative: true relative: true
source: path source: path
version: "3.0.0" version: "3.0.1"
talker_dio_logger: talker_dio_logger:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -953,14 +897,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
test:
dependency: transitive
description:
name: test
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
url: "https://pub.dev"
source: hosted
version: "1.25.15"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
@@ -969,14 +905,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.4" version: "0.7.4"
test_core:
dependency: transitive
description:
name: test_core
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
url: "https://pub.dev"
source: hosted
version: "0.6.8"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@@ -1081,22 +1009,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.3"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.14.0" version: "5.10.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@@ -1105,14 +1025,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
xxh3: xml:
dependency: transitive dependency: transitive
description: description:
name: xxh3 name: xml
sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916" sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "6.5.0"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
@@ -1130,5 +1050,5 @@ packages:
source: hosted source: hosted
version: "2.2.2" version: "2.2.2"
sdks: sdks:
dart: ">=3.8.0 <4.0.0" dart: ">=3.7.0-0 <4.0.0"
flutter: ">=3.29.0" flutter: ">=3.27.0"

View File

@@ -5,20 +5,21 @@ publish_to: 'none'
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=3.8.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
cherrypick: any cherrypick:
cherrypick_annotations: ^3.0.2-dev.0 path: ../../cherrypick
cherrypick_annotations:
path: ../../cherrypick_annotations
dio: ^5.4.0 dio: ^5.4.0
retrofit: ^4.0.3 retrofit: ^4.0.3
freezed_annotation: ^3.0.0 freezed_annotation: ^2.4.4
json_annotation: ^4.9.0
dartz: ^0.10.1 dartz: ^0.10.1
flutter_bloc: ^9.1.1 flutter_bloc: ^9.1.1
auto_route: ^10.1.0+1 auto_route: ^10.1.0+1
@@ -27,23 +28,25 @@ 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:
path: ../../talker_cherrypick_logger
talker_dio_logger: ^5.0.0 talker_dio_logger: ^5.0.0
talker_bloc_logger: ^5.0.0 talker_bloc_logger: ^5.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^6.0.0 flutter_lints: ^5.0.0
build_runner: ^2.5.0 build_runner: 2.4.15
cherrypick_generator: ^3.0.2-dev.0 cherrypick_generator:
path: ../../cherrypick_generator
json_serializable: ^6.9.0 json_serializable: ^6.9.0
retrofit_generator: ^10.0.5 retrofit_generator: ^9.1.5
auto_route_generator: ^10.0.1 auto_route_generator: ^10.0.1
freezed: ^3.0.0 freezed: ^2.5.8
melos: ^6.3.2 melos: ^6.3.2
flutter: flutter:

View File

@@ -16,8 +16,7 @@ scripts:
clean_all: clean_all:
run: | run: |
melos clean melos clean
melos exec -- rm -rf lib/**.g.dart lib/**/**.g.dart lib/generated/ melos exec -- rm -rf lib/**.g.dart lib/generated/
melos exec -- rm -rf .dart_tool build pubspec_overrides.yaml
description: | description: |
Очищает build артефакты flutter и сгенерированный код во всех пакетах. Очищает build артефакты flutter и сгенерированный код во всех пакетах.