mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
starting implement inject generator
This commit is contained in:
@@ -19,3 +19,5 @@ export 'src/instance.dart';
|
|||||||
export 'src/singleton.dart';
|
export 'src/singleton.dart';
|
||||||
export 'src/named.dart';
|
export 'src/named.dart';
|
||||||
export 'src/params.dart';
|
export 'src/params.dart';
|
||||||
|
export 'src/inject.dart';
|
||||||
|
export 'src/injectable.dart';
|
||||||
|
|||||||
17
cherrypick_annotations/lib/src/inject.dart
Normal file
17
cherrypick_annotations/lib/src/inject.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// 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 inject {
|
||||||
|
const inject();
|
||||||
|
}
|
||||||
17
cherrypick_annotations/lib/src/injectable.dart
Normal file
17
cherrypick_annotations/lib/src/injectable.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// 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 injectable {
|
||||||
|
const injectable();
|
||||||
|
}
|
||||||
@@ -7,10 +7,21 @@ builders:
|
|||||||
required_inputs: ["lib/**"]
|
required_inputs: ["lib/**"]
|
||||||
runs_before: []
|
runs_before: []
|
||||||
build_to: source
|
build_to: source
|
||||||
|
inject_generator:
|
||||||
|
import: "package:cherrypick_generator/inject_generator.dart"
|
||||||
|
builder_factories: ["injectBuilder"]
|
||||||
|
build_extensions: {".dart": [".cherrypick.g.dart"]}
|
||||||
|
auto_apply: dependents
|
||||||
|
required_inputs: ["lib/**"]
|
||||||
|
runs_before: []
|
||||||
|
build_to: source
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
$default:
|
$default:
|
||||||
builders:
|
builders:
|
||||||
cherrypick_generator|module_generator:
|
cherrypick_generator|module_generator:
|
||||||
|
generate_for:
|
||||||
|
- lib/**.dart
|
||||||
|
cherrypick_generator|inject_generator:
|
||||||
generate_for:
|
generate_for:
|
||||||
- lib/**.dart
|
- lib/**.dart
|
||||||
@@ -14,3 +14,4 @@ library;
|
|||||||
//
|
//
|
||||||
|
|
||||||
export 'module_generator.dart';
|
export 'module_generator.dart';
|
||||||
|
export 'inject_generator.dart';
|
||||||
|
|||||||
65
cherrypick_generator/lib/inject_generator.dart
Normal file
65
cherrypick_generator/lib/inject_generator.dart
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
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;
|
||||||
|
|
||||||
|
class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||||
|
const InjectGenerator();
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<String> 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.',
|
||||||
|
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'));
|
||||||
|
|
||||||
|
// Генерируем инициализацию для каждого поля с аннотацией @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')";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.writeln(
|
||||||
|
" instance.${field.name} = CherryPick.openRootScope().resolve<$fieldType>$namedParam;");
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.writeln(' }');
|
||||||
|
buffer.writeln('}');
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder injectBuilder(BuilderOptions options) =>
|
||||||
|
PartBuilder([InjectGenerator()], '.inject.cherrypick.g.dart');
|
||||||
@@ -90,4 +90,4 @@ class ModuleGenerator extends GeneratorForAnnotation<ann.module> {
|
|||||||
/// файлов, где встречается @module().
|
/// файлов, где встречается @module().
|
||||||
/// ---------------------------------------------------------------------------
|
/// ---------------------------------------------------------------------------
|
||||||
Builder moduleBuilder(BuilderOptions options) =>
|
Builder moduleBuilder(BuilderOptions options) =>
|
||||||
PartBuilder([ModuleGenerator()], '.cherrypick.g.dart');
|
PartBuilder([ModuleGenerator()], '.module.cherrypick.g.dart');
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ dependencies:
|
|||||||
build: ^2.4.1
|
build: ^2.4.1
|
||||||
build_runner: ^2.4.13
|
build_runner: ^2.4.13
|
||||||
source_gen: ^1.5.0
|
source_gen: ^1.5.0
|
||||||
|
collection: ^1.18.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^5.0.0
|
lints: ^5.0.0
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ packages:
|
|||||||
path: "../../cherrypick_generator"
|
path: "../../cherrypick_generator"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.1.0-dev.1"
|
version: "1.1.0-dev.2"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
35
examples/postly/lib/app.dart
Normal file
35
examples/postly/lib/app.dart
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import 'domain/repository/post_repository.dart';
|
||||||
|
import 'presentation/bloc/post_bloc.dart';
|
||||||
|
import 'router/app_router.dart';
|
||||||
|
|
||||||
|
part 'app.inject.cherrypick.g.dart';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
class MyApp extends StatelessWidget with _$MyApp {
|
||||||
|
final Scope scope;
|
||||||
|
final _appRouter = AppRouter();
|
||||||
|
|
||||||
|
@named('repo')
|
||||||
|
@inject()
|
||||||
|
late final PostRepository repository;
|
||||||
|
|
||||||
|
MyApp({super.key, required this.scope});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
_inject(this);
|
||||||
|
return BlocProvider(
|
||||||
|
create: (_) => PostBloc(repository),
|
||||||
|
child: MaterialApp.router(
|
||||||
|
routeInformationParser: _appRouter.defaultRouteParser(),
|
||||||
|
routerDelegate: _appRouter.delegate(),
|
||||||
|
theme: ThemeData.light(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import '../data/network/json_placeholder_api.dart';
|
|||||||
import '../data/post_repository_impl.dart';
|
import '../data/post_repository_impl.dart';
|
||||||
import '../domain/repository/post_repository.dart';
|
import '../domain/repository/post_repository.dart';
|
||||||
|
|
||||||
part 'app_module.cherrypick.g.dart';
|
part 'app_module.module.cherrypick.g.dart';
|
||||||
|
|
||||||
@module()
|
@module()
|
||||||
abstract class AppModule extends Module {
|
abstract class AppModule extends Module {
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:postly/app.dart';
|
||||||
import 'di/app_module.dart';
|
import 'di/app_module.dart';
|
||||||
import 'domain/repository/post_repository.dart';
|
|
||||||
import 'presentation/bloc/post_bloc.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'router/app_router.dart';
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final scope = CherryPick.openRootScope();
|
final scope = CherryPick.openRootScope();
|
||||||
@@ -12,25 +9,3 @@ void main() {
|
|||||||
|
|
||||||
runApp(MyApp(scope: scope));
|
runApp(MyApp(scope: scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
|
||||||
final Scope scope;
|
|
||||||
final _appRouter = AppRouter();
|
|
||||||
|
|
||||||
MyApp({super.key, required this.scope});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// Получаем репозиторий через injector
|
|
||||||
final repository = scope.resolve<PostRepository>(named: 'repo');
|
|
||||||
|
|
||||||
return BlocProvider(
|
|
||||||
create: (_) => PostBloc(repository),
|
|
||||||
child: MaterialApp.router(
|
|
||||||
routeInformationParser: _appRouter.defaultRouteParser(),
|
|
||||||
routerDelegate: _appRouter.delegate(),
|
|
||||||
theme: ThemeData.light(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ packages:
|
|||||||
path: "../../cherrypick_generator"
|
path: "../../cherrypick_generator"
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.1.0-dev.1"
|
version: "1.1.0-dev.2"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user