When upgrading a large Dart or Flutter codebase to a new SDK, how do you use dart fix to migrate deprecated APIs safely?
answer
- preview before you write
- only diagnostics that have fixes
- data-driven fixes shipped with packages
- --code narrows to one diagnostic
- review the diff, then analyze
basics
~20 sRun dart fix --dry-run to list proposed fixes per file, then dart fix --apply, optionally narrowed with --code to one diagnostic. It fixes diagnostics that have automated fixes, including data-driven API migrations that SDKs and packages ship.
solid answer
~50 s`dart fix` asks the analysis server for every diagnostic in the target that has an automated fix and applies them in bulk. It needs a mode: `--dry-run` (`-n`) lists proposed fixes by file and code; `--apply` writes them; with neither it only prints usage. Beyond compile errors and enabled lints, it applies **data-driven fixes**: SDKs and packages ship `fix_data.yaml` rules that rename or rewrite deprecated APIs, which is how SDK upgrades migrate call sites. On a large codebase: upgrade the SDK and run `dart pub get`, run `--dry-run` and read the counts, apply on a clean branch - scoping with `--code=<diagnostic>` to review one migration at a time - then run the analyzer and tests and commit the fix as its own change. Only enabled lints produce fixes, so enabling a lint can be a deliberate way to migrate a pattern.
code
bash · 5 linesdart pub get
dart fix --dry-run
dart fix --apply --code=deprecated_member_use
dart analyze
dart format .go deeper
Recall the two modes: --dry-run to preview and --apply to write the fixes.
Explain which diagnostics produce fixes, what --code does and where data-driven migration fixes come from.
Show a migration plan: upgrade and resolve, preview, apply per code in reviewable commits, then analyze, test and format.
Decide how the organisation sequences SDK upgrades across packages and uses lints plus dart fix to keep them cheap.
## What dart fix does `dart fix` is the bulk version of an IDE quick fix. It starts the analysis server on the target directory, collects every **diagnostic that has an associated automated fix**, and applies those fixes across the codebase. It covers two families of problems: - **Analysis issues** reported by the analyzer - compile errors, warnings and the **lints you have enabled** in `analysis_options.yaml` - where a fix exists. - **Outdated API usage** after an SDK or package upgrade, through **data-driven fixes**. Not every diagnostic has a fix, and lints that are not enabled produce nothing to fix. ## The two modes | Command | Effect | |---|---| | `dart fix --dry-run` (`-n`) | computes fixes and prints a summary per file and diagnostic code; writes nothing | | `dart fix --apply` | computes and writes the fixes | | `dart fix --apply --code=a,b` | applies only fixes for the named diagnostic codes | | `dart fix` (no mode) | prints usage and exits | The tool runs several passes (up to four), because applying one fix can reveal another. At the end of a dry run it prints the exact `--apply` command to run, per code or for everything. ## Data-driven fixes: how SDK migrations reach your code API authors can describe renames and signature changes in **`fix_data.yaml`** files shipped with the library. The Dart SDK carries one for its own libraries - for example the rename of the old upper-case `FileMode` constants - and Flutter ships a `lib/fix_data/` directory covering many deprecations across its libraries. When your code uses an element one of those rules matches, the analyzer reports it and `dart fix` rewrites it. A recent example: Flutter's move of Material and Cupertino into standalone packages is migrated with `dart fix --apply --code=migrate_design_widgets`, and Dart 3.13.1 fixed that fix to rewrite `export` as well as `import` URIs. ## A safe migration on a large codebase 1. **Start clean.** Commit or stash other work so the fix diff stands alone. 2. **Upgrade and resolve.** Change the SDK or package constraint and run `dart pub get`, so the analyzer sees the new APIs and their fix data. 3. **Preview.** Run `dart fix --dry-run` and read which codes dominate and how many files each touches. 4. **Apply in slices.** Use `--code=<diagnostic>` to apply one migration at a time, so each commit has one purpose a reviewer can check. 5. **Verify.** Run the analyzer and the test suite; automated fixes are mechanical and can still change behaviour at edges, such as a renamed parameter with a different default. 6. **Format.** Run `dart format` afterwards so the committed result matches the formatter's output. 7. **Handle the rest by hand.** Some deprecations have no fix; the analyzer still lists them. In a monorepo, run it per package so each package's own analysis options and dependencies apply. ## Using lints as a migration lever Because fixes only exist for reported diagnostics, you can enable a lint in `analysis_options.yaml` on purpose - the dart.dev example is `use_super_parameters` - run `dart fix --apply`, and keep the lint so the analyzer flags regressions afterwards. ## Common mistakes - Running `--apply` first on a dirty tree, mixing mechanical and manual changes. - Expecting `dart fix` to fix lints that are not enabled. - Skipping `dart pub get` after upgrading, so the new fix data is not seen. - Assuming a clean `dart fix` run means the migration is complete.
- Where do the API-migration fixes that dart fix applies after an SDK upgrade come from?From data-driven fix files shipped with the libraries: `fix_data.yaml` rules that describe renames and signature changes. The Dart SDK ships one for its libraries and Flutter ships a `lib/fix_data/` set, so upgrading and running `dart fix --apply` rewrites matching call sites.
- What does dart fix do if you pass neither --dry-run nor --apply?It prints its usage information and exits without computing or writing any fixes. You must choose preview or apply explicitly.
saying these in an interview costs you the question
- Believes dart fix fixes every analyzer diagnostic
- Expects fixes for lints that are not enabled
- Runs dart fix --apply on a dirty tree mixed with manual edits
- Thinks a clean dart fix run means the migration is finished
- Assumes dart fix applies changes when run with no flags