dart - Dart build runner 生成一个包含内容的 dart 文件
问题描述
我正在开发一个包含 200 多个模型的 dart 包,目前我必须为每个模型手动编写一行“导出”,以使模型可供使用此包的每个人使用。
我希望构建运行器生成一个包含每个导出定义的 dart 文件。
因此我会创建一个注释“ExportModel”。构建器应搜索使用此注释注释的每个类。
我尝试创建一些构建器,但它们将为每个带注释的类生成一个 *.g.dart 文件。我只想拥有一个文件。
哪里有一种方法可以创建一个只运行一次并在最后创建一个文件的构建器?
解决方案
对只运行一次并在包中创建单个文件的构建器的问题的简短回答是r'$lib$'
用作输入扩展名。长答案是,要找到带注释的类,您可能需要一个中间输出来跟踪它们。
我会用 2 个构建器编写这个,一个用于搜索ExportModel
注释,另一个用于编写导出文件。这是一个省略了细节的粗略草图——我没有在这里测试任何代码,但它应该能让你走上正确的道路。
Builder 1 - 找到用@ExportModel()
.
可以使用 中的一些实用程序编写package:source_gen
,但不能使用,LibraryBuilder
因为它不输出 Dart 代码...
目标是在.exports
每个文件旁边写一个.dart
文件,作为所有带有注释的类的名称@ExportModel()
。
class ExportLocatingBuilder implements Builder {
@override
final buildExtensions = const {
'.dart': ['.exports']
};
@override
Future<void> build(BuildStep buildStep) async {
final resolver = buildStep.resolver;
if (!await resolver.isLibrary(buildStep.inputId)) return;
final lib = LibraryReader(await buildStep.inputLibrary);
final exportAnnotation = TypeChecker.fromRuntime(ExportModel);
final annotated = [
for (var member in lib.annotatedWith(exportAnnotation)) element.name,
];
if (annotated.isNotEmpty) {
buildStep.writeAsString(
buildStep.inputId.changeExtension('.exports'), annotated.join(','));
}
}
}
这个构建器应该是build_to: cache
并且您可能希望有一个PostProcessBuilder
清理它产生的所有输出,这些输出将用applies_builder
. 您可以使用FileDeletingBuilder
廉价地实施清理。例如,请参阅有关临时输出和角度清理的常见问题解答。
Builder 2 - 找到.exports
文件并生成 Dart 文件
用于findAssets
追踪所有这些文件,并为每个.exports
文件编写一个语句。export
将 ashow
与应包含已注释成员名称的文件内容一起使用。
class ExportsBuilder implements Builder {
@override
final buildExtensions = const {
r'$lib$': ['exports.dart']
};
@override
Future<void> build(BuildStep buildStep) async {
final exports = buildStep.findAssets(Glob('**/*.exports'));
final content = [
await for (var exportLibrary in exports)
'export \'${exportLibrary.changeExtension('.dart').uri}\' '
'show ${await buildStep.readAsString(exportLibrary)};',
];
if (content.isNotEmpty) {
buildStep.writeAsString(
AssetId(buildStep.inputId.package, 'lib/exports.dart'),
content.join('\n'));
}
}
}
build_to: source
如果你想在 pub 上发布这个文件,这个构建器应该是可能的。它应该有一个required_inputs: [".exports"]
以确保它在前一个构建器之后运行。
为什么需要这么复杂?
您可以将其实现为findAssets
用于查找所有 Dart 文件的单个构建器。缺点是重建会慢得多,因为它会因任何 Dart 文件中的任何内容更改而失效,并且您最终会解析所有Dart 代码以更改任何Dart 代码。使用 2 builder 方法,只有.exports
来自更改的 Dart 文件的个体需要在更改时解析和重建,然后只有在导出更改时exports.dart
文件才会失效。
旧版本build_runner
也不支持使用Resolver
来解析不是从输入库中传递导入的代码。最近的版本build_runner
放宽了这个限制。
推荐阅读
- python - 下面的 *****.objects.all() 无法被 python 识别,它们在输入时不会出现在建议中。我在 IDE 和控制台上都试过了
- cmake - CMake 目标 INTERFACE_INCLUDE_DIRECTORIES 是否自动添加到父 INCLUDE_DIRECTORIES?
- sql - 从基于范围的查询中获取整个月份
- python - Tornado API 2.2.5 和 2.3.1 之间的 Keras 预测?
- go - Go 中的时间转换不正确
- javascript - 在显示之前获取 dom 元素?
- markdown - 从 blogdown 页面中删除的内联 html
- parsing - 在颤振/飞镖中解析数字
- javascript - Append(), One() 的 jQuery 到 JavaScript 翻译
- java - 解析 ISO-8601 日期时间