Skip to content

Add a hint if a package uses Future but does not import it from dart:async, and pubspec SDK constraint is too old #35162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
6 tasks done
stereotype441 opened this issue Nov 13, 2018 · 14 comments
Assignees
Labels
legacy-area-analyzer Use area-devexp instead. P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug
Milestone

Comments

@stereotype441
Copy link
Member

stereotype441 commented Nov 13, 2018

This would address a small, targeted subset of #34978 that we believe will be particularly troublesome for customers. Tasks to do:

  • Verify that the earliest version of the SDK in which dart:core began exporting Future was 2.1.0-dev.5.0.
  • Create a hint that fires if the user's code contains a reference to Future that would not have worked prior to the above SDK version, and the user's pubspec SDK constraint includes a lower-bound version of the SDK prior to 2.1.0-dev.5.0
  • If time allows, add logic to the analyzer to ensure that a change to the pubspec triggers re-analysis of the hint
  • If time allows, add quick fixes to allow the user to correct the hint by either:
    • adding an import of 'dart:async'
    • adjusting the pubspec as appropriate

Ideally, all these changes should be made in such a way that they can be cherry-picked to the dev branch of the SDK repo, so that they can be released as part of 2.1.1. However, if it's not feasible to do this for the "if time allows" items that's ok.

Yet to be determined (suggestions welcome):

  • What to do if the pubspec does not contain an SDK constraint? Does pub have a standard interpretation of this situation that we could follow?
  • What to do if no pubspec could be found?
  • What to do if analysis is being performed in "build mode" (i.e. when run under bazel)? (Note that bazel doesn't allow the analyzer to access files that aren't explicitly specified as sources in the BUILD declaration, so simply looking for a pubspec file won't work)
  • Do we need to address weird corner cases with re-exports (e.g. a.dart imports b.dart and uses Future; b.dart exports dart:async. Theoretically this is ok but it may not be worth trying to make the analyzer handle this case correctly)
  • If the user opts for the quick fix that changes the pubspec, should we adjust the pubspec to require 2.1.0-dev.5.0, or simply 2.1.0?
  • Pub accepts a wide variety of formats for version constraints. Does the quick fix need to be able to handle all of them?
@stereotype441 stereotype441 added P1 A high priority bug; for example, a single project is unusable or has many test failures legacy-area-analyzer Use area-devexp instead. type-enhancement A request for a change that isn't a bug labels Nov 13, 2018
@stereotype441
Copy link
Member Author

@bwilkerson or @scheglov, can one of you look into this?

@bwilkerson
Copy link
Member

Did you intend to include @pq?

What to do if no pubspec could be found?

If there's no pubspec, then I think analyzer should assume that the package is intended to work with the version of the SDK from which the analyzer is being run (that is, the latest, which means don't produce any hints).

What to do if analysis is being performed in "build mode" (i.e. when run under bazel)?

We don't use pubspec files in Bazel, so I think it should default to the behavior described above.

Do we need to address weird corner cases with re-exports ...

I think we should. I think analyzer should create a hint if Future is imported from 'core', which means that it isn't imported from any other library. I don't think it's that much harder to check.

Pub accepts a wide variety of formats for version constraints. Does the quick fix need to be able to handle all of them?

It needs to only make changes if it understands the format and can do so correctly. We might be able to look at a few well known packages on Github and see what formats are currently being used. It's possible that there's not that many being used for the SDK constraint.

@stereotype441
Copy link
Member Author

Confirmed that the earliest version of the SDK in which dart:core began exporting Future was 2.1.0-dev.5.0.

@stereotype441
Copy link
Member Author

Did you intend to include @pq?

What to do if no pubspec could be found?

If there's no pubspec, then I think analyzer should assume that the package is intended to work with the version of the SDK from which the analyzer is being run (that is, the latest, which means don't produce any hints).

What to do if analysis is being performed in "build mode" (i.e. when run under bazel)?

We don't use pubspec files in Bazel, so I think it should default to the behavior described above.

Do we need to address weird corner cases with re-exports ...

I think we should. I think analyzer should create a hint if Future is imported from 'core', which means that it isn't imported from any other library. I don't think it's that much harder to check.

Pub accepts a wide variety of formats for version constraints. Does the quick fix need to be able to handle all of them?

It needs to only make changes if it understands the format and can do so correctly. We might be able to look at a few well known packages on Github and see what formats are currently being used. It's possible that there's not that many being used for the SDK constraint.

SGTM

@pq
Copy link
Member

pq commented Nov 14, 2018

the user's pubspec SDK constraint includes a lower-bound version of the SDK prior to 2.1.0-dev.5.0

