fall_gen_base 0.0.8
fall_gen_base: ^0.0.8 copied to clipboard
Fall Core Code Generator - Code generation tools for Fall Core framework. Provides ServiceGenerator and AopGenerator for compile-time code generation.
Fall Gen Base #
Fall Core 框架的代码生成基础模块,提供可扩展的代码生成工具和通用生成器。
📦 模块介绍 #
fall_gen_base
是 Fall Core 框架的代码生成基础模块,为其他代码生成器提供了通用的基础设施和工具类。它抽象了代码扫描、文件处理、代码生成等常用功能,使开发者可以更容易地创建自定义的代码生成器。
✨ 特性 #
- 🏗️ 抽象基础生成器:提供可扩展的
BaseAutoScan
抽象类 - 🔍 文件扫描引擎:支持 Glob 模式的文件包含/排除机制
- 🛠️ 代码生成工具:提供丰富的代码生成工具函数
- 📂 路径计算工具:智能的导入路径计算和转换
- 🎯 注解处理:统一的注解读取和处理工具
- ⚡ 高性能扫描:优化的文件扫描和处理机制
- 🔧 Source Gen 集成:完美集成 Dart source_gen 框架
🏗️ 核心组件 #
BaseAutoScan #
抽象的自动扫描代码生成器基类:
abstract class BaseAutoScan<T extends ServiceInfoBase>
extends GeneratorForAnnotation<AutoScan> {
// 处理单个ClassElement,返回对应的服务信息对象列表
List<T> process(ClassElement element, ConstantReader annotation, BuildStep buildStep);
// 生成注册方法的方法体
String genRegisterBody(List<T> services);
// 生成注入方法的方法体
String genInjectBody(List<T> services);
// 生成Class或Extension对象
Object genClassExtend(String className, List<Method> methods);
}
GenUtil #
代码生成工具类,提供常用的工具函数:
class GenUtil {
// 计算相对导入路径
static String getImportPath(Uri importUri, Uri outputUri);
// 读取注解中的列表参数(泛型版本)
static List<T> readList<T>(ConstantReader annotation, String fieldName, List<T> defaultValue);
// 检查元素是否有指定注解
static bool hasAnnotation(Element element, Type annotation);
// 获取元素的注解对象
static DartObject? getAnnotation(Element element, Type annotation);
// 创建类型检查器
static TypeChecker checker(Type type);
}
ServiceInfoBase #
服务信息基类接口,定义了服务信息对象的基本结构:
abstract class ServiceInfoBase {
String get className; // 类名
Uri get inputUri; // 源文件URI
String? get serviceName; // 服务名称(可选)
List<InjectableField> get injectableFields; // 可注入字段列表
}
InjectableField #
可注入字段信息类:
class InjectableField {
final String fieldName; // 字段名
final String fieldType; // 字段类型
final bool lazy; // 是否懒加载
final String? serviceName; // 服务名称(可选)
// 收集标注@Auto的字段
static List<InjectableField> collectInjectableFields(ClassElement element);
}
🚀 快速开始 #
1. 安装 #
在你的 pubspec.yaml
中添加:
dependencies:
fall_core_base: ^0.0.8
dev_dependencies:
fall_gen_base: ^0.0.8
build_runner: ^2.7.0
2. 创建自定义生成器 #
// my_generator.dart
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:code_builder/code_builder.dart';
import 'package:source_gen/source_gen.dart';
import 'package:fall_gen_base/fall_gen_base.dart';
// 定义自定义服务信息类
class MyServiceInfo extends ServiceInfoBase {
@override
final String className;
@override
final Uri inputUri;
@override
final String? serviceName;
@override
final List<InjectableField> injectableFields;
MyServiceInfo({
required this.className,
required this.inputUri,
this.serviceName,
required this.injectableFields,
});
}
// 实现自定义生成器
class MyGenerator extends BaseAutoScan<MyServiceInfo> {
MyGenerator({bool debug = false}) : super(debug: debug);
@override
List<MyServiceInfo> process(
ClassElement element,
ConstantReader annotation,
BuildStep buildStep,
) {
// 处理单个类元素,提取服务信息
return [
MyServiceInfo(
className: element.name ?? 'Unknown',
inputUri: buildStep.inputId.uri,
serviceName: annotation.read('name').isNull
? null
: annotation.read('name').stringValue,
injectableFields: InjectableField.collectInjectableFields(element),
)
];
}
@override
String genRegisterBody(List<MyServiceInfo> services) {
// 生成服务注册代码
final buffer = StringBuffer();
for (final service in services) {
buffer.writeln('Get.lazyPut<${service.className}>(() => ${service.className}());');
}
return buffer.toString();
}
@override
String genInjectBody(List<MyServiceInfo> services) {
// 生成依赖注入代码
final buffer = StringBuffer();
for (final service in services) {
for (final field in service.injectableFields) {
buffer.writeln(
'InjectUtil.inject<${field.fieldType}>(${field.serviceName != null ? "'${field.serviceName}'" : 'null'}, '
'(instance) => Get.find<${service.className}>().${field.fieldName} = instance);'
);
}
}
return buffer.toString();
}
@override
Object genClassExtend(String className, List<Method> methods) {
// 生成扩展类
return Extension(
(b) => b
..name = '${className}Extension'
..on = refer(className)
..methods.addAll(methods),
);
}
}
3. 配置构建器 #
// build.dart
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
import 'my_generator.dart';
Builder myGeneratorBuilder(BuilderOptions options) {
return SharedPartBuilder([MyGenerator(debug: true)], 'my_generator');
}
4. 配置 build.yaml #
targets:
$default:
builders:
my_package:my_generator:
enabled: true
generate_for:
- lib/**
options:
debug: true
🔧 高级功能 #
文件扫描配置 #
@AutoScan(
include: [
'lib/services/**/*.dart',
'lib/repositories/**/*.dart'
],
exclude: [
'**/*_test.dart',
'**/*.g.dart',
'**/*.freezed.dart'
],
annotations: [Service, Component] // 指定要扫描的注解类型
)
class MyConfig {}
路径计算示例 #
// 计算相对导入路径
final importUri = Uri.parse('package:my_app/services/user_service.dart');
final outputUri = Uri.parse('package:my_app/init/auto_scan.g.dart');
final relativePath = GenUtil.getImportPath(importUri, outputUri);
// 结果: '../services/user_service.dart'
注解参数读取 #
// 读取不同类型的列表参数
final stringList = GenUtil.readList<String>(annotation, 'include', ['lib/**/*.dart']);
final typeList = GenUtil.readList<Type>(annotation, 'annotations', [Service]);
final intList = GenUtil.readList<int>(annotation, 'priorities', [1, 2, 3]);
自定义字段收集 #
// 扩展 InjectableField 收集其他注解
class CustomField extends InjectableField {
final bool required;
CustomField({
required String fieldName,
required String fieldType,
required bool lazy,
String? serviceName,
required this.required,
}) : super(
fieldName: fieldName,
fieldType: fieldType,
lazy: lazy,
serviceName: serviceName,
);
static List<CustomField> collectCustomFields(ClassElement element) {
// 自定义字段收集逻辑
return [];
}
}
🛠️ 工具函数详解 #
GenUtil.getImportPath() #
智能路径计算函数,支持:
- Package URI 和 Asset URI 之间的转换
- 相同 package 内的相对路径计算
- 跨 package 的绝对路径处理
- 自动处理路径分隔符标准化
GenUtil.readList #
泛型列表读取函数,支持:
String
列表Type
列表int
、double
、bool
基础类型列表- 自动过滤空值和无效值
InjectableField.collectInjectableFields() #
字段收集函数,功能包括:
- 自动识别
@Auto
注解 - 提取字段类型信息
- 解析懒加载和命名参数
- 错误处理和异常忽略
📊 性能优化 #
扫描优化 #
- 使用 Glob 模式进行高效文件匹配
- 支持排除模式减少不必要的文件处理
- 并行处理多个文件以提升性能
内存优化 #
- 延迟加载和处理文件内容
- 及时释放不需要的对象引用
- 优化字符串操作减少内存分配
构建优化 #
- 支持增量构建,只处理变更的文件
- 智能缓存机制避免重复计算
- 最小化生成代码的体积
🐛 故障排除 #
常见问题 #
-
扫描不到文件
# 检查 include 模式是否正确 include: - 'lib/**/*.dart' # 正确 - 'lib/*/*.dart' # 只扫描一层目录
-
路径计算错误
// 确保 URI 格式正确 final uri1 = Uri.parse('package:my_app/file.dart'); // 正确 final uri2 = Uri.parse('my_app/file.dart'); // 错误
-
注解读取失败
// 使用 try-catch 包装注解读取 try { final value = annotation.read('fieldName').stringValue; } catch (e) { // 使用默认值 }
调试技巧 #
-
启用调试模式:
MyGenerator(debug: true) // 输出详细日志
-
查看扫描结果:
// 在 process 方法中添加日志 if (debug) { print('Found service: ${element.name}'); }
🔗 相关模块 #
- fall_core_base - 核心注解和工具模块
- fall_core_gen - 具体的代码生成器实现
- fall_core_main - 运行时核心模块
📄 许可证 #
本项目采用 MIT 许可证。
🤝 贡献 #
欢迎提交 Issue 和 Pull Request!
Fall Gen Base - 可扩展的代码生成基础设施 🏗️