Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/rust-analyzer/src/config.rs30
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs9
-rw-r--r--crates/rust-analyzer/src/main_loop.rs11
-rw-r--r--crates/rust-analyzer/src/reload.rs4
4 files changed, 44 insertions, 10 deletions
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 1bc164b157..90857a3073 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -1070,6 +1070,7 @@ struct ClientInfo {
version: Option<Version>,
}
+/// The configuration of this rust-analyzer instance.
#[derive(Clone)]
pub struct Config {
/// Projects that have a Cargo.toml or a rust-project.json in a
@@ -1079,11 +1080,16 @@ pub struct Config {
/// Projects whose configuration was generated by a command
/// configured in discoverConfig.
discovered_projects_from_command: Vec<ProjectJsonFromCommand>,
- /// The workspace roots as registered by the LSP client
+ /// The workspace roots as registered by the LSP client.
workspace_roots: Vec<AbsPathBuf>,
caps: ClientCapabilities,
- /// The LSP root path, deprecated in favor of `workspace_roots`
+
+ /// The root of the first project encountered. This is deprecated
+ /// because rust-analyzer might be handling multiple projects.
+ ///
+ /// Prefer `workspace_roots` and `workspace_root_for()`.
root_path: AbsPathBuf,
+
snippets: Vec<Snippet>,
client_info: Option<ClientInfo>,
@@ -1787,9 +1793,23 @@ impl Config {
s
}
- pub fn root_path(&self) -> &AbsPathBuf {
- // We should probably use `workspace_roots` here if set
- &self.root_path
+ /// Find the workspace root that contains the given path, using the
+ /// longest prefix match.
+ pub fn workspace_root_for(&self, path: &AbsPath) -> &AbsPathBuf {
+ self.workspace_roots
+ .iter()
+ .filter(|root| path.starts_with(root.as_path()))
+ .max_by_key(|root| root.as_str().len())
+ .unwrap_or(self.default_root_path())
+ }
+
+ /// Best-effort root path for the current project.
+ ///
+ /// Use `workspace_root_for` where possible, because
+ /// `default_root_path` may return the wrong path when a user has
+ /// multiple workspaces.
+ pub fn default_root_path(&self) -> &AbsPathBuf {
+ self.workspace_roots.first().unwrap_or(&self.root_path)
}
pub fn caps(&self) -> &ClientCapabilities {
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index c24591b7ab..9c2e0a5f32 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -2453,7 +2453,14 @@ fn run_rustfmt(
let cmd_path = if command.contains(std::path::MAIN_SEPARATOR)
|| (cfg!(windows) && command.contains('/'))
{
- snap.config.root_path().join(cmd).into()
+ let project_root = Utf8PathBuf::from_path_buf(current_dir.clone())
+ .ok()
+ .and_then(|p| AbsPathBuf::try_from(p).ok());
+ let project_root = project_root
+ .as_ref()
+ .map(|dir| snap.config.workspace_root_for(dir))
+ .unwrap_or(snap.config.default_root_path());
+ project_root.join(cmd).into()
} else {
cmd
};
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 7c494de6f7..a8c3d062d0 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -830,12 +830,19 @@ impl GlobalState {
let command = cfg.command.clone();
let discover = DiscoverCommand::new(self.discover_sender.clone(), command);
+ let discover_path = match &arg {
+ DiscoverProjectParam::Buildfile(it) => it,
+ DiscoverProjectParam::Path(it) => it,
+ };
+ let current_dir =
+ self.config.workspace_root_for(discover_path.as_path()).clone();
+
let arg = match arg {
DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
};
- match discover.spawn(arg, self.config.root_path().as_ref()) {
+ match discover.spawn(arg, current_dir.as_ref()) {
Ok(handle) => {
if self.discover_jobs_active == 0 {
let title = &cfg.progress_label.clone();
@@ -953,7 +960,7 @@ impl GlobalState {
if let Some(dir) = dir {
message += &format!(
": {}",
- match dir.strip_prefix(self.config.root_path()) {
+ match dir.strip_prefix(self.config.workspace_root_for(&dir)) {
Some(relative_path) => relative_path.as_utf8_path(),
None => dir.as_ref(),
}
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 83f4a19b39..71accbed4e 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -390,7 +390,7 @@ impl GlobalState {
info!(%cause, "will fetch build data");
let workspaces = Arc::clone(&self.workspaces);
let config = self.config.cargo(None);
- let root_path = self.config.root_path().clone();
+ let root_path = self.config.default_root_path().clone();
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| {
sender.send(Task::FetchBuildData(BuildDataProgress::Begin)).unwrap();
@@ -883,7 +883,7 @@ impl GlobalState {
config,
crate::flycheck::FlycheckConfigJson::default(),
None,
- self.config.root_path().clone(),
+ self.config.default_root_path().clone(),
None,
None,
)]