I'm trying to use rust-analyzer (with the helix text editor, if that matters at all), in a cargo workspace with multiple members.
I tried many things, but I can't seem to get this to work: I'd like to get diagnostics only for a given member of the workspace, that I'm currently working on.
My issue is that I'm doing some pretty massive refactoring, and I get diagnostics from multiple members of the cargo workspace all the time, making it pretty difficult to track what I'm doing on the single member I'm working on.
For now, my solution is to have a second terminal open and run cargo check on my workspace member... which I'd love to replace with some rust-analyzer goodness.
Thanks !
EDIT: forgot to say that yes, I open helix in the workspace member directly, something like hx . when I'm in worspace_root/workspace_member_A/
You seem to want diagnostics on single member, so check out User Manual for disabling workspace like rust-analyzer.check.workspace or somthing. Plus, you should know how to tweak LSP config in helix Languages (specifically for where to put the config file and the field conversion from JSON to TOML).
I also set this check.overrideCommand="cargo check --message-format=json" because the docs say that invocationLocation or invocationStrategy have no effect unless you set it.
I've also tried this workspace-lsp-roots = ["/path/to/my/workspace/member/"] in the languages.toml "local" config of helix, which is a file located at: /path/to/my/workspace/member/.helix/languages.toml.
Still, no luck...
To override the behavior by checking on single member:
"rust-analyzer.check.overrideCommand": "cargo check --message-format=json -p one-member" can be used to only check for one-member package
"rust-analyzer.check.overrideCommand": "cargo check --message-format=json" can be used to check the current package, which is useful for the following case:
You want diagnostics only from single package from which files are being saved, with other members opened, edited and analyzed, but no diagnostics from them.
overrideCommand seems to have highest priority, so no need to use "rust-analyzer.check.workspace": false again. (I've tested it. workspace = false and overrideCommand = "cargo check --message-format=json" work the same, because check.workspace = false just strip --workspace argument from check command.)
For your case, setting check.workspace to false can be enough.
Settings you mentioned
"rust-analyzer.check.invocationStrategy"
by default, the value is "per_workspace", meaning cargo check (even with no workspace argument) will be run for each workspace. If your project consists of multi-workspace, RA still checks for other packages, because RA still tries to invoke cago-check multiple times.
you can set it to "once" to run check only once anyway
"rust-analyzer.check.invocationLocation"
"workspace" by default: I think it's just because RA by default run check for workspace
"root": a bit confusing, but I think it means root for a package, not necessary to be a root of a workspace. But the documentation says project’s root directory, so what is project in this context? IDK
invocationStrategy = once implies invocationLocation = root
but I don't what's point of this setting: workspace = false or overrideCommand = "cargo check --message-format=json" works fine without setting it to "root"
"rust-analyzer.linkedProjects"
it's for non-cargo project, an example of this is rustlings lsp will generate a rust-project.json file to make RA work, since rustlings contains a collection of exercises with non-cargo layout; each exercise are single file (there are some exceptions in it, so non-cargo layout is a bit inaccurate, strictly speaking, "rust-analyzer.linkedProjects" are for mixed layouts).
if your project are already based on cargo layout, RA seems to work on cargo layout anyway, even though you force linkedProjects layout
at least in my testing, if a package is a member of workspace, linkedProjects or rust-project.json has no effect; if a package is an exclusion of workspace, they do work.
config loading
I think this would be a big problem and cause great time waste if people're unaware of /unfamiliar to how to load config on your IDE/editor/plugin.
For myself, when testing the settings above, I was hindered by these
in cargo project layout, I incorrectly expected rust-analyzer.json in member package folder to work for the member, but in reality
the config file for workspace members should be in root of the workspace to work
in non-cargo layout (like a package exluded from workspace), the config file in the isolated package should just work
the loading bugs: I use plugins in neovim to config RA, so there are several ways/places to write RA settings, but I may notice check.workspace = false works globally but not locally:
sometimes I have to manually reload local config to see it work
if you didn't know it work, you'll never try to make it work
One thing that is weird to me is that there are two (what they call) pickers in helix, for diagnostics. The "document" one, with space + d, and the "global" or "workspace" one, with space + D. What I was trying to do is get my package diagnostics in the "global" one. Maybe I misinterpreted what the "workspace picker" was about ?
Anyway, since you tested it and made it work in nvim, it's probably a helix issue if not an issue between my chair and my keyboard !
Thanks again for helping, I can mark your answer as the solution I think.
Well, on my old helix (23.10), space + d shows current diagnostics directly. (space+D for diagnostics from all workspace members.) So you might not need to config anything for RA.
I'm not using workspaces and space-d gives me errors in just the active buffer, while space-D gives errors in all buffers. Are you sure that's not what you're seeing?
You're right. I can comfirm that too. I didn't test multi-files in a member package.
Helix should describe space + d as Open diagnostic picker for current buffer/document/file only instead of Open diagnostic picker.
So I've also confirmed check.workspace = false works for mere single member. (Though I vaguely remember it didn't work for a while this morning. Anyway, it works now.)
Update: with the setting, it seems the diagnostics are from all members the first time they are seen, after several edits on the file, the diagnostics are finally from one member. The same behavior appears on nvim, which I though was a config loading delay.
Ha, so it was a bug then ? I agree with you in the issue you made on GH (thanks for doing that btw) that this is not what I expect when using RA that way.
Maybe I have not edited the file in my project enough times then (you mention that it needs several edits to work as we expect it).
I remember at some point thinking that it finally worked (had been trying for a while without closing the editor I think), only for the behavior I don't want to be back the next time I used helix. Maybe it's what you describe with the many edits.
I'll try again today and update. Thanks a lot !