This mechanism is simpler, and it has the advantage that if the
preview server fails to start for some reason, we get a useful failure
message rather than a timeout.
Change-Id: I6ead899b3af02431c2a022fa104c6596ff952917
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145142
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This will allow us to publish the migration tool on pub, so that we
can ship improvements to it that aren't coupled to SDK releases.
As of this CL, basic read-only functionality of the preview site is
working. However, the ability to apply migrations and add hints to
existing code has not yet been tested.
Change-Id: Ib1588e741efa7be7861fa75b962fd1565765e794
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144808
Reviewed-by: Janice Collins <jcollins@google.com>
Previously, all parameters returned by
MigrationResolutionHooksImpl.getExecutableParameters were synthetic
ones that came from translating the executable element's decorated
function type to its final post-migration type. Synthetic parameters
can't be field formal parameters, so this meant that when the
FixBuilder was re-resolving a constructor containing field formal
parameters, references to the field in the constructor body would get
incorrectly interpreted as pointing to the parameter rather than the
field, and that would cause them to be subject to promotion.
The fix is to only return synthetic parameters from
MigrationResolutionHooksImpl.getExecutableParameters when the
executable in question is in a library *not* being migrated. When
it's in a library that *is* being migrated, we can just return all of
the executable's parameters without translating them, because we know
that the parameters themselves have been visited by the NodeBuilder
and EdgeBuilder, hence they all have thier own associated decorated
types.
Fixes#41405.
Change-Id: I5e3c411dc92fe242a959a5670b9253fbccea2b31
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144122
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Consider the following code:
int f(int i) => i == null ? null : i + 1;
Previously, migration would mark the return type of `f` as nullable
even if `i` was non-nullable. This happened because the edge
connecting the explicit `null` (in the "then branch" of the
conditional) to the return type of `f` is created after visiting the
conditional expression, so the condition guards are no longer in
scope.
With this CL, we create an extra graph node when needed to ensure that
the guard is applied to the expression type.
Change-Id: Ie00eea0b431905241612c6661d69bdb55c0910d2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144121
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This change adds the ability to detect when one branch of a
conditional expression is weak-only due to nullability. For example,
in the following code:
int f(int/*!*/ i) => i == null ? g(null) : i;
int g(int j) => ...;
the call to `g` can only happen in weak checking mode. The migrator
also now understands that j only needs to be nullable if i is
nullable.
Fixes#41555.
Partially addresses #41551.
Bug: https://github.com/dart-lang/sdk/issues/41555
Change-Id: I02c9c3072f0104db0f1a5b432fb1f2f8f06d5282
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144120
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
The new name more accurately reflects the purpose, and will make tests
less confusing when we add analysis of weak-only conditional
expressions in a follow-up CL.
Change-Id: I388f68173a1b41456690ebd0082e9c8d0ebe2e06
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144003
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
In the FixBuilder, when we are discarding one of the branches of an
if-statement or if-element due to it being weak-only, we only visit
the branch we're keeping; this avoids trying to make changes to code
that's being removed. However, if we are keeping both branches and
simply warning about one of them being weak-only, then we need to
visit both branches so that fixes are applied to both of them.
Change-Id: I26a1bfcb5f2ef4a111b1117637bce74e42d3db07
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144000
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Previously, the spaces inserted by EditPlanner.addCommentPostfix
didn't carry the correct isInformative flag, so they would show up in
final migrated output.
Change-Id: I100ba88040ebff9ae5d406c49b242f6fb17ce7b8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143887
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: 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>
Previously, if we migrated a code snippet like this:
void f(int/*?*/ i) {
/*late*/ int j = i/*!*/;
}
the migration result would leave the hints and add the hinted text,
resulting in:
void f(int?/*?*/ i) {
/*late*/ late int j = i!/*!*/;
}
We now simply remove the `/*` and `*/` surrounding each hint (with
whitespace corrections as needed), to produce:
void f(int? i) {
late int j = i!;
}
Change-Id: Ic4e1216cb4693d73d71c9ab1a37d5cc15b8ef334
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143460
Reviewed-by: Mike Fairhurst <mfairhurst@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>
Previously, when handling an override such as:
abstract class A {
int/*?*/ f();
}
class C implements A {
f() => 0;
}
we would create a union edge between the implicit return type of C.f
and the explicit return type of A.f. This was a problem because
nullability information can propagate bidirectionally through union
edges, so it could result in types unnecessarily becoming nullable,
e.g.:
abstract class A {
int/*?*/ f();
}
abstract class B {
int f(); // Should not need to be made nullable
}
class C implements A, B {
f() => 0;
}
This CL fixes the problem by just making ordinary unidirectional edges
for overrides involving inferred types.
Change-Id: I63a5f1f640b5543fcf39304087592e984aa66694
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/141853
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, null check hints were only affecting the behavior of
EdgeBuilder, which meant that we handled simple cases like:
int f(int/*?*/ x) => x/*!*/;
(because the EdgeBuilder wouldn't build an edge from the type of `x`
to the return type of `f`, so the return type of `f` would be
non-nullable int, and hence the FixBuilder would insert a `!` in order
to prevent an error).
But if there were some *other* reason for the destination type to be
nullable, then no `!` would get inserted.
This CL adds explicit logic to the FixBuilder to ensure that a `/*!*/`
hint causes a `!` to be inserted whether it's necessary or not.
Change-Id: I283bb9793d8d01408333f5b56562286bf19d8773
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140904
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, when analyzing code like:
int f() {}
We assigned a NullabilityNodeTarget for `int` that simply said it was
the return type of the element for `f`; the location of `int` in the
source code was lost. With this CL, we produce the same target, but
we preserve the location information.
Change-Id: Ibfe11485aedf208a39947e5a4903b4fa738e86a7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139954
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>