Vscode-rust: Incorrectly reports missing Cargo.toml if it's not in the root

Created on 1 Jan 2018  Β·  11Comments  Β·  Source: rust-lang/vscode-rust

I'm working on a small multi-lang project where the Cargo.toml is in a child of the root directory:

root/
  README.md
  rust/
    cargo.toml
  # other stuff

It incorrectly reports that:

Cargo.toml must be in the workspace in order to support all features

Of course, Cargo.toml is in the workspace…

code-error

Most helpful comment

What about a feature instead that instead allows you to sepcify what folder the Cargo.toml is in? I have seen many other VS Code extensions do this. Perhaps add it to the context menu of a folder "Set as Cargo.toml location"?

All 11 comments

Yes... It also happens to me...

I think the error message has been changed to

A Cargo.toml file must be at the root of the workspace in order to support all features

(cf. #207) meaning that rls-vscode expects cargo.toml to be at the root of your workspace. Sadly, this implies we have to find a workaround for multi-lang projects (for example, use the "Add folder to workspace" feature in vscode) πŸ€”
Update: apparently, the extension does not work with multiple workspaces opened at the same time. So I have no other workaround than opening multiple instances of vscode πŸ˜• But I found a workaround in the atom extension's README:

Multi-crate projects

A root Cargo.toml is required in each atom project, however cargo workspaces can be used to support multiple crates in a single project. For example, a project with 'rust_foo' & 'rust_bar' directories/crates could have the following root Cargo.toml

# Cargo.toml
[workspace]
members = [
    "rust_foo",
    "rust_bar",
]

What about a feature instead that instead allows you to sepcify what folder the Cargo.toml is in? I have seen many other VS Code extensions do this. Perhaps add it to the context menu of a folder "Set as Cargo.toml location"?

I perused some of the extension's code but could not find how to hack it so that the 'root_path' for Cargo.toml is different from workspace.rootPath. That said, I found out that https://github.com/rust-lang-nursery/rls-vscode/commit/333332309695bb94e6d4e8c882db669d2b50d65f removed the variable rls.root that allowed running the rust language server from a different directory.

The commit message says:

rls.path is a better option, we don't need two ways and I don't think anyone uses this one any more

Maybe we need it back? 😊

Update: I misunderstood the first intent of rls.root. It is not what we want. What we want is something like:

    } else if (rls_root) {
        const env = await makeRlsEnv();
        console.info('running `cargo run` in ' + rls_root);
        childProcessPromise = Promise.resolve(child_process.spawn(
            CONFIGURATION.rustupPath, ['run', CONFIGURATION.channel, 'cargo', 'run', '--release'],
            { cwd: rls_root, env })
        );
    }

Update: I think I went a bit fast; rls.root isn't actually what we want. But we can use that as a basis for a new parameter, e.g., rust-client.cargoSubdir and pass the correct cwd to the spawn of RLS (in the child_process call)

Update2: setting cwd at the child_process cannot work as the Language Server protocol uses the workspaceFolder information, thus changing cwd won't do anything.

Yup! Seems like that's it. Especially with neon/ffi-like modules I think people would like this customized instead of having two VS Code workspaces open at the same time to have rls functionality.

Any progress on this feature?

This issue is really annoying when working with a rust, rarely is rust my sole project.
@maelvalais Solutions seems like a nice hack, but it doesn't fix the problem if you have multiple rust projects at the same time. What we actually need is for the extension to find the cargo.toml based on the file you have active and then either reuse or spin up a new language server.

You are right, my hack does not really help in these scenarios. Let us imagine we have open vscode in an hypothetical project/ folder that contains multiple rust projects (each one with a Cargo.toml and src/*.rs):

project/
β”œβ”€β”€ lib1/
β”‚  β”œβ”€β”€ Cargo.toml
β”‚  └── src/
β”‚     └── main1.rs
β”œβ”€β”€ lib2/
β”‚  β”œβ”€β”€ Cargo.toml
β”‚  └── src/
β”‚     └── main2.rs
└── lib3/
   β”œβ”€β”€ Cargo.toml
   └── src/
      └── main3.rs

Now, let's imagine a scenario:

  1. open the project/ in vscode
  2. open file main1.rs
  3. the rust-client extension fires up and looks for Cargo.toml in the parent folder and finds lib1/Cargo.toml
  4. because a Cargo.toml is found, the extension creates a new rls instance
  5. now, open file main2.rs
  6. the extension notices this file isn't related to the previous Cargo.toml from lib1/
  7. the extension looks for a Cargo.toml in the parent folder and finds lib2/Cargo.toml
  8. the extension creates a second rls instance (but the other one is still running)

@jannickj Does this scenario fit your expectation of how the extension should operate?

@maelvalais yes that's exactly how I would love it to operate :)

#457 implements what @maelvalais proposed

@nrc, I'm really looking forward to having this feature, do you know when you have time to look at it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mcclure picture mcclure  Β·  4Comments

Tape-Worm picture Tape-Worm  Β·  4Comments

rpeshkov picture rpeshkov  Β·  5Comments

fzzr- picture fzzr-  Β·  4Comments

byteshiva picture byteshiva  Β·  4Comments