Previously, if the migration tool encountered a Future expression with
a bad type (e.g. a Future<String?> where a Future<String> was needed),
it would "fix" the problem by introducing a cast. That is nearly
always the wrong thing to do; what we want to do is null check the
value that the future *completes* with.
This CL changes the migration tool so that it fixes this case by
appending `.then((value) => value!)` to the future expression.
Fixes#45472.
Bug: https://github.com/dart-lang/sdk/issues/45472
Change-Id: I7a35b54f673936e2e4b0f8f3a077ba8bf684b4eb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193700
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Instead of running `pub outdated` to see if the user's dependencies
have been migrated yet, the migration tool now examines all of the
transitive import dependencies of the user's code to see if they are
opted in to null safety. This produces a more accurate result than
`pub outdated`, because it is able to ignore files in transitive
package dependencies that aren't reachable via imports
(e.g. references to `package:analyzer` brought in by `package:test`).
Fixes#44061.
Bug: https://github.com/dart-lang/sdk/issues/44061
Change-Id: I38465bcbf35e8552f0060b5d51c0f1cfc5d18c7f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170561
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
With this change, the functionality of changing iterable method calls
such as `.firstWhere` into extension method calls such as
`.firstWhereOrNull` is working well enough that I think we can switch
it on.
We don't update the pubspec properly yet; that will be addressed in
follow-up CLs.
Change-Id: I758332e9752b12d399ecb5c70cf37bbc8da77d6c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168988
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Previously UnitInfo.regions contained just information about edits
that we wanted to alert the user about; it didn't contain information
about unimportant edits like adjusting whitespace.
This caused problems when trying to make complex edits (like those
necessary to transform a `.firstWhere` call into a `.firstWhereOrNull`
call) because it interfered with UnitRenderer._computeRegionContent's
ability to properly compute file offsets.
So we now include all edits in UnitInfo.regions, and we distinguish
the unimportant ones by seeing that their `kind` and `explanation`
fields are `null`.
To ensure that important edits never wind up with `null` values for
these fields, we add assertions to the `NullabilityFixDescription`
constructor.
Change-Id: I89928150eb507524222d03acfae0b4770363443c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168985
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This logic allows us to migrate code like this:
int firstEven(Iterable<int> values)
=> values.firstWhere((i) => i.isEven, orElse: () => null);
Into:
import 'package:collection/collection.dart' show IterableExtension;
int? firstEven(Iterable<int> values)
=> values.firstWhereOrNull((i) => i.isEven);
Rather than the default behavior, which would migrate it to:
int? firsteven(Iterable<int?> values)
=> values.firstWhere((i) => i!.isEven, orElse: () => null);
(The new migration is far superior because it doesn't require the
input iterable to accept null).
This functionality is disabled at the moment, because:
- The changes it makes don't show up properly in the web preview.
- The pubspec is not yet properly updated.
I will address these issues in follow-up CLs and then enable the
feature.
Change-Id: I96f3b12d682c586631920b38406bad6aa3f4789e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168500
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
We produce a diagnostic under the following conditions:
- For compound assignments, if the type read from the LHS is nullable
(this is illegal after NNBD, and requires user intervention to fix).
- For compound assignments, if the type returned from the combiner is
not assignable to the LHS (this was required prior to NNBD, but it
is a stricter condition after migration, both because the LHS might
have a non-nullable type, and because implicit downcasts are not
allowed).
- For null-aware assignments, if the type read from the LHS is
non-nullable (this indicates that once strong mode is enabled, the
assignment will be dead code).
Bug: https://github.com/dart-lang/sdk/issues/38676
Change-Id: Icb242ba36437e38364ada069880831eb05e3a513
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145664
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Fixes https://github.com/dart-lang/sdk/issues/38291
This change also involves moving the "package" where test sources are
written and analyzed; It used to be /home/test (or /project in some
places); and a pubspec.yaml was written (or a .packages file) which
specified the package's name was "test". However, this conflicts with
adding an entry for a mock copy of the actual _test_ package. A
.packages file cannot have two entries for a package named "test", so
the package where all test sources are written is changed to "tests"
(located at /home/tests).
Change-Id: I462b88a814931dc2d4f1e72d07e3daf64768a399
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144994
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Previously we considered such code "dead", but it's not really dead
until Dart 3.0. Removing it changes weak mode semantics, and we don't
want to do that automatically.
Fixes#41231
Change-Id: I6a88f016b4f3fcba160dcb738558867219715cbb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143941
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Technically, accepting a hint requires two edits, one to remove the
`/*` and one to remove the `*/`. But we only want it to show up as
one edit in the "Proposed Edits" pane.
Fixes#38471
Change-Id: Ica7880a2ffab98715a1c9f3bbe723363fd481086
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143484
Reviewed-by: Samuel Rawlins <srawlins@google.com>
We now sort changes into the following categories (in order):
- Dead code removals
- Casts added
- Null checks added
- Required keywords added
- Types made nullable
- Casts now unnecessary
- Language version comments removed
The reasoning is that this corresponds roughly to how important it is
for a human to inspect each kind of change to make sure it is safe
(dead code removals, for example, are highly likely to indicate an
incorrect migration, where as dropping of unnecessary casts is benign
and almost certainly correct).
Change-Id: I49e3adac3ac98de1a9298f9caadb76c73a9c67d9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/142542
Reviewed-by: Janice Collins <jcollins@google.com>
The values discardCondition, discardElse, discardIf, discardThen, and
removeNullAwareness are all variants of dead code removal and there's
no reason to distinguish them.
Change-Id: Id55035486e07f52e6ef7b5a2485dcb0cadb153e1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/142060
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
When migrating an unnecessary "if" test like this one:
if (x != null) {
Do something;
} else {
Do something else;
}
We make two modifications to the user's file:
- Drop "if (x != null) {"
- Drop "} else { Do something else; }"
With this change, the first modification has a description of
NullabilityFixDescription.discardCondition and the second has a
description of NullabilityFixDescription.discardElse. Previously,
both modifications had a description of
NullabilityFixDescription.discardElse, which was confusing.
Change-Id: I6407d7616b7a2d2c8af853ab48c3480959c4fdb9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132682
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Now there are only two circumstances in which an AtomicEdit won't have
information about the reason for the change:
- The AtomicEdit object was associated with adding or removing parens,
in which case we don't compute information about the reason for the
change because it's not straightforward to compute, and it should be
clear to the user anyway.
- Information about the reason for the change hasn't been plumbed
through properly (this should be addressed in follow-up CLs).
Since we are rapidly approaching a situation where nearly all
AtomicEdits will have reason information, the separation between
AtomicEdit and AtomicEditWithInfo now seems silly, so I just moved the
`info` object into AtomicEdit and removed AtomicEditWithInfo entirely.
Change-Id: I61afd9cd58b71d4695685e65d0142a2693b8e6b2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132451
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
The new FixBuilder component of the migration engine communicates the
changes it produces using a "changes" data structure of type Map<int,
List<AtomicEdit>>, and is not compatible with the old
SingleNullabilityFix class (which made the incorrect assumption that
each SourceEdit was associated with a single fix). This CL changes
the migration engine's instrumentation API to use this data structure,
and changes its listener API to avoid reference to the
SingleNullabilityFix class. This allows SingleNullabilityFix to be
deleted.
This required changing AtomicEditWithReason so that it can hold
multiple fix reasons, and a NullabilityFixDescription. It does so
using a new object, AtomicEditInfo, and AtomicEditWithReason is
renamed to AtomicEditWithInfo.
In addition, the old FixInfo class is removed, since it carries the
same information as the new AtomicEditWithInfo class.
This required deleting the "incremental workflow" functionality from
UnitRenderer. This functionality was disabled, and I believe it
wouldn't have worked anyway (since it, too, made the incorrect
assumption that each SourceEdit was associated with a single fix).
Change-Id: Id965cfd803b408c66f15436017b87fc3e46521c6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132306
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
In later CL's, I will make it possible for dead code to be deleted
instead of commented out. This change prepares for that, by
explicitly noting which API tests assume that dead code is commented
out.
Change-Id: I4e0ff6f1de4c0ab5fda050956944725b2d23dc5e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/130931
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Details provide a way for clients to provide navigation support. I'm
imagining that the description could be used as link text.
The deatils are currently more of a data dump than information. I need
to see more migration results in order to figure out when and how to
pare down the data into actionable information.
We might want to capture all of the navigation targets as we build the
info so that we can create anchors in the HTML.
Change-Id: Ie48622ce7d935d3c028ea42e51cfc8da590db149
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118908
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This interface is a callback interface that allows the client to
receive detailed information about the decisions made by the migration
tool, and the source code locations associated with those decisions.
The idea is that a client of this interface can put together a report
to the user to help them understand the behavior of the migration
tool.
The instrumentation interface mostly exposes internals of the
migration engine through some safe, non-destructive interfaces. The
interface itself is documented in the new file
pkg/nnbd_migration/lib/instrumentation.dart. For examples of what
information the client can expect to receive through the
instrumentation interface, see the new file
pkg/nnbd_migration/test/instrumentation_test.dart.
Change-Id: I079551922bff75e0e8d290819f31533c29d7b62f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117285
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>