facebook / starlark-rust

A Rust implementation of the Starlark language
Apache License 2.0
699 stars 57 forks source link

LSP: Add autocomplete & hover functionality, and jump to target name #68

Closed MaartenStaa closed 1 year ago

MaartenStaa commented 1 year ago

Fixes #52.

This PR adds the capability of sending auto-complete suggestions when in LSP mode. Currently it supports:

Not yet handled/open questions:

I'm hoping with some feedback, and maybe a merge of the Bazel PR, we can get this to a mergeable state 🙂 looking forward to hearing your thoughts!

ndmitchell commented 1 year ago

Sorry for the delay in looking at this - I was travelling.

How much of a problem is the use of kind = Method? What is the impact of that on a client such as VS Code? Just an incorrect icon in the completion list?

MaartenStaa commented 1 year ago

Thanks for going through this @ndmitchell! I'll go through your comments some time this week and a) tidy up the code and b) split out the Bazel specific stuff to a separate PR. In that case the initial PR might have to omit completion of exported symbols from other files altogether, as completing those requires inserting the appropriate load statement.

Regarding the "method" type, yeah it's just an incorrect icon basically, or e.g. in Neovim it might have the type "method" as text instead of an icon. Not a huge deal obviously.

Thanks for the tip about SaplingSCM, I'll take a look at that as well. For the follow-up PR, I might create a new branch based on both this one and #51, thoughts?

ndmitchell commented 1 year ago

I'm just about to go through #51 (the person who was working from this on our side left Meta, so it accidentally got lost, oops). Let me see.

ndmitchell commented 1 year ago

For generating a load statement, I imagine you need a method on LspContext like render_as_load(&self, target: &LspUrl, current_file: &LspUrl) -> anyhow::Result<String> ? That seems quite reasonable to add in.

MaartenStaa commented 1 year ago

That sounds like a good solution, yeah. Probably you want to be able to do the mapping in two directions:

facebook-github-bot commented 1 year ago

@ndmitchell has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

ndmitchell commented 1 year ago

Thanks! I'm going through the code now - plan to split pieces off and land them separately (those obvious bits) and slowly work until there is nothing left. Expect to see pieces of your code trickle out over the next day or so.

MaartenStaa commented 1 year ago

Thanks! I'm going through the code now - plan to split pieces off and land them separately (those obvious bits) and slowly work until there is nothing left. Expect to see pieces of your code trickle out over the next day or so.

@ndmitchell Awesome, looking forward to it. Feel free to ping me if any questions come up.

ndmitchell commented 1 year ago

I've submitted all the changes apart from those to lsp/server.rs and a handful of lines to definition.rs. I'll update once they are all landed. For the changes to server:

Overall, looks good, and the automatic adding of load statements is super slick.

ndmitchell commented 1 year ago

Other notes:

MaartenStaa commented 1 year ago

@ndmitchell Nice! I merged in origin/main and resolved any conflicts.

I think we need the LspContext so that it isn't Buck/Bazel specific, with the mapping from a URL to the load name and vice versa. Did anything happen to your LspContext suggestion above?

I don't think so, no. Not sure if the idea is to tackle that via #51 or not? I can try to come up with an initial implementation. One thought I had later on: should that actually be on the LspContext? Just wondering if it makes more sense to have Bazel as a "dialect", and let the LSP be aware of the Starlark dialect. I should probably add that I'm not sure what, if any, the actual differences are between Bazel and Buck and how they render load paths. If they're the same, then having it on the LspContext seems fine.

As an extension, I note you aren't auto completing using names that are loaded by other open modules. E.g. if I have a separate file open, with load("filename", "foo") then offering to complete to foo makes sense, even though foo isn't exported by anything open.

That's a nice idea, I'll try to find some time to add that!

We should probably have a method on LspContext to get a list of the global symbols.

Makes sense. I guess that would be the things under starlark/src/stdlib?

Completing keywords is quite nice - a hardcoded list of those should be fairly easy to add.

Added!

Overall, looks good, and the automatic adding of load statements is super slick.

Thanks! I was pretty happy with that too :)

MaartenStaa commented 1 year ago

@ndmitchell I have now added the autocomplete options gathered from load statements in open files.

MaartenStaa commented 1 year ago

@ndmitchell Added a few more things:

I'd appreciate it if you or someone else can take a critical look at render_as_load and resolve_load—I based my logic on how Bazel works, but don't know enough about Buck(2) to know whether it uses the same format of:

(also, it doesn't really handle stuff in other workspaces, e.g. @workspace//some:file)

ndmitchell commented 1 year ago

Thanks - hoping to take a look this weekend!

MaartenStaa commented 1 year ago

@ndmitchell OK, so I went off the rails a bit this week 😅 added a bunch of stuff. You can see it from the commits above, but summarizing:

I appreciate that this probably makes reviewing this more complicated, so I'm sorry about that. Is there some (semi-)public channel (Slack, Discord) you have where maybe we can work together a bit more closely to be able to land this? e.g. I know for the Relay team they have a private channel in the GraphQL Discord server.

ndmitchell commented 1 year ago

@MaartenStaa - might need a VC to ensure we move forward with this. Can you email me at ndmitchell -at- gmail.com and we can figure it out.

facebook-github-bot commented 1 year ago

@ndmitchell has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

ndmitchell commented 1 year ago

I've gone through this PR in consultation with @MaartenStaa:

With that I have 6 diffs that are ready to land now (being reviewed and landed internally) then one diff on top which is the hover/completion stuff. Once the prerequisites land I'll publish that and share it back here (it is 95%+ the work of @MaartenStaa).

ndmitchell commented 1 year ago

All the dependencies are now landed. https://github.com/facebookexperimental/starlark-rust/pull/79 is the code which is basically a version of this.

ndmitchell commented 1 year ago

Given #79 is now landed, closing this diff as it is 90% landed. Please open follow up PR for the rest of the pieces. Thanks so much for your improvements!

stagnation commented 1 year ago

Hooray, thank you! I checked with neovim and a simple bazel program to hopefully see if the starlark-bazel parts were included. The linting functionality that we've always had works just like before, and there are now more LSP functions implemented, go-to-definition can be called where it makes sense, loads and target references. But the landing location is typically just a (new) file with the token name, which I assume is expected for a bazel project. I'm happy to test-run starlark-bazel when it comes :)