diff --git a/cherrypick_annotations/lib/cherrypick_annotations.dart b/cherrypick_annotations/lib/cherrypick_annotations.dart index ec4afe5..dbdc089 100644 --- a/cherrypick_annotations/lib/cherrypick_annotations.dart +++ b/cherrypick_annotations/lib/cherrypick_annotations.dart @@ -21,3 +21,4 @@ export 'src/named.dart'; export 'src/params.dart'; export 'src/inject.dart'; export 'src/injectable.dart'; +export 'src/scope.dart'; diff --git a/cherrypick_annotations/lib/src/scope.dart b/cherrypick_annotations/lib/src/scope.dart new file mode 100644 index 0000000..b69b7cb --- /dev/null +++ b/cherrypick_annotations/lib/src/scope.dart @@ -0,0 +1,18 @@ +// +// Copyright 2021 Sergey Penkovsky (sergey.penkovsky@gmail.com) +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// ignore: camel_case_types +final class scope { + final String? name; + const scope(this.name); +} diff --git a/cherrypick_generator/lib/inject_generator.dart b/cherrypick_generator/lib/inject_generator.dart index 598062c..8292dda 100644 --- a/cherrypick_generator/lib/inject_generator.dart +++ b/cherrypick_generator/lib/inject_generator.dart @@ -1,6 +1,6 @@ import 'dart:async'; +import 'package:analyzer/dart/constant/value.dart'; import 'package:build/build.dart'; -import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann; @@ -11,8 +11,6 @@ class InjectGenerator extends GeneratorForAnnotation { @override FutureOr generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) { - // Only classes are supported for @module() annotation - // Обрабатываются только классы (другие элементы — ошибка) if (element is! ClassElement) { throw InvalidGenerationSourceError( '@injectable() can only be applied to classes.', @@ -28,30 +26,36 @@ class InjectGenerator extends GeneratorForAnnotation { .any((m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject')); - // Генерируем инициализацию для каждого поля с аннотацией @inject() final buffer = StringBuffer(); buffer.writeln('mixin $mixinName {'); buffer.writeln(' void _inject($className instance) {'); for (final field in injectedFields) { - // Получаем имя типа - final fieldType = field.type.getDisplayString(); - // Ищем аннотацию @named - final namedAnnotation = field.metadata.firstWhereOrNull( - (m) => m.computeConstantValue()?.type?.getDisplayString() == 'named', - ); - String namedParam = ''; - if (namedAnnotation != null) { - final namedValue = namedAnnotation - .computeConstantValue() - ?.getField('value') - ?.toStringValue(); - if (namedValue != null) { - namedParam = "(named: '$namedValue')"; + 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(); } } - buffer.writeln( - " instance.${field.name} = CherryPick.openRootScope().resolve<$fieldType>$namedParam;"); + + final String fieldType = field.type.getDisplayString(); + + String accessor = (scopeName != null && scopeName.isNotEmpty) + ? "CherryPick.openScope(scopeName: '$scopeName').resolve" + : "CherryPick.openRootScope().resolve"; + + String generic = fieldType != 'dynamic' ? '<$fieldType>' : ''; + String params = (namedValue != null && namedValue.isNotEmpty) + ? "(named: '$namedValue')" + : '()'; + + buffer.writeln(" instance.${field.name} = $accessor$generic$params;"); } buffer.writeln(' }'); diff --git a/examples/postly/lib/app.dart b/examples/postly/lib/app.dart index 86bae2e..218b890 100644 --- a/examples/postly/lib/app.dart +++ b/examples/postly/lib/app.dart @@ -11,14 +11,22 @@ part 'app.inject.cherrypick.g.dart'; @injectable() class MyApp extends StatelessWidget with _$MyApp { - final Scope scope; final _appRouter = AppRouter(); + @scope('authZone') + @inject() + late final String text; + + @scope('authZone') + @named('timeout') + @inject() + late final int timeout; + @named('repo') @inject() late final PostRepository repository; - MyApp({super.key, required this.scope}); + MyApp({super.key}); @override Widget build(BuildContext context) { diff --git a/examples/postly/lib/main.dart b/examples/postly/lib/main.dart index 37cbf6b..5a63c72 100644 --- a/examples/postly/lib/main.dart +++ b/examples/postly/lib/main.dart @@ -4,8 +4,6 @@ import 'package:postly/app.dart'; import 'di/app_module.dart'; void main() { - final scope = CherryPick.openRootScope(); - scope.installModules([$AppModule()]); - - runApp(MyApp(scope: scope)); + CherryPick.openRootScope().installModules([$AppModule()]); + runApp(MyApp()); }