codegen-and-toolchain について
codegen-and-toolchainは、build_runnerまたはgen-l10nを使うFlutter/Dartプロジェクト向けの開発スキルです。コード生成からフォーマット、解析、テストまでの再現可能な順序に加え、生成範囲やファイル方針、ワークスペースを案内します。
主な機能
- 01決定的なコード生成ワークフロー
- 02generate_forによる生成範囲の限定
- 03生成ファイルのコミットとCI方針
- 04解析とカバレッジの除外設定
- 05SDK固定とワークスペースの指針
活用シーン
- 01アノテーション変更後のコード再生成
- 02パッケージ範囲に合わせたbuild.yaml設定
- 03生成ファイルのコミット方針の選択
- 04マルチパッケージワークスペースの設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zakariaf/ flutter-skills --skill codegen-and-toolchainインストール後、Claude Code で/codegen-and-toolchainを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/build.yamlgitattributes.examplereferences/codegen-scoping.mdcommit-vs-gitignore.mdtoolchain-and-workspace.mdscripts/check-codegen-hygiene.shregen.sh詳細
コード生成とツールチェーン
決定的なコード生成パスを唯一のソースとし、すべての生成ファイルを管理します。
まずこれを実行し、対象を厳密に絞り、出力を Git に含めるかどうかを一度だけ決定してください。
build_runner または gen-l10n を使用するプロジェクトに適用されます。
作業内容に応じて、以下のリファレンスを確認してください。
references/codegen-scoping.md— ジェネレーター一覧、generate_for:のスコープ設定表、エラーから修正へのリカバリーマップ。references/commit-vs-gitignore.md— Git にコミットする方法と Gitignore に追加する方法、 それぞれのトレードオフ、および必要となる正確な CI ゲート。references/toolchain-and-workspace.md— SDK の固定、アナライザー/カバレッジの 除外設定、およびマルチパッケージワークスペースのレイヤー構成(フェンス付き、オプトイン)。
PR の前に scripts/regen.sh(コード生成 → フォーマット → 解析)を実行し、
scripts/check-codegen-hygiene.sh を実行して、除外設定とコミットポリシーの整合性を確認してください。
必須ルール
- コード生成は
flutter analyzeより先に実行します。 新規クローンでは生成ファイルが存在しない場合や、アノテーションの編集後に古くなっている場合があります。その状態で解析すると、「missing part file」や「undefined class_$Foo」といった誤解を招くエラーが出力されます。再生成してから解析してください。呼び出し箇所で症状を追いかけてはいけません。 - 必ず
--delete-conflicting-outputsを渡します。 これがないと、build_runnerは名前変更または削除されたソースの出力を上書きできず、「conflicting outputs」という大量のメッセージとともに失敗します。これは調査すべきバグではありません。 - 生成ファイルを手作業で編集してはいけません。 次回のビルドで変更が黙って元に戻され、編集内容も失われます。アノテーションのあるソースを変更し、コード生成を再実行してください。
- パッケージごとの
build.yamlで、すべてのビルダーにgenerate_for:を設定してスコープを絞ってください。 あるディレクトリの変更によって、ツリー全体が再生成されないようにします。各グロブは、アノテーションを管理する最小のディレクトリを指定してください。 - コミットするか Gitignore に追加するかを一度だけ決定し、対応する CI ゲートを設けてください。 Gitignore に追加する場合 → CI で解析前に再生成します。コミットする場合 → CI で再生成してから、鮮度ゲートとして
git diff --exit-codeを実行します。どちらも有効ですが、ゲートのないポリシーは認められません(references/commit-vs-gitignore.mdを参照)。 - 生成ファイルのグロブをアナライザーとカバレッジの除外設定の両方に反映してください。 機械生成された出力を lint するとレビューの無駄になり、lcov にグロブがないとカバレッジが水増しされます。出力されたサフィックスを除外してください。推測せず、確認してください。
- SDK を固定し、ローカルと CI のバージョンを一致させてください。 CI の Flutter/Dart バージョンは、固定したローカルのバージョン(FVM を使う場合は
.fvmrc、またはリポジトリで標準化されたツール)と一致させる必要があります。ここに差異があると、「自分のマシンでは動く」というフォーマット/コード生成の差異が再現します。 watchはローカルの編集ループ専用ツールです。 CI と解析前のステップでは、必ず単発のbuildコマンドを使用してください。
標準コマンド
リポジトリのルートから実行します。
dart run build_runner build --delete-conflicting-outputs
これにより、すべてのビルダー(drift_dev、freezed、json_serializable、
riverpod_generator、mockito)が一度に実行されます。gen-l10n は
Flutter ツール経由で実行されますが、同様に扱います(最初に再生成し、同じコミットポリシーを適用します)。
flutter gen-l10n # if not auto-triggered by `flutter pub get` via l10n.yaml
新規クローン後、pull の後、またはアノテーションを編集した後は、次の順序で実行します。
build_runner build --delete-conflicting-outputs → format → analyze → test
コード生成を解析の後に回してはいけません。編集中のセッションに限り、保存時にウォッチャーが変更のあった出力を再生成します。
dart run build_runner watch --delete-conflicting-outputs
build.yaml でビルダーのスコープを設定する
コード生成を担う各パッケージ(または単一のアプリパッケージ)に専用の
build.yaml を用意し、各ビルダーの generate_for: を、アノテーションを管理する最小のディレクトリに限定してください。スコープを絞っていないルート設定ではツリー内のすべてのアノテーションが対象となり、Task モデルの編集で、無関係な Order や Account の出力まで再生成されます。examples/build.yaml をコピーしてください。すべてのジェネレーターとサフィックスの対応表、およびビルダーごとのグロブについては references/codegen-scoping.md を参照してください。
commit と gitignore のどちらを選ぶか:ゲートも設定する
どちらの戦略も妥当ですが、リスクの種類が異なります(ルール 5 を参照)。gitignore を使うとツリーをクリーンに保てますが、ビルドには動作するツールチェーンが必要です。コミットすれば、将来ツールチェーンが壊れても生成物が残り、スキーマの差分をレビューできますが、.gitattributes の差分を折りたたむ設定(examples/gitattributes.example)と、必須の鮮度チェックゲートが必要です。再生成してから、次を実行します。
git diff --exit-code -- '*.g.dart' '*.freezed.dart' '*.drift.dart'。ゲートのないポリシーはポリシーではありません。両方の戦略、それぞれのトレードオフ、必要となる正確なゲートについては、references/commit-vs-gitignore.md を参照してください。
Analyzer とカバレッジの除外設定
コミットする場合も gitignore にする場合も、生成されたすべてのサフィックスを Analyzer と lcov のカバレッジフィルターの両方から除外してください。まず、設定で実際に出力されるサフィックスを確認し、推測しないでください。Analyzer の glob が漏れると、機械生成の出力にレビューの手間をかけることになります。lcov の glob が漏れる、またはアンカーの指定を間違えると、テストされていないコードによってカバレッジが水増しされます。生成された時代に対応するデータクラスを保持するマイグレーションテストのベースラインディレクトリも、Analyzer から除外する必要があります。エクスポートされたスキーマスナップショット内で自動修正を行うと、マイグレーションの検証を損なう可能性があります(run-migration を参照)。正式な除外ブロックと、正しくアンカーされた lcov パターンは、references/toolchain-and-workspace.md にあります。
複数パッケージの場合(ワークスペース)
パッケージが 1 つでは対応できなくなったリポジトリに限ります。単一アプリのプロジェクトでは、これらは不要です。
- ネイティブの Dart pub ワークスペースでメンバーをリンクします。すべてのメンバーの pubspec に
resolution: workspaceを指定し、ルートにworkspace:リストを記述して、ルートに 1 つのpubspec.lockを生成します。パッケージごとのロックファイルは追加しないでください。 - Melos を重ねて使う場合は、スクリプトのオーケストレーション専用(
melos run gen/format/analyze/test)とし、パスのリンクには使わないでください。リンクは pub が行います。genスクリプトの対象は、build_runnerに依存するパッケージに絞ります。 - ワークスペースのルートで
build_runnerを 1 回実行し、すべてのメンバーを同じ実行で再生成します。1 つのパッケージディレクトリ内で実行すると、ほかのパッケージが古いままになります。
アンチパターン
- 再生成の前に解析する — 後続のエラーはすべて幻です。コードではなく、順序を修正してください。
--delete-conflicting-outputsを省略する — 通常の名前変更がビルドの障害になります。- エラーを黙らせるために
.g.dart/.drift.dartを手編集する — 次のビルドで元に戻ります。本当の修正箇所は、アノテーションを付けたソースです。 - 鮮度チェックゲートなしで生成コードをコミットする — 出力がソースと気付かれないまま乖離し、レビュー担当者は誤った内容を信頼してしまいます。
- スコープを絞らないルートの
build.yamlを 1 つ置く — 些細な編集のたびにツリー全体が再生成され、すべてのビルドが遅くなります。 - 間違ったサフィックスに一致するカバレッジ/Analyzer の glob — Analyzer ではエラーなく失敗し、lcov 2.x では大きなエラーになり、カバレッジはひそかに水増しされます。
- CI の Flutter バージョンと固定したローカルバージョンが異なる — 説明できない、再現性のないフォーマットやコード生成の差分が発生します。
- 生成されたマイグレーションテストに空のデータリストを残す — 何も証明しないまま、常に成功します(
[] == [])。データを入力するか、削除してください(run-migrationを参照)。
完了の定義
- クリーンなツリーで
dart run build_runner build --delete-conflicting-outputsが成功し、その後flutter analyzeにも問題がない。 - コード生成を行うすべてのパッケージに、スコープを絞った
generate_for:glob を含むbuild.yamlがある。 - commit と gitignore のどちらにするかが決定され、対応する CI ゲート(鮮度チェックの差分、またはコード生成を先に行う設定)がある。
- 生成されるすべてのサフィックスが、
analysis_options.yamlと lcov カバレッジフィルターの両方から除外されている。 - SDK が固定され、CI のツールチェーンバージョンがそれと一致している。
- 生成ファイルが手編集されておらず、CI で
watchを使用していない。
関連スキル
- 運用上の自由度が低い「このコマンドをそのまま実行する」ループと、そのトラブルシューティング表については、
run-codegenを参照してください。 - codegen パスで生成される Drift のスキーマスナップショットとマイグレーションテストの手順については、
run-migrationを参照してください。 - これらのジェネレーターがデータを供給する Drift/DAO データレイヤーについては、
persistence-driftを参照してください。 - ここに反映されているアナライザールールセットと除外設定については、
lint-and-style-configを参照してください。 - パイプライン内で codegen と鮮度チェックが行われる箇所については、
ci-pipeline-and-gatesを参照してください。 - ロックファイルと SDK の固定方法については、
dependency-hygieneを参照してください。
参考資料
- build_runner:https://dart.dev/tools/build_runner
- Drift の codegen とビルド設定:https://drift.simonbinder.eu/docs/advanced-features/builder_options/
- freezed:https://pub.dev/packages/freezed
- json_serializable:https://pub.dev/packages/json_serializable
- riverpod の codegen:https://riverpod.dev/docs/concepts/about_code_generation
- Flutter gen-l10n:https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization
- Dart の pub ワークスペース:https://dart.dev/tools/pub/workspaces