The new FixBuilder infrastructure has the ability to remove dead code
either by commenting it out or by deleting it entirely. Previous to
FixBuilder all we could do is comment it out. My intention when
landing FixBuilder was to keep this behavior so that we could make a
deliberate switch at a later time (when everything was well tested).
But I accidentally set the flag wrong for some code paths, and so
currently we delete code.
This has caused some bugs in the preview tool (which I will file in
the issue tracker shortly). In order to avoid causing problems for
members of the language team who intend to try out the tool this week,
I'm switching back to "comment code out" as a temporary measure.
Change-Id: I0ca8674b6a8d9ab23cf6726a15fa3dc1919085b4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133081
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Fixes https://github.com/dart-lang/sdk/issues/40181
As long as its possible to union a bound to a node involved in a
substitution, its possible to make a bound "exact nullable." This
implies that all instantiations of that type must be with a nullable
version of that parameter, which is not desirable for any program.
This marks new failing tests due to
https://github.com/dart-lang/sdk/issues/39404. However, re-running this
on package:collection resulted in a better migration result (no issues
from the non-nullable inferred types being made explicit or not). So my
personal feeling is this is worth landing now, however, we could land it
later.
Change-Id: I63479c5e4edecf301c27e21b5ba57508d625e8ab
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132748
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
This should be the last version before a Dart implementation.
Pins package_config to old version per SDK and dart-lang/sdk#40208,
fixes updates of repositories in place, speeds up fetching of
initial repositories, and allows fetching without recursive
dev_dependencies.
Change-Id: Ie00b5dab7fc9b34191c61cd4e2ad3f7540d71b51
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132960
Commit-Queue: Janice Collins <jcollins@google.com>
Reviewed-by: Samuel Rawlins <srawlins@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>
Addresses a concern from code review
https://dart-review.googlesource.com/c/sdk/+/129302 that
EditPlanner.surround is difficult to use correctly, by adding wrapper
methods for several common use cases that are easier to use correctly.
Also adapts fix_aggregator.dart to make use of the new methods.
EditPlanner.surround remains in the public API for EditPlanner because
there are still use cases for it that aren't supported by the wrapper
methods. My hope is that the remaining use cases are either rare
enough or trivial enough that we don't need wrappers for them; if that
proves to be incorrect we can always add more wrapper methods.
Change-Id: Ia1d6cc8b10ffaedcf8803ff7c8f9460ada1d7c4e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132462
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This CL allows tests based on AnalysisContextCollectionImpl to enable
NNBD by modifying the analysis options and introduce a different
feature set, rather than having to add virtual filesystem files to
convince the analyzer that NNBD is enabled for the package. This is
more consistent with the way we enable NNBD for other unit tests that
invoke analysis more directly, and is less sensitive to details of how
the analyzer infers the current language version.
Currently used in the migration engine's EditPlanTest, which in a
subsequent CL will need this functionality to test editing source code
that contains null checks.
Change-Id: I352fd2d7f6ee71d42f02a31714e3395567967240
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132461
Reviewed-by: Brian Wilkerson <brianwilkerson@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>
Previously, we used the offset of an AST node as a unique ID to
represent it, with a special hack to make sure we can distinguish a
generic function type from its return type (which has the same
offset). But in an upcoming CL, I will need to start associating
unique IDs with expressions, so that will bring up a whole bunch more
ambiguity.
This CL switches to a technique where we combine the offset and the
end of any source span into a single unique identifier. The algorithm
produces an output that is no larger than the square of either input.
Since we have 64-bit integers in Dart, this should be adequate for any
reasonable input file size.
Change-Id: I68ce27533eb485cc824e1080326d02de98bff1e7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132404
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>
The FixBuilder implemenation is now at feature parity with the
non-FixBuilder implementation when testing with api_test.dart, except
for one test of extension functionality (which doesn't seem worth
fixing right now, since extensions are still so rarely used).
Change-Id: I89df7ec388824fa9f4181706bfadbaeb232d2b5f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132169
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, we tried to hook in to the resolver so that every time it
tried to check the type of a TypeAnnotation, the FixBuilder would see
if it needed to add a `?` to it before letting the resolver continue.
This was clumsy and didn't catch all the TypeAnnotations. This CL
changes to a simpler technique where we simply visit all
TypeAnnotations, making note of where we need to add `?`s and updating
types, prior to re-running resolution.
Change-Id: Idf5ba286415fb2b90e2cd1d5ba3635b6b559aef6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132164
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This creates a editable repository workspace of the transitive dev
dependencies of a given pub package, assuming that package and its
dependencies are either stored at github under dart-lang/[package_name],
or special knowledge has been hardcoded into the script.
Tested on 'collection'. Packages in its transitive dev dependencies
are likely to work, others probably not.
Bug: https://github.com/dart-lang/sdk/issues/40173
Change-Id: I7c8f0d06a7d8eb1160957c3832f11b37a11ade98
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131947
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Janice Collins <jcollins@google.com>
We will need to hook into this for migration as well, because the type
arguments of typed literals will be changed by migration from star
types to either nullable or non-nullable types.
Change-Id: Ie721390effd9cf733b9f977c1ba729f6fc4b2ebb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131920
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This should make the fix builder faster, since TypedLiteralResolver
has to query the elements of various collections multiple times.
Change-Id: If49317b8e095b49b693e8a4885914a631efd6d2e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131844
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
One minor issue remains: when dead code elimination causes a
collection to become empty, migration should insert explicit type
parameter(s) to ensure that the empty collection will still get
analyzed as having the right type. This is noted in TODO comments.
Change-Id: Ibed25f6cb8ed9eec3ddccb0444178960c6b35c84
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131843
Commit-Queue: Paul Berry <paulberry@google.com>
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>
Instead of storing planIndex in the class (which makes it hard to
follow what methods are expected to update it, and consequently hard
to tell that _processPlans will process each plan exactly once), pass
it between _processPlans and _handleRemoveEditPlans so that it's
clearer how it is updated.
Change-Id: I1b03ad2b8bb0ae5e488d02827d2a4a56f37ede21
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131711
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Previously, TypedLiteralResolver obtained them from the library, but
this didn't work when the resolver was invoked by the migration tool,
because the migration tool needed to re-run migration of a non-NNBD
library using the NNBD TypeProvider and TypeResolver.
Change-Id: I73acca120a726c773c2e08b65d1227531a5fd2e1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131704
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Consider a generic AST structure like this:
A
/ \
B C
/ \
D E
Previously, if we wanted to build a "pass through" edit plan for A,
incorporating inner plans representing changes to be made to B, D, and
F, we would do the following: (1) pass each inner plan through the
_incorporateParent function, which might leave it unchanged or might
produce a plan targeted at the parent node, and then (2) ask each
inner plan for its set of changes, and produce a new plan for A
containing those changes.
The purpose of step (1) was to allow an edit plan to describe changes
that might affect the node above it. For example, changing an
expression might cause the parentheses surrounding it to become
unnecessary, so those parentheses would be removed (that's the case
that's currently implemented). Or, removing a list element from a
list might necessitate adjusting the comma before or after it, which
belongs to the parent node (this isn't implemented yet).
This had a design flaw: step (1) might produce overlapping changes.
For instance, calling _incorporateParent on the plans for D and E
might conceivably both plans for C, and those plans might try to make
overlapping (and thus incompatible) changes to node C.
It turns out that this isn't a problem for eliminating unnecessary
parens, because it's impossible for two edit plans to target two
different non-overlapping AST nodes whose parents are both the same
ParenthesizedExpression node (because a ParenthesizedExpression has
only one child). But it will be a problem for removing elements
lists, statements from blocks, declarations from classes, etc.
The new strategy is that we will bubble inner plans up the tree one
level at a time. In the example above, we would first combine the
inner plans for D and E into a pass through plan for C. Then we would
combine the plans for B and C into a plan for A. This is a bit more
work, but I believe it can be made efficient in typical use cases, and
it will avoid the problem described above because at each stage, all
the inner plans we combine will have the same parent, so it will be
tractable to figure out their interactions with each other.
Some vestiges of the old _incorporateParent approach still remain; I
plan to remove them in a follow-up CL.
Change-Id: I9ecbdb1549b949177ffc5d66447d4aede77e2dd9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131400
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
The derived class, NodeProducingEditPlan, represents an edit plan
whose effect will be to transform the source AST node into another AST
node (e.g. replace an expression with one of its subexpressions). The
base class, EditPlan, will be able to represent more general kinds of
edit plans.
Future CLs will introduce edit plans that don't result in an AST node,
e.g. an edit plan that removes a source statement or a collection
element, or an edit plan that replaces one source statement or
collection element with several.
Change-Id: I01455f643b858c6500d864be679b12768029cffb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/130941
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>