-
Notifications
You must be signed in to change notification settings - Fork 309
LSP: builtin completions and docs #1142
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
base: main
Are you sure you want to change the base?
LSP: builtin completions and docs #1142
Conversation
|
@facebook-github-bot has imported this pull request. If you are a Meta employee, you can view this in D87061519. (Because this pull request was imported automatically, there will not be any future comments.) |
This is generally quite useful, needed in next diff.
We look at the build file names and check against that, same with package file names. This gets us a full OwnedStarlarkPath. So we can change our LSP behaviour depending on on what file the user is looking at (e.g. the next diff, whether to load prelude).
As you can see, valid_at was written only once, at startup. So DocsCache was a cache in name only. As soon as you touched prelude, the DocsCache would never be is_reusable again.
We fall back to builtins only if prelude fails to document.
ff8888a to
efc1698
Compare
| match self.is_reusable(¤t_dice_ctx) { | ||
| true => (), | ||
| false => { | ||
| let new_docs_cache = Self::new_docs_cache(fs, &mut current_dice_ctx).await?; | ||
| *docs_cache = new_docs_cache | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look closely, you'll see we never wrote to self.valid_at after initializing it in the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this diff could have been simpler if we just wrote to self.valid_at, but I only care if you do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically this diff makes it easier to special-case docs cache creation for starlark modules inside the prelude, as alluded to in the TODO you can see in the main diff.
|
I see @Nero5023 has been adding various docs for starlark APIs this week. Would you have a look at this? It puts those docs you've been writing only a keystroke or hover away. |
|
Alright, sorry it took me so long to get to this. I'm attempting to review all of this and am far enough along now to be able to start leaving some comments, but this code has always felt pretty awful and my attempting to understand it now is not making me feel any better about it. Before any of the details, let me get two things out of the way:
I'll leave comments one commit at a time
Wait I don't get it, wtf is going on in this function? What in the world is Obviously not on you. Maybe I missed something, but if this sounds right, replace this and hardcode it with
I found the
So unfortunately, this implementation is not quite correct for reasons that you can't really be expected to know: We support a thing called buck2/app/buck2_interpreter_for_build/src/interpreter/interpreter_for_dir.rs Lines 381 to 390 in abae83b
Now, we could go and add extra code to that, but that seems super brittle and all this code is way too complicated already so I don't really want to do that. Here's my alternative suggestion: First, push the code I linked above into the let calculator = dice_ctx
.get_interpreter_calculator(import_path.clone())
.await?;
let (module, _) = calculator.prepare_eval(import_path).await?;
let docs1 = module.get_private_docs();
let docs = calculator.globals().documentation();
// mergeWhere That's all robust and easy to implement. If you're worried about the perf, see below.
I have no idea wtf is going on with this dice cache or why this was done the way it was. We generally don't do explicit cache checks in buck2, is there a reason that this code couldn't just use a dice key to compute derivatives of dice data like everything else does? If so that'd be a lot better than this, it would mean that you can't get this wrong and also it would provide an obvious path towards fixing whatever perf concerns there might be. If you're worried about the perf of my previous suggestion, you could do the same there. Besides that, I also have one question for you. We currently implement this thing where go-to-def on builtins opens up a new file with a stub implementation looking thing. I've... never seen that before in any other LSP and it honestly doesn't make a lot of sense to me. Do you find it valuable/see the value in it? With this implemented, could we just delete that behavior and rely on hovers for surfacing docs for builtins? Thanks again |
JakobDegen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review automatically exported from Phabricator review in Meta.
Line 78 in abae83b
Don't copy this, we should improve the docs stuff so that we don't need it instead of propagating it further, we'll have to live with the disadvantages in the meantime |
|
You're welcome, thanks for getting round to it. This is pretty old code indeed, much of it blames back to "initial commit" so we might never know why some of it was done this way.
I think the intention was for the LSP to be active on I think you're right that everything would still work if you hardcoded one importpath for all of them, but it doesn't really bother me and helps with debugging if the path reflects the one in the editor. We can delete the handling of
Yes. Strikes me as obvious in retrospect, now that I'm familiar with all the different path types.
As for putting it in buck2_interpreter_for_build, sounds fine to me, and this is what I landed on for doing typechecking. Seems like enum DocEnvironmentKey {
/// Each cell can configure buildfile.includes differently, so partition on cell name
Buildfile(CellName),
/// If inside prelude, we skip generating `native` symbol that holds the prelude
OtherStarlark { inside_prelude: bool }
}and compute/store very close to the bare minimum of these. We would parse an empty string with a fake path probably, which would conveniently avoid issues like "no docs for builtins when file on disk has parse error". I can give that a go. |
Fixes #952.
Previously we had no docs or completion for builtins or prelude symbols. Now we do. And it's really, really good. You don't need to search through https://buck2.build nearly as often.
This builds on #1132 which is a big PR, but only really for theSplit out from that work.BuckLspContext::import_path_from_urlfunction that determines whether the current file is a build file, so 1132 can be split up without much trouble if need be. For now this PR is just two commits at the end.It also fixes #1124. And an apparent bug where the docs for prelude were (I think) not ever being cached.
See? It works!
You get completions/docs for global builtins everywhere, but for prelude symbols you get them only in build files. Like below:
Caveat -- rust rules
Please note that the
rust_*rules in the prelude have no docs due to being wrapped in macros (rust_common_macro_wrapper). That's out of scope for this PR. I don't know what was done to make this work for https://buck2.build where the rust rules clearly do get docs, maybe it can be replicated.