Multi-root workspace in VSCode

I use a single VSCode instance for working in multiple projects (Rust, NodeJS, etc.) and with different "workspaces". But rust-analyzer seems to assume that the instance only has one workspace.
Is this configurable?

Example:

I have multiple but separate projects at a path /projects, e.g. /projects/a and /projects/b.
For now, I have created a /projects/Cargo.toml with the contents

[workspace]
resolver = "2"
members = [
    "/projects/*",
]

This makes rust-analyzer work. But cargo build builds all projects.
Also, when I press the "Run" button in VSCode above "fn main()", it runs in /projects, instead of the "nearest folder with Cargo.toml", e.g. /project/a if I'm editing /project/a/src/main.rs.
The behavior in a nodejs project is to take "currently viewed file" and go up in parent folders until finding a "package.json", and then run "npm run ..." in that path.
I was expecting a similar behavior.

I think the rust-analyzer only reads the Cargo.toml file in the "root of the currently open folder", e.g. /projects/Cargo.toml. But ideally it would evaluate the currently open file, then find the nearest Cargo.toml, as the project file, and move up in parent folders until it finds a Cargo.toml with a [workspace] declaration, as its workspace configuration file.

Does this make sense?

So I would expect it to run in /projects/a/ if there was no parent workspace Cargo.toml, and otherwise in /projects.
So if I had two workspaces:
/projects/workspace1/a/main.rs
/projects/workspace2/c/main.rs
then running /projects/workspace1/a/main.rs would execute in /projects/workspace1/.

Is this configurable? Or something I should request as a feature request on GitHub?

Looks like[1] there is a configuration – rust-analyzer.linkedProjects – where you can list all your root Cargo.tomls (I suppose the ones for the cargo workspaces, and/or individually for the non-workspaced packages) in a vscode / rust-analyzer setting. (Probably best done in a workspace-specific setting, not globally.)

I have never tried this setting and cannot comment on how this interacts with your described effects specifically, e.g. how the Run button behaves then. Feel free to share your results here, if it works.


  1. and see also the other thread linked from there ↩ī¸Ž

Yes, that seems to work. It would be ideal if the workspaces could also be specified with a wildcard though, e.g. linkedProjects=/projects/workspaces/*, to avoid any manual management of the configuration files.

settings.json:

"rust-analyzer.linkedProjects": ["/projects/workspace1/Cargo.toml"]

/projects/workspace1/Cargo.toml

[workspace]
resolver = "2"
members = [
    "projects/*",
]

/projects/workspace1/projects/a/src/main.rs
/projects/workspace1/projects/a/Cargo.toml

as you have find out, that's not how rust-analyzer works. rust-analyzer has an editor plugin and LSP server, and it's the LSP server that's doing the heavy lifting, and the LSP server works on a "project" basis, not per "currently viewed file".

actually, rust-analyzer does not reads the manifest file in the "root of the currently open folder", but algorithm to discover rust projects starts from the root of the open folder recursively. for example. if you have two projects projects/a/Cargo.toml and projects/b/Cargo.toml, and you open the directory projects, both a and b will be discovered and loaded.

you can, however, disable the auto-discovery and manually configure what projects to load, as pointed out by @steffahn

I don't know what you mean by "otherwise in /projects", rust-analyzer always load "project", not single file (well, open a single file will put it in a "default" project anyway), even for non-cargo projects (such as cmake), rust-analyzer can work, as long you have a rust-project.json config file.

it already works like this. I think you are confused about vscode workspaces and cargo workspaces. rust-analyzer will always invoke cargo from the workspace directory.

suppose you have the following structure, and you open the "projects" directory in vscode, rust-analyzer will discovery all 4 projects: project-1a, project-1b, project-2a, project-2b, and when you run a binary or test from project-1a, it will run under projects/workspace1, when you run a binary from project-2b, it will run under projects/workspace2.

projects
+---workspace1
|   |   Cargo.lock
|   |   Cargo.toml
|   |
|   +---project-1a
|   |   |   Cargo.toml
|   |   |
|   |   \---src
|   |           lib.rs
|   |
|   \---project-1b
|       |   Cargo.toml
|       |
|       \---src
|               lib.rs
|               main.rs
|
\---workspace2
    |   Cargo.lock
    |   Cargo.toml
    |
    +---project-2a
    |   |   Cargo.toml
    |   |
    |   \---src
    |           lib.rs
    |
    \---project-2b
        |   Cargo.toml
        |
        \---src
                lib.rs
                main.rs
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.