# Code Generation (build_runner)

> **PENTING:** `build_runner` di proyek ini **tidak bisa** dijalankan dengan Flutter 3.47 / Dart 3.13.
> Gunakan SDK Flutter 3.41.9 (Dart 3.11.5) lewat FVM. Aplikasinya sendiri tetap di-`run`/`build`
> dengan Flutter versi global (3.47).

---

## TL;DR

PowerShell (Windows):

```powershell
$FVM = "$env:USERPROFILE\fvm\versions\3.41.9\bin"

& "$FVM\flutter.bat" pub get                                        # 1. resolve paket dgn Dart 3.11.5
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs   # 2. generate
flutter pub get                                                      # 3. balik ke SDK global 3.47
```

Git Bash:

```bash
FVM=~/fvm/versions/3.41.9/bin

"$FVM/flutter.bat" pub get
"$FVM/dart.bat" run build_runner build --delete-conflicting-outputs
flutter pub get
```

Durasi normal: **±90–120 detik** untuk full build (146 output).

Setelah itu jalankan `flutter analyze` untuk memastikan hasil generate bersih.

---

## Kenapa harus SDK terpisah?

Kalau codegen dijalankan dengan Flutter global (3.47 / Dart 3.13), semua builder gagal dengan:

```
W SDK language version 3.13.0 is newer than `analyzer` language version 3.9.0.
E freezed on lib/application/.../category_analytic_loader_bloc.dart:
  Exception: Missing implementation of visitDotShorthandPropertyAccess
```

Rantai penyebabnya:

1. `freezed 2.5.8` membatasi `analyzer <8.0.0`, jadi pub me-resolve ke **analyzer 7.7.1** (language version 3.9).
2. Dart 3.13 memakai sintaks *dot-shorthand* (`.value`) di sumber SDK/framework.
3. Analyzer 7.7.1 bisa mem-*parse*-nya tapi belum bisa menuliskannya ke summary → crash saat resolve.
4. Semua generator (`freezed`, `json_serializable`, `injectable_generator`, `auto_route_generator`) berbagi analyzer yang sama, jadi semuanya ikut mati — termasuk saat men-generate file lama yang tidak diubah.

Dart 3.11.5 (Flutter 3.41.9) adalah versi tertinggi yang **masih cocok dengan analyzer 7.7.1** sekaligus memenuhi batas `pubspec.lock` (`dart >=3.11.0-0`).

---

## Setup sekali di mesin baru

```powershell
dart pub global activate fvm
```

Tambahkan folder binari pub ke PATH agar perintah `fvm` dikenali:
`%LOCALAPPDATA%\Pub\Cache\bin`

Lalu unduh SDK-nya (±1 GB, sekali saja):

```powershell
fvm install 3.41.9
fvm list          # verifikasi
```

SDK tersimpan di `%USERPROFILE%\fvm\versions\3.41.9` dan **tidak** mengubah Flutter global.

> Kita sengaja **tidak** menjalankan `fvm use`, supaya repo tidak punya `.fvmrc`/`.fvm/`
> dan IDE tetap memakai Flutter 3.47 untuk menjalankan aplikasi.
> Kalau lebih suka pin per-project, jalankan `fvm use 3.41.9` lalu pakai `fvm dart run build_runner ...`,
> dan tambahkan `.fvm/` ke `.gitignore`.

---

## Perintah harian

Semua contoh memakai variabel `$FVM` dari bagian TL;DR.

```powershell
# build sekali (paling sering dipakai)
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs

# mode watch saat banyak mengubah anotasi
& "$FVM\dart.bat" run build_runner watch --delete-conflicting-outputs

# hanya membersihkan output generated
& "$FVM\dart.bat" run build_runner clean
```

Wajib generate ulang setiap kali mengubah/menambah file dengan anotasi:

| Anotasi | Generator | Output |
| --- | --- | --- |
| `@freezed` | freezed | `*.freezed.dart` |
| `@JsonSerializable` / `fromJson` di DTO | json_serializable | `*.g.dart` |
| `@injectable`, `@LazySingleton` | injectable_generator | `lib/injection.config.dart` |
| `@RoutePage()` | auto_route_generator | `lib/presentation/router/app_router.gr.dart` |
| asset baru di `assets/` | flutter_gen_runner | `lib/presentation/components/assets/assets.gen.dart` |

### Localization (i18n) — tidak lewat build_runner

`flutter gen-l10n` memakai tooling Flutter, bukan analyzer, jadi **aman dijalankan dengan Flutter 3.47**:

```powershell
flutter gen-l10n
```

Jalankan setiap kali `lib/l10n/app_id.arb` / `app_en.arb` berubah. Hasilnya: `lib/l10n/app_localizations*.dart`.

---

## Aturan penting soal `--delete-conflicting-outputs`

Flag ini **menghapus dulu** semua file generated (±55 file `*.freezed.dart` / `*.g.dart`) sebelum membuat ulang.
Kalau proses dibatalkan di tengah jalan, project akan penuh error karena file-nya sudah hilang.

Pemulihan (semua file generated ikut ter-commit di git):

```bash
git status --porcelain | grep -E "^ D" | sed 's/^ D //' | while read -r f; do git checkout -- "$f"; done
```

Tips: jangan pipe output build ke `tail`/`head` — outputnya jadi ter-buffer sampai proses selesai,
sehingga terlihat seperti *hang* padahal sedang jalan.

---

## Troubleshooting

| Gejala | Penyebab | Solusi |
| --- | --- | --- |
| `Missing implementation of visitDotShorthandPropertyAccess` | codegen dijalankan dengan Flutter global 3.47 | pakai SDK FVM 3.41.9 |
| `Failed to update packages` + dump stack VM | `flutter pub run build_runner` / `fvm spawn ... pub run` | pakai `dart.bat run build_runner`, jangan `flutter pub run` |
| Ratusan error “isn't defined” di IDE, file `*.freezed.dart` hilang | build dibatalkan setelah `--delete-conflicting-outputs` | restore lewat `git checkout` (lihat di atas) |
| `pub get` gagal / versi paket bergeser | `pubspec.lock` di-resolve oleh SDK berbeda | jalankan `flutter pub get` dengan SDK global setelah codegen selesai |
| Build terasa lama di run pertama | asset graph baru dibuat dari nol | wajar, ±90–120 detik; run berikutnya inkremental |

---

## Rencana jangka panjang

Perbaikan permanen = upgrade toolchain codegen supaya jalan native di Dart 3.13:

- `freezed` 2.5.8 → 3.x, `freezed_annotation` 2.4.x → 3.x
- `injectable` 2.x → 3.x, `injectable_generator` 2.7 → 3.x
- `auto_route` 9.x → 11.x, `auto_route_generator` 9.x → 10.x
- `build_runner` → 2.16.x, `json_serializable` → 6.14.x (analyzer ikut naik ke 13.x)

Konsekuensinya breaking dan cukup besar, jadi perlu dijadwalkan sendiri:

- freezed 3 **menghapus** `.map()` / `.when()` / `.maybeWhen()` / `.maybeMap()` → ±49 pemakaian (mayoritas di handler event BLoC) harus diganti pattern matching Dart 3 (`switch`).
- ±98 file dengan `@freezed` harus dideklarasikan `abstract class` atau `sealed class`.
- Migrasi konfigurasi router (auto_route 11) dan DI (injectable 3).

Selama migrasi itu belum dikerjakan, gunakan alur FVM di dokumen ini.
