Initial project

This commit is contained in:
Cody
2026-03-06 14:56:17 +08:00
parent 977b627b15
commit bf9e099747
1180 changed files with 50973 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:networks_sdk/src/annotations/api_request.dart';
import 'package:source_gen/source_gen.dart';
import 'package:build/build.dart';
/// @ApiRequest 代码生成器
///
/// 为标注了 `@ApiRequest` 的类自动生成 mixin提供
/// - `path`, `method`, `requestType`, `includeToken` 协议实现
/// - 自动注册响应类型的 `fromJson`(在 `parameters` getter 中触发,
/// 保证首次请求前完成注册,无需手动调用 `registerApiResponses()`
///
/// 生成的 mixin 命名规则:`_$<ClassName>Api`
///
/// 示例输出:
/// ```dart
/// mixin _$LoginRequestApi on ApiRequestable<LoginData> {
/// @override String get path => '/auth/login';
/// @override HttpMethod get method => HttpMethod.post;
/// @override ApiRequestType get requestType => ApiRequestType.login;
/// @override bool get includeToken => false;
/// @override
/// Map<String, dynamic>? get parameters {
/// registerResponse<LoginData>(LoginData.fromJson);
/// return super.parameters;
/// }
/// }
/// ```
class ApiRequestGenerator extends GeneratorForAnnotation<ApiRequest>
{
@override
String generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep,)
{
if (element is! ClassElement) {
throw InvalidGenerationSourceError(
'@ApiRequest can only be applied to classes.',
element: element,
);
}
final className = element.name;
final path = annotation.read('path').stringValue;
// 读取 HttpMethod 枚举值
final methodName = _readEnumName(
annotation.read('method').objectValue,
'post',
);
// 读取 responseType用于泛型绑定 + 自动注册 fromJson
final responseType = annotation.read('responseType').typeValue;
final responseTypeName = responseType.getDisplayString();
// 读取 ApiRequestType 枚举值
final requestTypeName = _readEnumName(
annotation.read('requestType').objectValue,
'request',
);
// 读取 includeToken默认根据 requestType 推断login → false其余 → true
final includeTokenReader = annotation.peek('includeToken');
final bool includeToken;
if (includeTokenReader != null && !includeTokenReader.isNull) {
includeToken = includeTokenReader.boolValue;
} else {
includeToken = requestTypeName != 'login';
}
return '''
/// Generated by @ApiRequest for [$className]
mixin _\$${className}Api on ApiRequestable<$responseTypeName> {
@override
String get path => '$path';
@override
HttpMethod get method => HttpMethod.$methodName;
@override
ApiRequestType get requestType => ApiRequestType.$requestTypeName;
@override
bool get includeToken => $includeToken;
@override
Map<String, dynamic>? get parameters {
registerResponse<$responseTypeName>($responseTypeName.fromJson);
return super.parameters;
}
}
''';
}
/// 从 DartObject 提取枚举常量名称
String _readEnumName(dynamic dartObject, String defaultValue) {
final index = dartObject.getField('index')?.toIntValue();
if (index == null) return defaultValue;
final type = dartObject.type;
if (type is InterfaceType) {
final constants = type.element.fields
.where((f) => f.isEnumConstant)
.toList();
if (index < constants.length) {
return constants[index].name ?? defaultValue;
}
}
return defaultValue;
}
}

View File

@@ -0,0 +1,12 @@
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
import 'api_request_generator.dart';
/// @ApiRequest 代码生成器入口
///
/// 在 `build.yaml` 中注册此 builder配合 `build_runner` 使用。
/// 生成的代码通过 `SharedPartBuilder` 合并到 `.g.dart` 文件中,
/// 与 `json_serializable` 等生成器共存。
Builder apiRequestBuilder(BuilderOptions options) =>
SharedPartBuilder([ApiRequestGenerator()], 'api_request');