关于 run-codegen
面向 Dart/Flutter 项目的 build_runner 代码生成操作指南,规定注解代码的再生成顺序和固定命令,并要求先生成再运行分析。
主要功能
- 01固定 build_runner 生成命令
- 02代码生成后再运行分析
- 03禁止手动修改生成文件
- 04说明多包工作区生成范围
- 05提供常见生成错误处理步骤
适用场景
- 01分支切换后重新生成注解代码
- 02分析器提示缺少生成文件时排查
- 03在多包工作区安排代码生成
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zakariaf/ flutter-skills --skill run-codegen安装后在 Claude Code 中输入/run-codegen确认已加载。
详细介绍
运行代码生成(build_runner)
一份确定性强、自由度低的操作手册:一次性重新生成所有由注解驱动的代码,然后运行分析。严格按原样运行固定命令——不要修改命令、添加标志,或手动编辑生成的文件。只要源文件带有代码生成注解(@freezed、@JsonSerializable、@riverpod、@DriftDatabase 或 drift 表),且其 *.g.dart / *.freezed.dart / *.drift.dart 文件缺失或已过时,就适用本手册。
不可妥协的规则
- 在运行
flutter analyze之前运行代码生成。 全新克隆、切换分支或刚编辑完带注解的文件时,磁盘上都没有生成的部分文件。对这样的代码树运行分析会产生误导性的“缺少部分文件”和未定义类错误;这些错误描述的是缺少的输出,并非真正的代码缺陷——先重新生成,再运行分析。 - 始终原样使用固定命令,并带上
--delete-conflicting-outputs。 如果不加这个参数,build_runner 会拒绝覆盖本次运行未生成的输出,并报出一大堆“输出冲突”文本。这是过时文件冲突,不是 bug——不要为此四处排查。 - 绝不手动编辑生成的文件。 下一次构建会悄无声息地还原它,并一并抹掉你的修改。请修改带注解的源文件——drift 表、freezed 类、Notifier 或 ARB——然后重新运行。
- 绝不对生成的文件运行
git add -f。 是否提交生成的代码或将其加入 gitignore,由codegen-and-toolchain负责决定;无论仓库选择哪种方式,都不要强行添加违反忽略规则的产物,也不要提交当前源代码无法重新生成的文件。 watch仅用于本地开发,不用于 CI 或提交前钩子。 CI 和分析前步骤始终使用一次性build。- 先修复手写源代码。 生成器读取的是已解析的 AST;源代码无法通过分析时,它就无法生成代码。
lib/中任何无关错误都可能阻止生成表或 provider——先清除这些错误,再判断是不是代码生成的问题。
标准命令
在软件包根目录(单软件包应用)或工作区根目录(多软件包仓库)运行:
dart run build_runner build --delete-conflicting-outputs
这是每个 CI 流程和每次全新克隆后,在格式化和分析之前执行的第一步。
全新克隆、拉取或切换分支后的标准流程
flutter pub get(解析依赖)。dart run build_runner build --delete-conflicting-outputs(重新生成)。- 然后再运行
flutter analyze。
跳过第 2 步,是代码实际没有问题的克隆版本出现分析器报错的最常见原因。
开发迭代(可选的 watch)
持续编辑带注解的源文件时,可以运行监听器代替一次性构建;它会在保存时重新构建受影响的输出:
dart run build_runner watch --delete-conflicting-outputs
运行一次性 build 前先停止监听器——两个并发的 build_runner 进程在同一代码树上运行时,会争抢输出文件。
多软件包工作区
build_runner 按软件包运行:一次调用会重新生成当前软件包及其路径依赖软件包,不会自动覆盖工作区中的所有同级软件包。因此,在工作区根目录运行单条命令,会一次性覆盖根软件包及其路径依赖;但如果根目录只是一个协调器,本身并不依赖每个成员软件包,就不会重新生成那些同级软件包。要完整重新生成多个软件包,请使用仓库级的扇出包装器(例如 melos run gen),让它在每个工作区成员上运行该命令;工作区完成引导后,优先使用这种方式。开发时若要有意将范围限定在单个软件包,请从该软件包的目录运行同一命令。生成器的范围配置(每个生成器读取哪些文件)位于各软件包的 build.yaml 中,由 codegen-and-toolchain 负责。
代码生成与分析器不一致时
分析器读取磁盘上的文件;build_runner 则会写入文件。出现不一致几乎总是因为磁盘上的内容未更新,而不是代码有误。
| 症状 | 处理方法 |
|---|---|
| 分析器提示某个类或 getter 未定义,但代码生成本应生成它 | 重新运行固定版本的构建,然后重启分析服务器。不要去“修复”调用处。 |
在 *.g.dart / *.freezed.dart / *.drift.dart 文件内部报告错误 | 文件已过时,或分析器的排除规则有误。先重新生成;切勿手动编辑生成的输出。 |
| build_runner 在手写源代码中报告分析器错误并失败 | 修复手写源代码——生成器无法解析无法分析的 AST。 |
| 大量显示“Conflicting outputs” | 使用 --delete-conflicting-outputs 重新运行;它会清除重命名或删除源文件留下的过时输出。 |
反模式
- 在全新代码树上先运行
flutter analyze——你会追查重新生成后就会消失的虚假缺少 part 错误。 - 省略
--delete-conflicting-outputs——首次重命名或删除时,就会因过时输出冲突而导致整个运行失败。 - 手动编辑
.g.dart/.freezed.dart/.drift.dart——下次构建会还原修改;应在带注解的源代码中修复。 - 对被 git 忽略的生成文件运行
git add -f——这会绕过仓库对提交与忽略生成代码的决策,并提交可能已过时的产物。 - 在 CI 或 pre-commit 钩子中运行
build_runner watch——结果不确定;CI 必须使用一次性build。
完成标准
- 在包/工作区根目录运行了固定版本的
dart run build_runner build --delete-conflicting-outputs,且没有出现“conflicting outputs”错误。 - 此命令在
flutter analyze之前运行,且现在分析通过。 - 没有手动编辑或强制添加任何生成文件。
- CI 或钩子中没有配置
build_runner watch进程。
相关技能
- 关于本操作指南背后的知识,请参阅
codegen-and-toolchain:build.yaml构建器范围设置、提交生成代码与将生成代码加入 gitignore 的决策、SDK 固定版本,以及针对生成文件的分析器/覆盖率排除规则。 - 关于 drift 架构快照和迁移流程,请参阅
run-migration;该流程会在此代码生成步骤中调用drift_dev make-migrations。 - 关于会重新运行此命令并比较代码树差异的 CI 新鲜度检查,请参阅
ci-pipeline-and-gates。 - 关于将生成文件排除在 lint 范围之外的分析器排除规则,请参阅
lint-and-style-config。
参考资料
- build_runner:https://pub.dev/packages/build_runner
- Dart 工具 — build_runner 用法:https://dart.dev/tools/build_runner
- drift 代码生成:https://drift.simonbinder.eu/docs/getting-started/
- freezed:https://pub.dev/packages/freezed
- riverpod_generator:https://pub.dev/packages/riverpod_generator