diff --git a/cherrypick_generator/lib/inject_generator.dart b/cherrypick_generator/lib/inject_generator.dart index b421d2d..5766606 100644 --- a/cherrypick_generator/lib/inject_generator.dart +++ b/cherrypick_generator/lib/inject_generator.dart @@ -1,3 +1,16 @@ +// +// 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. +// + import 'dart:async'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/type.dart'; @@ -6,9 +19,28 @@ import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann; +/// InjectGenerator generates a mixin for a class marked with @injectable() +/// and injects all fields annotated with @inject(), using CherryPick DI. +/// +/// For Future fields it calls .resolveAsync(), +/// otherwise .resolve() is used. Scope and named qualifiers are supported. +/// +/// --- +/// +/// InjectGenerator генерирует миксин для класса с аннотацией @injectable() +/// и внедряет все поля, помеченные @inject(), используя DI-фреймворк CherryPick. +/// +/// Для Future полей вызывается .resolveAsync(), +/// для остальных — .resolve(). Поддерживаются scope и named qualifier. +/// class InjectGenerator extends GeneratorForAnnotation { const InjectGenerator(); + /// The main entry point for code generation. + /// + /// Checks class validity, collects injectable fields, and produces injection code. + /// + /// Основная точка входа генератора. Проверяет класс, собирает инъектируемые поля и создает код внедрения зависимостей. @override FutureOr generateForAnnotatedElement( Element element, @@ -30,7 +62,8 @@ class InjectGenerator extends GeneratorForAnnotation { ..writeln('mixin $mixinName {') ..writeln(' void _inject($className instance) {'); - // Collect and process all @inject fields + // Collect and process all @inject fields. + // Собираем и обрабатываем все поля с @inject. final injectFields = classElement.fields.where(_isInjectField).map(_parseInjectField); @@ -45,14 +78,20 @@ class InjectGenerator extends GeneratorForAnnotation { return buffer.toString(); } - // Checks if a field has @inject annotation + /// Checks if a field has the @inject annotation. + /// + /// Проверяет, отмечено ли поле аннотацией @inject. static bool _isInjectField(FieldElement field) { return field.metadata.any( (m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject', ); } - // Parsed structure storage + /// Parses the field for scope/named qualifiers and determines its type. + /// Returns a [_ParsedInjectField] describing injection information. + /// + /// Разбирает поле на наличие модификаторов scope/named и выясняет его тип. + /// Возвращает [_ParsedInjectField] с информацией о внедрении. static _ParsedInjectField _parseInjectField(FieldElement field) { String? scopeName; String? namedValue; @@ -89,7 +128,11 @@ class InjectGenerator extends GeneratorForAnnotation { ); } - // Generates the injection invocation line for the field + /// Generates a line of code that performs the dependency injection for a field. + /// Handles resolve/resolveAsync, scoping, and named qualifiers. + /// + /// Генерирует строку кода, которая внедряет зависимость для поля. + /// Учитывает resolve/resolveAsync, scoping и named qualifier. String _generateInjectionLine(_ParsedInjectField field) { final methodName = field.isFuture ? 'resolveAsync<${field.coreType}>' @@ -105,11 +148,26 @@ class InjectGenerator extends GeneratorForAnnotation { } } +/// Data structure representing all information required to generate +/// injection code for a field. +/// +/// Структура данных, содержащая всю информацию, +/// необходимую для генерации кода внедрения для поля. class _ParsedInjectField { + /// The name of the field / Имя поля. final String fieldName; + + /// The base type name (T or Future) / Базовый тип (T или тип из Future). final String coreType; + + /// True if the field type is Future; false otherwise + /// Истина, если поле — Future, иначе — ложь. final bool isFuture; + + /// Optional scope annotation argument / Опциональное имя scope. final String? scopeName; + + /// Optional named annotation argument / Опциональное имя named. final String? namedValue; _ParsedInjectField({ @@ -121,5 +179,8 @@ class _ParsedInjectField { }); } +/// Builder factory. Used by build_runner. +/// +/// Фабрика билдера. Используется build_runner. Builder injectBuilder(BuilderOptions options) => PartBuilder([InjectGenerator()], '.inject.cherrypick.g.dart');