withered-magic / starpls

An LSP implementation for Starlark, the configuration language used by Bazel and Buck2.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fail to load io_bazel_rules_go rules

sluongng opened this issue · comments

Something weird when I tried to open my WORKSPACE file.

This line in particular does not load properly https://github.com/buildbuddy-io/buildbuddy/blob/222b491273d6fd971b342d8e5d4216600028027b/WORKSPACE#L60

Could not resolve module "@io_bazel_rules_go//go:deps.bzl": No such file or directory (os error 2) (starpls)

But I do have that repository available on disk 🤔

Ah, I was able to reproduce this and fixed it by fetching all external repositories with bzlmod via bazel fetch --enable_bzlmod //... --keep_going and then refreshing the diagnostics by editing the file.

Basically what happened is that starpls defaults to resolving external dependencies with bzlmod if it sees a MODULE.bazel file and the current Bazel version supports the bazel mod dump_repo_mapping command. So in this case the io_bazel_rules_go apparent name was mapped to the rules_go~ canonical name, but the rules_go~ directory was missing from the $(bazel info output_base)/external. The bazel fetch command above created the rules_go~ directory and then after that all the load statements with @io_bazel_rules_go worked and things like go to def for symbols loaded from io_bazel_rules_go worked as well!

I wonder if there's a good way to tell starpls to use bzlmod or not when both MODULE.bazel and WORKSPACE are present, maybe a per-project config file or choosing one via the command line?

I initially also looked into having starpls always do an initial bazel fetch //..., but for our monorepo at work it could take up to 5 mins for that to complete, and I didn't want the server to potentially have to block for that long, so I ended up just deferring to the user to make sure external repos are fetched for their chosen mode (i.e. bzlmod or legacy workspaces). Maybe this could be a configurable option too?

I think the current recommended way of detecting bzlmod enabled/disabled is to run

> bazel info release starlark-semantics
Starting local Bazel server and connecting to it...
release: release 7.1.1
starlark-semantics: StarlarkSemantics{enable_bzlmod=false}

If the release is before Bazel 7, the default is false. After Bazel 7, the default is true.
If it's different from the default, the actual value will be printed out inside starlark-semantics like the example above.


I think it's fine to call bazel query --keep_going -- @<repo>//... to only load that repo.

Perhaps, there could be an additional async task that trigger these in the background once the editor opens a file.
I can also see cases where you might want to run

bazel query --keep_going -- 'buildfiles(:all)'

to get all related repositories and "prefetch" them somehow. The point is that you don't want to load everything all at once, but only the minimum for the current package.

For a better local experience, a prefilled --repository_cache= could help to save on network bandwidth.

Nice, I wasn't aware of starlark-semantics, that seems pretty straightforward and I can adjust the bzlmod detection logic to use that instead!

I'll also see what I can do about incrementally loading dependencies like that, seems like a pretty reasonable strategy especially when there's tons of external repositories. I don't think there's anything in how I currently have things set up that would prohibit that from happening, so it might actually be relatively straightforward to implement an initial working version. Can probably do something like suppress diagnostics for files that are having their dependencies lazy loaded (but not actually block things like autocomplete/hover while the async process is running)

The logic for checking bzlmod based on release version and starlark-semantics is now on main, thanks for the suggestion! I can leave this issue open while investigating incrementally loading dependencies