| name | fl-code-generation |
| description | Runs build_runner across core, data_source, and apps/main via the makefile after edits to freezed/injectable/retrofit sources (and the optional Hive type adapters) |
| license | MIT |
| metadata | {"audience":"flutter-developers","framework":"flutter","pattern":"code-generation"} |
Code Generation Skill
When to use
After editing any file annotated with @freezed, @JsonSerializable/@JsonKey, @Injectable/@LazySingleton/@Singleton/@module, @RestApi, @FlRouteProvider, the optional @HiveType, or that declares a _StateData for a bloc.
Commands
The makefile is the canonical interface. It auto-detects fvm if present and falls back to the system Flutter SDK.
| Command | What it runs |
|---|
make gen_all | gen_core → gen_data_source → gen_main (full graph) |
make gen_main | build_runner build only inside apps/main/ |
make gen_core | build_runner build only inside core/ |
make gen_data_source | build_runner build only inside modules/data_source/ |
make gen | Interactive picker for the same targets |
make lang | Regenerates app_localizations_*.dart from localizations.csv |
make asset | Regenerates the asset accessor under each package |
make format | dart format . across the repo |
make pub_get | pub get across plugins, core, main |
When you don't know the scope of your change, run make gen_all. It's slower but never wrong.
Generated files
| Pattern | Producer | Hand-edit? |
|---|
*.freezed.dart | freezed | Never |
*.g.dart | json_serializable, retrofit (and hive_ce, when used) | Never |
*.config.dart | injectable | Never |
app_localizations*.dart | flutter intl tooling via make lang | Never |
All generated files are committed to source control — CI does not regenerate them.
When generation fails
- Stale cache —
dart run build_runner clean from inside the failing package, then re-run make gen_<scope>.
- Missing
part directive — every freezed/json/retrofit source needs the matching part 'foo.freezed.dart'; / part 'foo.g.dart';.
- Missing
sealed — freezed unions and the bloc _StateData require sealed class.
- Missing
@Default(...) — non-nullable fields without a default break codegen.
- Conflicting outputs — the makefile already passes
--delete-conflicting-outputs; if you're invoking dart run build_runner directly, do the same.
Watch mode
Useful while iterating on a single package:
cd apps/main
fvm dart run build_runner watch --delete-conflicting-outputs
Stop with Ctrl-C. Don't leave it running in CI.
CI hook
For a pre-commit/CI gate, run make gen_all and then assert that no generated artifacts changed:
make gen_all
git diff --exit-code -- '**/*.freezed.dart' '**/*.g.dart' '**/*.config.dart' \
'apps/main/lib/l10n/generated/**'
Checklist
Common mistakes
- Running
dart run build_runner build without --delete-conflicting-outputs and stopping at the first conflict.
- Editing
*.freezed.dart to silence an analyzer warning — fix the source instead.
- Forgetting that
make gen_main does not touch core/ or modules/data_source/. When core types change, run make gen_all.
Related