mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
refactor inject generator
This commit is contained in:
@@ -11,7 +11,10 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
|
||||
@override
|
||||
FutureOr<String> generateForAnnotatedElement(
|
||||
Element element, ConstantReader annotation, BuildStep buildStep) {
|
||||
Element element,
|
||||
ConstantReader annotation,
|
||||
BuildStep buildStep,
|
||||
) {
|
||||
if (element is! ClassElement) {
|
||||
throw InvalidGenerationSourceError(
|
||||
'@injectable() can only be applied to classes.',
|
||||
@@ -23,61 +26,99 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
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()
|
||||
..writeln('mixin $mixinName {')
|
||||
..writeln(' void _inject($className instance) {');
|
||||
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('mixin $mixinName {');
|
||||
buffer.writeln(' void _inject($className instance) {');
|
||||
// Collect and process all @inject fields
|
||||
final injectFields =
|
||||
classElement.fields.where(_isInjectField).map(_parseInjectField);
|
||||
|
||||
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<T> ---
|
||||
final DartType type = field.type;
|
||||
String genericType;
|
||||
String resolveMethod;
|
||||
|
||||
if (type.isDartAsyncFuture) {
|
||||
// Если поле Future<T>
|
||||
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;");
|
||||
for (final parsedField in injectFields) {
|
||||
buffer.writeln(_generateInjectionLine(parsedField));
|
||||
}
|
||||
|
||||
buffer.writeln(' }');
|
||||
buffer.writeln('}');
|
||||
buffer
|
||||
..writeln(' }')
|
||||
..writeln('}');
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
// Checks if a field has @inject annotation
|
||||
static bool _isInjectField(FieldElement field) {
|
||||
return field.metadata.any(
|
||||
(m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject',
|
||||
);
|
||||
}
|
||||
|
||||
// Parsed structure storage
|
||||
static _ParsedInjectField _parseInjectField(FieldElement field) {
|
||||
String? scopeName;
|
||||
String? namedValue;
|
||||
|
||||
for (final meta in field.metadata) {
|
||||
final DartObject? obj = meta.computeConstantValue();
|
||||
final type = obj?.type?.getDisplayString();
|
||||
if (type == 'scope') {
|
||||
scopeName = obj?.getField('name')?.toStringValue();
|
||||
} else if (type == 'named') {
|
||||
namedValue = obj?.getField('value')?.toStringValue();
|
||||
}
|
||||
}
|
||||
|
||||
final DartType dartType = field.type;
|
||||
String coreTypeName;
|
||||
bool isFuture;
|
||||
|
||||
if (dartType.isDartAsyncFuture) {
|
||||
final ParameterizedType paramType = dartType as ParameterizedType;
|
||||
coreTypeName = paramType.typeArguments.first.getDisplayString();
|
||||
isFuture = true;
|
||||
} else {
|
||||
coreTypeName = dartType.getDisplayString();
|
||||
isFuture = false;
|
||||
}
|
||||
|
||||
return _ParsedInjectField(
|
||||
fieldName: field.name,
|
||||
coreType: coreTypeName,
|
||||
isFuture: isFuture,
|
||||
scopeName: scopeName,
|
||||
namedValue: namedValue,
|
||||
);
|
||||
}
|
||||
|
||||
// Generates the injection invocation line for the field
|
||||
String _generateInjectionLine(_ParsedInjectField field) {
|
||||
final methodName = field.isFuture
|
||||
? 'resolveAsync<${field.coreType}>'
|
||||
: 'resolve<${field.coreType}>';
|
||||
final openCall = (field.scopeName != null && field.scopeName!.isNotEmpty)
|
||||
? "CherryPick.openScope(scopeName: '${field.scopeName}')"
|
||||
: "CherryPick.openRootScope()";
|
||||
final params = (field.namedValue != null && field.namedValue!.isNotEmpty)
|
||||
? "(named: '${field.namedValue}')"
|
||||
: '()';
|
||||
|
||||
return " instance.${field.fieldName} = $openCall.$methodName$params;";
|
||||
}
|
||||
}
|
||||
|
||||
class _ParsedInjectField {
|
||||
final String fieldName;
|
||||
final String coreType;
|
||||
final bool isFuture;
|
||||
final String? scopeName;
|
||||
final String? namedValue;
|
||||
|
||||
_ParsedInjectField({
|
||||
required this.fieldName,
|
||||
required this.coreType,
|
||||
required this.isFuture,
|
||||
this.scopeName,
|
||||
this.namedValue,
|
||||
});
|
||||
}
|
||||
|
||||
Builder injectBuilder(BuilderOptions options) =>
|
||||
|
||||
Reference in New Issue
Block a user