source_gen 库的使用
2022年10月12日大约 2 分钟
Fair 源码中用到了 source_gen 库,因此,本文主要介绍一下 source_gen 库的使用。
1. source_gen 库的介绍
source_gen 是一个用于 Dart 代码自动生成的工具库和开发框架。相较于 build 库,source_gen 提供更易于使用的 API 和工具。
在 Fair 源码中,Fair DSL 的生成使用了 source_gen。
2. source_gen 库的使用
2.1 添加 source_gen 依赖
dependencies:
source_gen: ^1.2.2
2.2 创建注解和使用
下面以 Fair 中的使用为例,首先创建了注解 - FairPatch。
/// Annotation for Fair compiler, this indicate the top Widget need to generate as bundle resource
class FairPatch {
/// Optional,Set the module for the currently generated bundle.
/// bundle files in the same module can be downloaded as a set of resources.
final String module;
const FairPatch({this.module = 'lib'});
}
然后使用 FairPatch。
@FairPatch()
class IfEqualBoolPage extends StatefulWidget {
var fairProps;
IfEqualBoolPage(dynamic data) {
fairProps = data;
}
@override
State<StatefulWidget> createState() {
return _State();
}
}
2.3 创建 Generator
class BundleGenerator extends GeneratorForAnnotation<FairPatch>
with FairCompiler {
@override
Future<String?> generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) async {
......
/// Get the value of the module parameter in the FairPatch annotation.
/// If module is not set, or the value of module is an empty string, the default value is 'lib'
var module = annotation.peek('module');
......
final tmp = await temp;
tmp.writeAsBytesSync(await buildStep.readAsBytes(buildStep.inputId));
var r = await compile(buildStep, ['-f', tmp.absolute.path]);
tmp.deleteSync();
......
return r.data;
}
}
根据注解 FairPatch 过滤 Dart 源代码,并且可以解析获取 FairPatch 中设置的数据。调用 compile 生成 Fair DSL。
2.4 创建 Builder
Generator 的执行需要 Builder 来触发。创建 Builder 如下:
Builder build(BuilderOptions options) {
return BundleBuilder(BundleGenerator(), formatOutput: JsonFormatter().format);
}
2.5 创建 build.yaml
builders:
fairc:
import: "package:fair_compiler/src/builder.dart"
builder_factories: ["build", "bind"]
build_extensions: {".dart": [".bundle.json", ".binding", ".fair.ignore"]}
auto_apply: root_package
build_to: cache
defaults:
generate_for:
- lib/**
applies_builders: [":archive"]
runs_before: [":archive"]
其中,
- import 用于导入返回 Builder 的方法所在包
- builder_factories 填写的是返回 Builder 的方法名
- build_extensions 指定输入扩展名到输出扩展名的映射
- auto_apply 指定 builder 作用域,可选值:(可选,默认为 none)
- "none":除非手动配置,否则不要应用此 Builder
- "dependents":将此Builder应用于包,直接依赖于公开构建器的包
- "all_packages":将此 Builder 应用于传递依赖关系图中的所有包
- "root_package":仅将此 Builder 应用于顶级包
- build_to 指定输出位置,(可选,默认为 cache)
- "source":输出到其主要输入的源码树上
- "cache":输出到隐藏的构建缓存上
- required_inputs:指定一个或一系列文件扩展名,表示在任何可能产生该类型输出的 Builder 之后运行(可选)
- runs_before:在指定的 Builder 之前运行
2.6 运行 Builder
通常 source_gen 会结合 build_runner 使用,执行如下命令即可:
flutter pub run build_runner build