@bwilkerson : are you thinking of enhancing the existing PubspecVisitor for this? Regardless it should be updated to make environment details available to pub-related lints... Needless to say, happy to help with that.

@bwilkerson
Copy link
Member

are you thinking of enhancing the existing PubspecVisitor for this?

No, I wasn't. I don't think we need to visit the whole file to extract the sdk constraints. We should probably parse it as YAML to account for all the valid syntaxes, but we just need to extract the one value.

Ideally we'd piggy-back on top of the work that @srawlins is doing to better support a notion of packages. The constraints are specified by the package, and this would allow us to do the right thing for packages that don't use a pubspec file. Unfortunately, I don't know that we can wait that long before implementing this feature.

@stereotype441
Copy link
Member Author

Ideally we'd piggy-back on top of the work that @srawlins is doing to better support a notion of packages. The constraints are specified by the package, and this would allow us to do the right thing for packages that don't use a pubspec file. Unfortunately, I don't know that we can wait that long before implementing this feature.

Yeah, since we want to cherry-pick the fix onto 2.1.1, it can't depend on @srawlins' work. I think it's ok if the bug gets fixed in a somewhat kludgy way for now, and then as part of #34978 we can clean it up to take advantage of Sam's work.

@bwilkerson bwilkerson self-assigned this Nov 14, 2018
@JekCharlsonYu JekCharlsonYu added this to the Dart2.1 milestone Nov 16, 2018
@bwilkerson
Copy link
Member

@stereotype441
Copy link
Member Author

I did some experiments and found that cherry-picking these CLs to the dev branch leads to test failures, due to the fact that they relied on code that was in the analyzer branch but not yet landed on master. So @bwilkerson is going to try cherry-picking them to master and fixing up the resulting failures.

stereotype441 added a commit to stereotype441/flutter that referenced this issue Nov 19, 2018
In Dart SDK version 2.1.0-dev.5.0, dart:core was modified so that it
exports the classes Future and Stream.  (Previously these classes were
only available via an import of dart:async).  Some of the useages of
Future and Stream in Flutter fail to import dart:async, therefore in
order to work correctly Flutter requires Dart SDK version
2.1.0-dev.5.0 or later.

The Dart analyzer team is in the process of implementing a hint to
help users remember to update their pubspecs when using Future or
Stream and not importing dart:async
(dart-lang/sdk#35162).  In order to avoid
Flutter failing this hint when it lands, we need to update the
pubspecs now.
@stereotype441
Copy link
Member Author

There is now a fix for the first two checkboxes on master that can be cherry-picked. I've submitted a cherry-pick request here: #35232

@stereotype441
Copy link
Member Author

Remaining work is P2

@stereotype441 stereotype441 added P2 A bug or feature request we're likely to work on and removed P1 A high priority bug; for example, a single project is unusable or has many test failures labels Nov 20, 2018
@bwilkerson
Copy link
Member

The quick fixes are implemented by https://dart-review.googlesource.com/c/sdk/+/84691.

@stereotype441 stereotype441 assigned scheglov and unassigned bwilkerson Nov 26, 2018
dart-bot pushed a commit that referenced this issue Nov 27, 2018
So, analysis result signatures depend on it and recomputed when it
is changed.

Also, change analysis server to update analysis options not only
when analysis_options.yaml is changed, but also when pubspec.yaml
is changed.

[email protected], [email protected]

Bug: #35162
Change-Id: If4b937c26212d3da74ac7125eb2c6f70dbcb1793
Reviewed-on: https://dart-review.googlesource.com/c/85405
Commit-Queue: Konstantin Shcheglov <[email protected]>
Reviewed-by: Brian Wilkerson <[email protected]>
Reviewed-by: Paul Berry <[email protected]>
@Hixie
Copy link
Contributor

Hixie commented Jan 10, 2019

Isn't this kind of thing happening all the time? I mean, we keep adding features to Dart, right? Do we have a lint for each one to ask that the SDK constraint be moved up?

@natebosch
Copy link
Member

Isn't this kind of thing happening all the time? I mean, we keep adding features to Dart, right? Do we have a lint for each one to ask that the SDK constraint be moved up?

This situation was somewhat unique in the wider opportunity for misuse.

It's true that there are always new features going in and using them requires an SDK constraint. This feature looks a little different from most:

  • It's a usage by omission, you don't see a new API called in your code.
  • Future and Stream are very widespread. Adding a new constructor to StreamTransformer is seen by a tiny fraction of code compared to using Future and Stream.
  • It's triggered by common behavior of developers. It's typical to add a reference to Future and only add the import to dart:async when the the analyzer complains.

That said, I think even other changes are things we'd like to help catch, this was the most critical one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legacy-area-analyzer Use area-devexp instead. P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

7 participants