Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9bcdbfa

Browse files
[nnbd_migration] Update README
Change-Id: Idc81bbebadbe3d6111a6e7e31ee0c68a30d8ff26 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148795 Reviewed-by: Devon Carew <[email protected]> Reviewed-by: Janice Collins <[email protected]>
1 parent b467ba5 commit 9bcdbfa

File tree

1 file changed

+105
-52
lines changed

1 file changed

+105
-52
lines changed

pkg/nnbd_migration/README.md

Lines changed: 105 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,138 @@
11
# Null Safety Migration Tooling
22

3-
Note: the null safety migration tooling and workflow is in an early state;
4-
this doc will be updated as the steps and workflow are simplified.
3+
Note: the null safety migration tooling is in an early state and may have bugs
4+
and other issues.
55

6-
## Building the NNBD sdk
6+
For best results, use SDK version 2.9.0-10.0.dev or higher.
77

8-
In order to run the tool currently you have to be able to build your own copy
9-
of the Dart SDK.
8+
## How Migration Works
109

11-
To do this, run:
10+
The migration uses a _new interactive algorithm_ designed specifically for Dart
11+
null safety.
1212

13-
```
14-
./tools/build.py -mrelease --nnbd create_sdk
13+
Typical code migration tools are designed to be run once, handle most cases, and
14+
let the developer do manual cleanup on the result. This does **not work well**
15+
for Null-Safety and attempting this workflow will result in a lot more manual
16+
work. Similarly, after your migration has been applied, the migration **cannot
17+
be rerun** without first reverting it.
18+
19+
### Why does the interactive approach save so much time?
20+
21+
Remember that Dart already has nullable types. Every type in old Dart code is
22+
nullable! What old Dart lacks is _non-null_ types.
23+
24+
And like most migrations, our tool tries to preserve your code's current
25+
behavior. In the case of null safety, we may mark a lot of your types as
26+
nullable -- because they really were nullable before.
27+
28+
Nulls are traced through your program as far as they can go, and types are
29+
marked nullable in this process. If the tool makes a single mistake or choice
30+
you disagree with, it can lead many excess nullable types.
31+
32+
### Interactive feedback to the tool
33+
34+
Unintentional null is the top cause of crashes in Dart programs. By marking your
35+
intention with comments like `/*?*/` and `/*!*/`, we can stop these
36+
unintentional nulls from spreading through your program in your migrated code.
37+
Adding a small number of these hints will have a huge impact on migration
38+
quality.
39+
40+
The high level workflow of the tool is therefore driven through an interactive
41+
web UI. After running `dart migrate`, open the resulting url in a browser. Scan
42+
through the changes, use the "nullability trace" feature to find the best place
43+
to add a nullability hint (adding a hint in the best place can prevent dozens of
44+
types from being made nullable). Rerun the migration and repeat, committing the
45+
hints as you go. When the output is correct and acceptable, apply the migration
46+
and publish your null safe code!
47+
48+
For example,
49+
50+
```dart
51+
List<int> ints = const [0, null];
52+
int zero = ints[0];
53+
int one = zero + 1;
54+
List<int> zeroOne = [zero, one];
1555
```
1656

17-
The NNBD sdk now lives under the ReleaseX64NNBD sub-directory of your build
18-
directory, e.g.
57+
The default migration will be backwards compatible, but not ideal.
1958

59+
```dart
60+
List<int?> ints = const [0, null];
61+
int? zero = ints[0];
62+
int one = zero! + 1;
63+
List<int?> zeroOne = <int?>[zero, one];
2064
```
21-
xcodebuild/ReleaseX64NNBD/dart-sdk/
65+
66+
`zero` should not be marked nullable, but it is. We then have cascading quality
67+
issues, such as null-checking a value that shouldn't have been marked null, and
68+
marking other variables as null due to deep null tracing. We can fix this all by
69+
adding a single `/*!*/` hint.
70+
71+
```dart
72+
List<int?> ints = const [0, null];
73+
int/*?*/ zero = ints[0]!; // Just add /*?*/ here, the migration tool does the rest!
74+
int one = zero + 1;
75+
List<int> zeroOne = <int>[zero, one];
2276
```
2377

78+
If you add one hint before migrating, you have done the equivalent of making
79+
five manual edits after migrating. To find the best place to put your hints, use
80+
the preview tool's nullability trace feature. This lets you trace back up to the
81+
root cause of any type's inferred nullability. Add hints as close to the
82+
original source of null as possible to have the biggest impact to the migration.
83+
84+
**Note**: The migration tool **cannot be rerun on a migrated codebase.** At
85+
that point in time, every nullable and non-nullable type is indistinguishable
86+
from an **intentionally** nullable or non-nullable type. The opportunity to
87+
change large numbers of types for you at once without also accidentally changing
88+
your intent has been lost. A long migration effort (such as one on a large
89+
project) can be done incrementally, by committing these hints over time.
90+
2491
## Migrating a package
2592

26-
- build a NNBD version of the SDK (see above)
2793
- select a package to work on
28-
- in that package, edit the `analysis_options.yaml` to enable the NNBD
29-
experiment from the POV of the analyzer:
30-
```yaml
31-
analyzer:
32-
enable-experiment:
33-
- non-nullable
34-
```
35-
- run `pub get` for the package (and, verify that the
36-
`.dart_tool/package_config.json` file was created)
94+
- run `pub get` for the package
3795

3896
Then, run the migration tool from the top-level of the package directory:
3997

4098
```
41-
<sdk-repo>/xcodebuild/ReleaseX64NNBD/dart migrate .
99+
dart migrate
42100
```
43101

44-
The migration tool will run, print the proposed changes to the console, and
45-
display a url for the preview tool. Open that url from a browser to see a rich
46-
preview of the proposed null safety changes.
102+
The migration tool will run and display a url for the web UI. Open that url from
103+
a browser to view, analyze, and improve the proposed null-safe migration.
47104

48105
## Using the tool
49106

50107
1. Run the tool (see above).
51-
2. Once analysis and migration suggestions are complete, open the indicated url
52-
in a browser.
53-
3. Start with an important or interesting file in your package on the left
54-
side by clicking on it.
108+
2. Once analysis and migration is complete, open the indicated url in a browser.
109+
3. Start with an important or interesting file in your package on the left side
110+
by clicking on it.
55111
4. Look at the proposed edits in the upper right, and click on them in turn.
56112
5. If you see an edit that looks wrong:
57113
1. Use the "trace view" in the bottom right to find the root cause
58-
2. Go to your editor and make a change to the original file by adding a hint
59-
(`String foo` ==> `String/*!*/ foo`) or making other changes as needed.
60-
3. You can have the migration tool perform this itself, although right now
61-
for large packages this takes a prohibitively long time.
62-
1. ***Warning: DO NOT mix edits in your editor and edits applied by the
63-
migration tool. We have not yet written the necessary logic to
64-
prevent the migration tool from clobbering files edited while the
65-
preview tool is running.***
66-
2. To try this, from the 'Edit Details' area in the bottom right select
67-
the `Force type to be non-nullable` or `Force type to be nullable`
68-
links. These will add the indicated hints on disk and recompute the
69-
migration suggestions.
70-
6. After some edits are complete, control-C the migration and rerun it. If
71-
some things are still wrong, return to step 5.
72-
7. Once all edits are complete and you've rerun migration and are satisfied with
73-
the output:
114+
2. Either click on an "add hint" button to correct it at the root, or open
115+
your editor and make the change manually.
116+
1. Some changes are as simple as adding a `/*!*/` hint on a type. The
117+
tool has buttons to do this for you.
118+
2. Others may require larger refactors. These changes can be made in
119+
your editor, and may often be committed and published immediately.
120+
3. Periodically rerun the migration and repeat.
121+
6. Once you are satisfied with the proposed migration:
74122
1. Save your work using git or other means. Applying the migration will
75-
overwrite the existing files on disk.
76-
2. Rerun the migration with `--apply-changes`, or click the
77-
`Apply Migration` button in the interface.
78-
8. Remove any SDK constraint in your pubspec.yaml.
79-
9. Remove any opt-out comments in your library files (e.g.: `// @dart = 2.6`).
80-
10. Rerun `pub get` and test your package.
123+
overwrite the existing files on disk.
124+
2. Rerun the migration by clicking the `Apply Migration` button in the
125+
interface.
126+
3. Tip: leaving the web UI open may help you if you later have test failures
127+
or analysis errors.
128+
7. Rerun `pub get` and test your package.
129+
1. If a test fails, you may still use the preview to help you figure out
130+
what went wrong.
131+
2. If large changes are required, revert the migration, and go back to step
132+
one.
133+
8. Commit and/or publish your migrated null-safe code
81134

82135
## Providing feedback
83136

84137
Please file issues at https://github.com/dart-lang/sdk/issues, and reference the
85-
`analyzer-nnbd-migration` label (you may not be able to apply the label yourself).
138+
`analyzer-nnbd-migration` label (you may not be able to apply the label yourself).

0 commit comments

Comments
 (0)