Currently the migrator can add `@required` from the preview, which will crash
the preview upon rerunning, if package:meta is not imported.
This change instead adds a /*required*/ hint when meta is not imported.
Additionally, /*required*/ is understood by the migrator just as if it were
`@required`.
Fixes https://github.com/dart-lang/sdk/issues/43751
Change-Id: I1ea532246b956feacedd179146372b13c65003df
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169900
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This should help ensure that descriptions of nullabilities that show
up in the stack trace refer to parts of the program the user is
familiar with, rather than simply saying "explicit type".
Change-Id: If53198cc45077a664e44859c7c0770ec9831c765
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/146964
Reviewed-by: Mike Fairhurst <mfairhurst@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>
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>
We should consider the nullability of the right hand side of a typedef
to be "never", since a `?` is not allowed on there. Instead, we
should allow each use of a typedef to have its own independent
nullability.
Fixes a bug wherein we would erroneously migrate code like this:
typedef F<T> = int Function(T);
F<String> f = null;
Into the following:
typedef F<T> = int Function(T)?;
F<String>? f = null;
(Note the bogus `?` after `int Function(T)`).
Change-Id: I8535645303fc644c73617684b8bb3488462589ee
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136900
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
We now track decorated type parameter bounds similarly to how we track
ordinary type parameter bounds in the FixBuilder, by having a single
static instance of a DecoratedTypeParameterBounds class that keeps
track of the mapping.
Change-Id: I49196e8a506ca8765857b3d47a355b7aaaa1918e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134411
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This required adding logic to the `TypeParameterType` case of the
`toFinalType` function, so that we look up the decorated type of the
type parameter bound, and convert it to a final type as well.
(Previously we were just using the bound stored in the element model,
which was in many cases the bounds from prior to migration, and hence
it was a `*` type so it behaved as though it was non-nullable).
This required moving `toFinalType` into the `Variables` class so that
it could look up the decorated types of type parameter bounds.
Fixes#40355.
Change-Id: I53c2636aef6954500589e924b9755a297c2b30f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134061
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Since https://dart-review.googlesource.com/c/sdk/+/133422 has
introduced the possibility that a node previously marked as
non-nullable would later be marked as nullable, we need to make sure
that doesn't happen for types that have been explicitly marked as
non-nullable using a "/*!*/" hint, or types that are non-nullable in
an already-migrated library.
This required refactoring the state of nullability nodes slightly.
Nodes can now be in six states:
1. Non-nullable (previously called "undetermined")
2. Non-nullable, with non-nullable intent (previously called
"nonNullable")
3. Nullable
4. Nullable, with non-nullable intent (previously indistinguishable
from 3)
5. Exact nullable
6. Exact nullable, with non-nullable intent (previously
indistinguishable from 5)
To allow all these states to be distinguished, we separate the state
into two orthogonal parts: a "nullability" part and a "non-null
intent" part.
Change-Id: I588a2e63eaa76e3992fdfbaaa2e8b212cc1f60d1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133440
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Looks like we used to do this, but we stopped when we started changing
this pattern:
```
dynamic x = 1;
int y = x;
```
Our first iteration treated `dynamic` as nullable all the time. This is
not ideal in the example above. So we went back and instead began
treating `dynamic` as nullable only when it was observed to have a null
value.
However, in the case of unbounded type parameters:
```
class C<T> {}
```
We don't want to wait to observe:
```
C<Object> o = C(null);
```
before treating the bound as nullable.
Change-Id: I50b8ca6188d82cd62f795ada99a355afe2eae771
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131714
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
Previously, when the migration engine found a type that was implicitly
or explicitly dynamic, it assumed the type was meant to be nullable.
This seemed reasonable (since, after migration, `dynamic` indeed
allows null), but it caused unnecessary nullabilities to be
propagated. With this change, the migration engine tracks whether
dynamic types can be nullable or not, just as it does for all other
types. This cleans up a number of tricky corner cases in the
migration engine that were getting in the way of fixing up uses of
`always` and `never` nodes.
Note that if a `dynamic` type is determined to be non-nullable, it
will still be `dynamic` after migration; this change merely prevents
nullabilities from being needlessly propagated from that dynamic type
to other types.
Note that we still assume `dynamic` is nullable when it occurs in an
already-migrated library or as the result of a dynamic dispatch.
Change-Id: I380d0907f3489d0b84f3fdd7164113daae24274e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/125084
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This should address ~26 exceptions whose stack trace contains the line:
Variables._createDecoratedElementType (package:nnbd_migration/src/variables.dart:230:7)
Change-Id: I69fdf75aaa1e2a9bdbaef3b49c7928812566b131
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/116083
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
I have a lot more testing of decorated types to land in follow-up CLs;
this CL introduces a mixin containing helper methods that should make
that testing a lot easier.
Change-Id: I29c17ffb4af65498fcd85704dc404343429e09ad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112847
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
We will need some special treatment for decorated type parameter
bounds, because sometimes we will need to create type parameters
(e.g. when comparing decorated types). So we store the bounds of
non-ephemeral type parameters (the ones whose enclosing element is
non-null) in the Variables data structure, and we store the bounds of
ephemeral type parameters (the ones whose enclosing element is null)
in an expando.
Change-Id: I918c9baffedab9a8871ecea37c8101b5ef44a5d9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112743
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This updates NodeBuilder so that when it visits a method declaration,
it does not count any parameters defined in body statements
as part of the parameters defined in the method signature.
Change-Id: I4da3989eb2bc65c422d94fa264885910850b0ed2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107921
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>