feat: implement instance/provide annotations

This commit is contained in:
Sergey Penkovsky
2025-05-21 00:50:57 +03:00
parent 7914d91653
commit 14dce2aafa
4 changed files with 53 additions and 9 deletions

View File

@@ -16,5 +16,6 @@ library;
export 'src/module.dart'; export 'src/module.dart';
export 'src/bind.dart'; export 'src/bind.dart';
export 'src/provide.dart'; export 'src/provide.dart';
export 'src/instance.dart';
export 'src/singleton.dart'; export 'src/singleton.dart';
export 'src/named.dart'; export 'src/named.dart';

View 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
class instance {
const instance();
}

View File

@@ -76,12 +76,15 @@ class BindSpec {
/// Список параметров, которые требуются методу для внедрения зависимостей /// Список параметров, которые требуются методу для внедрения зависимостей
final List<BindParameterSpec> parameters; final List<BindParameterSpec> parameters;
final String bindingType; // 'instance' | 'provide'
BindSpec({ BindSpec({
required this.returnType, required this.returnType,
required this.methodName, required this.methodName,
required this.isSingleton, required this.isSingleton,
required this.parameters, required this.parameters,
this.named, this.named,
required this.bindingType,
}); });
/// Формирует dart-код для биндинга, например: /// Формирует dart-код для биндинга, например:
@@ -95,11 +98,14 @@ class BindSpec {
final argsStr = parameters.map((p) => p.generateArg()).join(', '); final argsStr = parameters.map((p) => p.generateArg()).join(', ');
// Если аргументов много или они длинные — разбиваем вызов на несколько строк // Если аргументов много или они длинные — разбиваем вызов на несколько строк
final needMultiline = argsStr.length > 60 || argsStr.contains('\n'); //final needMultiline = argsStr.length > 60 || argsStr.contains('\n');
final provide = needMultiline // Важно: для .toInstance всегда просто method(), для .toProvide нужна лямбда
final provide = bindingType == 'instance'
? '.toInstance($methodName($argsStr))'
: (argsStr.length > 60 || argsStr.contains('\n')
? '.toProvide(\n${' ' * (indent + 2)}() => $methodName($argsStr))' ? '.toProvide(\n${' ' * (indent + 2)}() => $methodName($argsStr))'
: '.toProvide(() => $methodName($argsStr))'; : '.toProvide(() => $methodName($argsStr))');
final namePart = named != null ? ".withName('$named')" : ''; final namePart = named != null ? ".withName('$named')" : '';
final singletonPart = isSingleton ? '.singleton()' : ''; final singletonPart = isSingleton ? '.singleton()' : '';
@@ -132,12 +138,24 @@ class BindSpec {
params.add(BindParameterSpec(typeStr, paramNamed)); params.add(BindParameterSpec(typeStr, paramNamed));
} }
// определяем bindingType
final hasInstance = _MetadataUtils.anyMeta(method.metadata, 'instance');
final hasProvide = _MetadataUtils.anyMeta(method.metadata, 'provide');
if (!hasInstance && !hasProvide) {
throw InvalidGenerationSourceError(
'Метод $methodName класса-модуля должен быть помечен либо @instance(), либо @provide().',
element: method,
);
}
final bindingType = hasInstance ? 'instance' : 'provide';
return BindSpec( return BindSpec(
returnType: returnType, returnType: returnType,
methodName: methodName, methodName: methodName,
isSingleton: isSingleton, isSingleton: isSingleton,
named: named, named: named,
parameters: params, parameters: params,
bindingType: bindingType,
); );
} }
} }

View File

@@ -9,16 +9,24 @@ part 'app_module.cherrypick.g.dart';
@module() @module()
abstract class AppModule extends Module { abstract class AppModule extends Module {
@instance()
int timeout() => 1000;
@instance()
@named('baseUrl')
String baseUrl() => "https://google.com";
@provide()
@singleton() @singleton()
@named('dio') @named('dio')
Dio dio() => Dio(); Dio dio(@named('baseUrl') String baseUrl) =>
Dio(BaseOptions(baseUrl: baseUrl));
@provide()
@singleton() @singleton()
@named('api')
JsonPlaceholderApi api(@named('dio') Dio dio) => JsonPlaceholderApi(dio); JsonPlaceholderApi api(@named('dio') Dio dio) => JsonPlaceholderApi(dio);
@provide()
@named('repo') @named('repo')
@singleton() PostRepository repo(JsonPlaceholderApi api) => PostRepositoryImpl(api);
PostRepository repo(@named('api') JsonPlaceholderApi api) =>
PostRepositoryImpl(api);
} }