import 'dart:async'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann; class InjectGenerator extends GeneratorForAnnotation { const InjectGenerator(); @override FutureOr generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) { if (element is! ClassElement) { throw InvalidGenerationSourceError( '@injectable() can only be applied to classes.', element: element, ); } final classElement = element; final className = classElement.name; final mixinName = '_\$$className'; final injectedFields = classElement.fields.where((field) => field.metadata .any((m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject')); final buffer = StringBuffer(); buffer.writeln('mixin $mixinName {'); buffer.writeln(' void _inject($className instance) {'); for (final field in injectedFields) { String? scopeName; String? namedValue; for (final m in field.metadata) { final DartObject? obj = m.computeConstantValue(); final type = obj?.type?.getDisplayString(); if (type == 'scope') { scopeName = obj?.getField('name')?.toStringValue(); } else if (type == 'named') { namedValue = obj?.getField('value')?.toStringValue(); } } // --- Фикс: определяем resolveAsync для Future --- final DartType type = field.type; String genericType; String resolveMethod; if (type.isDartAsyncFuture) { // Если поле Future final typeArg = (type as ParameterizedType).typeArguments.first; genericType = typeArg.getDisplayString(); resolveMethod = 'resolveAsync<$genericType>'; } else { genericType = type.getDisplayString(); resolveMethod = 'resolve<$genericType>'; } // Вызываем openScope или openRootScope String accessor = (scopeName != null && scopeName.isNotEmpty) ? "CherryPick.openScope(scopeName: '$scopeName').$resolveMethod" : "CherryPick.openRootScope().$resolveMethod"; // Аргументы resolve String params = (namedValue != null && namedValue.isNotEmpty) ? "(named: '$namedValue')" : '()'; buffer.writeln(" instance.${field.name} = $accessor$params;"); } buffer.writeln(' }'); buffer.writeln('}'); return buffer.toString(); } } Builder injectBuilder(BuilderOptions options) => PartBuilder([InjectGenerator()], '.inject.cherrypick.g.dart');