-
Notifications
You must be signed in to change notification settings - Fork 229
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
Better IDE support #2180
Comments
I understand that "add package UI" would require a What exactly is "install the latest package"? Do you mean Or do you mean upgrade the version in Note. programmatically modifying YAML is non-trivial if we want to preserve whitespace and comments. We could write a special parser for this, or we could drop all comments and whitespace formatting from the YAML files. |
We might need more feedback from users on this issue. One concrete enhancement the community has been working on is autocompleting package names in the IDE as seen here: https://plugins.jetbrains.com/plugin/12693-flutter-enhancement-suite |
I suppose some API on the client or server to search package names would be useful things like this. |
I can think of a few features that would make a big difference in VS Code:
Some of these could be done in VS Code by using
|
We have no such stable API. And the API we have have not best hardened to handle load from IDEs just yet.
I think this is efficient, be sure to make requests concurrently.
The API end-points documented in dartlang/pub/doc/repository-spec-v2.md is stable. These are used by the side note: please set a custom |
@DanTup, is it really only a list of all packages that we need to make a stable API for? This wouldn't be hard to add. Would we need anything else? |
I don't know how big a list like this would be, but this seems like the most sensible solution to me (we wouldn't want to send HTTP requests during typing to have the filtering done on the server if we could just cache it locally and filter it there). cc @pq in case he has any opinions about this for IntelliJ.
Perfect!
Will do, thanks! |
Some math on scalability:
Thus, 10x or even 100x would still be fine. At 1000x this would start to become problematic and the API would have to be redesigned. So an API that returns a list of all package names might be reasonable for now. If the client downloads the list of package names once per day, this should be fine in terms of load. |
That all sounds reasonable to me :) |
Thanks for looping me in! Pub package discovery is something we've ruminated about off and on for a long time.
My gut says this is a service we'd want to the analysis server to provide. Or certainly not implemented (and re-implemented) in clients. (Having it in DAS would play most naturally with improved code completion.) |
Yeah, I think this makes sense too. I was considering building a PoC directly in VS Code as an easier way to try it out - however the YAML-parsing options don't look too hot, and since I think the server already has a good parser, it might end up being easier to do there anyway. |
@jonasfj I've been thinking about this again lately (the server now has some basic support for code-completion in YAML, so it would fit in nicely there). Previously I mentioned getting just the package names, though some of the metadata (for example deprecated packages, descriptions) could also be quite useful to include in the completion data (a list of only package names alone would still be a good step though). Is there any way for me to get that data today, even if only for building a proof-of-concept (and not shipping) for now? |
@DanTup For listing all package names there: Once you have package name, using the version listing API to get the pubspec with package description, list of dependencies, and what versions of the package exists is easy. Side note: we recently added |
@jonasfj great, I'll have a look - thanks!
There are a lot of packages I think have been deleted that show up there (eg. search for "film") that maybe should be filtered out? |
@jonasfj I had a quick play with the (unstable) API mentioned above, and managed to get something working: It's currently just package names though, it'd be nice to have descriptions there. I think there are two options:
The first would significantly increase the initial payload, but would avoid additional requests as the user moves the selection through the list. The second would add many more requests, but avoid transferring a huge amount of data for the descriptions that might never be seen. What do you think would be best? Assuming the second would be best (and therefore the package-name-list API meets the needs), what would be involved in getting to a stable API to the point you'd be happy with the server using it? FWIW, some other minor things I noticed about the list that may or may not be desired:
|
This is a relic from spam fighting, they're with-held pending eventual deletion.
Legacy from when
Should be shown, but we can sort them differently client-side or serverside.
My concerns mainly related to
I suppose that if were to return:
Sorted by Depending on how cool much we can reasonably squeeze into the UI, I suppose we could later add things like:
I'm thinking we should try to compile this information and see how big it would be assuming that the number of packages can grow 10x - 100x. @isoos, any thoughts? Last thing we need is an API end-point, maybe |
That sounds perfect to me - though the latest version number would be great too - then we could complete on that too once the package name is selected.
I think that should be reasonable. If there was a way to get packages since a data (eg. created in last x days) that could allow us to update the cache without having to re-fetch the whole lot?
If the returned packages from the server depend on the project (or values in the pubspec) that might affect how we can cache it. It may be better to do that client side - although it would require having the data to do this, and may make using stale data less ideal. If this is complicated, it may be better as a future enhancement - the benefit is likely much lower than basic package name/description/version completion. |
I think the "default" sort order of pub.dev (which is currently the combination of score, likes and popularity) would be a more consistent experience. |
I did a little quick and dirty hack, fetching all pubspec and compiling data from public APIs (for ease of debugging). If we have: {
"package": "retry",
"description": "Utility for wrapping an asynchronous function in automatic retry logic with\nexponential back-off, useful when making requests over network.\n",
"tags": [
"sdk:dart",
"sdk:flutter",
"platform:android",
"platform:ios",
"platform:windows",
"platform:linux",
"platform:macos",
"platform:web",
"runtime:native-aot",
"runtime:native-jit",
"runtime:web"
],
"latest": "3.0.1",
"updated": "2020-07-01T17:29:53.216548Z",
"likes": 90
}, Then size is:
That's 1MB, I think we have to cut a few things away :D |
If this API is specifically for completion, there's probably not much value in likes/update. Tags could probably also be squashed into something simpler (I wouldn't expect to filter except maybe for Dart vs Flutter). I don't know if that makes a big enough difference though? |
I cut the description to 160 characters, as this is recommended max, but it still gets somewhat large.
If we use all the tricks in the book, single letter for property names in JSON, encode dates as unix-timestamp, and encode tags as a bitfield 🙈, then we get something like:
(Just having a little fun, I don't think encoding tags a bitfield qualifies as a good idea, hehe) Doing just
Doing
If we sort packages by a "combination of score, likes and popularity" (as @isoos suggested), then the first page is always going to be the most relevant. And whether it contains 1k packages or 10k packages doesn't matter so much.
An alternative could be do an API that takes the first 2 characters of the package name, like:
Then maybe the client would use I'm not so sure this is smart, because lots of packages starts with
I'm thinking we should cut
Yeah, I don't know how rich the interface is... but using icons to represent tags like: |
Is the intention that we'd just immediately page through everything to cache them locally? If so, beside a little longer warm-up time due to multiple requests, I think that'd work just as well to me.
Right now I only provide the list of completions at the time the IDE requests is (so the list is then filtered in the IDE). If the list is incomplete at the time the completion is invoked, some packages would just be missing. I don't think that's a big problem though if we intend to populate the cache before the user is using the completion (eg. when the server starts up, or when a pubspec.yaml file is opened).
For VS Code, the ranking we provide is used before the user has typed anything and then VS Code takes over ranking as they start typing. For the other IDEs, I'm not sure how they rank when there are fuzzy matches (@bwilkerson may know).
My current PoC is fetching the description (+ latest version number) on-demand. Pre-populating some of them from the seed data would be a trivial change. I think it'd may be weird to not have descriptions for the less-used packages though, so I think fetching those on demand would be better than not showing.
This is essentially what I'm currently doing (using the unstable API above for the package names).. it was very fast in my testing, though I don't have the version number so have to get
I think it would be a little strange if the completion list only included packages you'd used before?
For VS Code, we don't really get to delay this for 200ms. If we want to show the description against the completion we need to fetch it as soon as it's highlighted. We could artificially delay responding for 200ms (and if we're asked to cancel in that time, skip) though it'd make the descriptions appear to populate quite slowly. If we can provide a batch of descriptions for some starting characters instead of only one specific package, that may speed up showing them if the user moves through a few surrounding packages, though whether that's worth adding a new API for, I'm not sure).
That sounds reasonable to me. |
Talking with @sigurdm and @isoos today, we've agreed to do a package name listing API in I think we should do another API similar to that:
Where we filter out packages that:
And then we should introduce an API for getting the description for the latest version: This is not idea, there is a few other options I outlined in the braindump below... hehe :D But it's probably better that we ship something simple, that we can maintain over time. So let's start simple and over-engineer the solution later :D Braindump of options I was contemplatingOption (1): A package completion data API
Pros:
Cons:
Option (2): A package name completion data API
Pros:
Cons:
Option (3): A package completion data API
With following caveats documented in documentation:
Pros:
Cons:
I think we can pick between:
The behavior might feel arbitrary. But I doubt anyone will notice if unpopular packages, without many likes, that haven't been published recently are omitted. |
@DanTup wdyt? would what I outlined above be a good starting point for vscode? |
@jonasfj that solution sounds good to me. I also think it's only a small change from the PoC I've been working on (which currently uses the unstable API you gave for the list, and the main package API (without In my testing, the request to fetch the description has been incredibly fast. I'm also caching the version number with the description so we can provide completion on that. Assuming we'll go with this solution, I have some questions I'm interested in opinions on (+ @bwilkerson @devoncarew):
|
I would start no later than when a
Yes, we should cache to disk to improve the UX when there is no network connectivity. Large portions of the world still experience this regularly. I don't know how frequently the data coming from
We know that many of our users leave their IDEs running for multiple days / weeks. I know that I almost never restart my IDE except when there are updates to either the IDE or my OS that force it. All to say, it might be more common than not. If we cache the data to disk, then we could potentially have a background thread to fetch the data from
I think we should cache it indefinitely, but there might be a negative consequence that I'm not aware of. Is there a cost to presenting outdated data to the user when we are unable to get more up-to-date data?
Exponential backoff is probably a good strategy for this. |
Wow, yes, this is very fast :D
I think we get 10-30 new packages per day. I see little value to refreshing if cached data is no older than 18 hours -- but that's just a number I'm pulling out of thin air :D There is little reason to refresh frequently, but refreshing the next working day seems like a good idea.
Won't you keep the list of all version numbers? Or at-least the list of all major and minor versions (and maybe just the latest patch version), if we don't want to pollute the completion options. Note: I would suggest our completion strongly favors caret-notation on topic: we get around 100-300 new versions per day, so keeping this for 18 hours is probably reasonable. We could also control the caching server-side by specifying a |
If I've interpreted the comments above correctly:
Is
My current plan was only to keep the latest one to avoid a big list (on the assumption that if you're going to add a version, it'll probably be the latest). It also avoids editor ranking messing with the ordering and potentually putting a non-latest version at the top when you start typing (though it's possible other editors don't re-order things like VS Code does here). Right now the version numbers will only show in VS Code because we only fetch the description/package info in the
Just for setting |
Good point, it's best if this is handled in the HTTP client. Perhaps just handle
That might also be a good option, I'm not a UX designer :D It might be worth having the latest stable and latest prerelease, if the latest prerelease is newer than the latest stable. On pub.dev we generally say that the latest is the latest stable (if there is a stable release), so if Example: |
Makes sense - I think this will mean sticking with |
let's just make that a start, then we can always optimize later by making a The
Only downside is that for packages with a lot of versions the API end-point can become somewhat large. But I think we limit packages to 1000 versions or something like that. So worst case it'll be a few MBs, but that's probably very very rare :D |
Sounds good to me. If I've understand correctly, the only thing required from Pub for us to be able to ship this completion in the server is a live/stable equiv of |
This has already shipped: https://pub.dev/api/package-names |
Oh my, thank you! 😀 |
@DanTup, that's doesn't have the ordering, or the filtering we mentioned. I filed dart-lang/pub-dev#4302 for creating an end-point specifically for code completion of package names. |
Got it - I'll hold off landing this work until that API is done then. Thanks! |
@DanTup checkout: Note: we created the end-point so that it requires |
@jonasfj thanks! I've an open change here if you want to review the interaction with the API: https://dart-review.googlesource.com/c/sdk/+/176120 The related bits are in |
Stumbled upon this issue. It seems rather unfocused, and the part about naming completion seems finished. Should we close it? Or split it into a few more concrete features that we could imagine improves the IDE support. |
Yeah, it's probably done... We even have suggestions for version numbers, though it's possible they aren't triggering automatically. But let's close it. |
Respondents of the Q2 2019 Flutter user survey asked for better IDE support for developing and using packages, such as “add package” UI, “install the latest package” UI, etc. (Related: #1447)
cc: @mit-mit
The text was updated successfully, but these errors were encountered: