From 44f28f65af15371cfe35e3599571e7217d6a9db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=C3=A9baud=20Weksteen?= Date: Tue, 9 Jun 2020 21:26:42 +0200 Subject: Accept relative paths in rust-project.json If a relative path is found as part of Crate.root_module or Root.path, interpret it as relative to the location of the rust-project.json file. --- crates/ra_project_model/src/lib.rs | 32 +++++++++++++++++--------------- crates/rust-analyzer/src/bin/main.rs | 8 ++++---- crates/rust-analyzer/src/config.rs | 6 ++++-- crates/rust-analyzer/src/main_loop.rs | 7 ++++++- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index cb0e27dce..9541362f5 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -29,13 +29,7 @@ pub enum ProjectWorkspace { /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, /// Project workspace was manually specified using a `rust-project.json` file. - Json { project: JsonProject }, -} - -impl From for ProjectWorkspace { - fn from(project: JsonProject) -> ProjectWorkspace { - ProjectWorkspace::Json { project } - } + Json { project: JsonProject, project_location: PathBuf }, } /// `PackageRoot` describes a package root folder. @@ -164,10 +158,15 @@ impl ProjectWorkspace { format!("Failed to open json file {}", project_json.display()) })?; let reader = BufReader::new(file); + let project_location = match project_json.parent() { + Some(parent) => PathBuf::from(parent), + None => PathBuf::new(), + }; ProjectWorkspace::Json { project: from_reader(reader).with_context(|| { format!("Failed to deserialize json file {}", project_json.display()) })?, + project_location: project_location, } } ProjectManifest::CargoToml(cargo_toml) => { @@ -200,9 +199,11 @@ impl ProjectWorkspace { /// the root is a member of the current workspace pub fn to_roots(&self) -> Vec { match self { - ProjectWorkspace::Json { project } => { - project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() - } + ProjectWorkspace::Json { project, project_location } => project + .roots + .iter() + .map(|r| PackageRoot::new_member(project_location.join(&r.path))) + .collect(), ProjectWorkspace::Cargo { cargo, sysroot } => cargo .packages() .map(|pkg| PackageRoot { @@ -219,7 +220,7 @@ impl ProjectWorkspace { pub fn proc_macro_dylib_paths(&self) -> Vec { match self { - ProjectWorkspace::Json { project } => project + ProjectWorkspace::Json { project, .. } => project .crates .iter() .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) @@ -235,7 +236,7 @@ impl ProjectWorkspace { pub fn n_packages(&self) -> usize { match self { - ProjectWorkspace::Json { project } => project.crates.len(), + ProjectWorkspace::Json { project, .. } => project.crates.len(), ProjectWorkspace::Cargo { cargo, sysroot } => { cargo.packages().len() + sysroot.crates().len() } @@ -251,13 +252,14 @@ impl ProjectWorkspace { ) -> CrateGraph { let mut crate_graph = CrateGraph::default(); match self { - ProjectWorkspace::Json { project } => { + ProjectWorkspace::Json { project, project_location } => { let crates: FxHashMap<_, _> = project .crates .iter() .enumerate() .filter_map(|(seq_index, krate)| { - let file_id = load(&krate.root_module)?; + let file_path = project_location.join(&krate.root_module); + let file_id = load(&file_path)?; let edition = match krate.edition { json_project::Edition::Edition2015 => Edition::Edition2015, json_project::Edition::Edition2018 => Edition::Edition2018, @@ -540,7 +542,7 @@ impl ProjectWorkspace { ProjectWorkspace::Cargo { cargo, .. } => { Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) } - ProjectWorkspace::Json { project: JsonProject { roots, .. } } => roots + ProjectWorkspace::Json { project: JsonProject { roots, .. }, .. } => roots .iter() .find(|root| path.starts_with(&root.path)) .map(|root| root.path.as_ref()), diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 8d071ab1c..99e3f7173 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -108,11 +108,11 @@ fn run_server() -> Result<()> { config.update(value); } config.update_caps(&initialize_params.capabilities); + let cwd = std::env::current_dir()?; + config.root_path = + initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); if config.linked_projects.is_empty() { - let cwd = std::env::current_dir()?; - let root = - initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); let workspace_roots = initialize_params .workspace_folders .map(|workspaces| { @@ -122,7 +122,7 @@ fn run_server() -> Result<()> { .collect::>() }) .filter(|workspaces| !workspaces.is_empty()) - .unwrap_or_else(|| vec![root]); + .unwrap_or_else(|| vec![config.root_path.clone()]); config.linked_projects = ProjectManifest::discover_all(&workspace_roots) .into_iter() diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 1253db836..0e7a937a0 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -38,12 +38,13 @@ pub struct Config { pub with_sysroot: bool, pub linked_projects: Vec, + pub root_path: PathBuf, } #[derive(Debug, Clone)] pub enum LinkedProject { ProjectManifest(ProjectManifest), - JsonProject(JsonProject), + InlineJsonProject(JsonProject), } impl From for LinkedProject { @@ -54,7 +55,7 @@ impl From for LinkedProject { impl From for LinkedProject { fn from(v: JsonProject) -> Self { - LinkedProject::JsonProject(v) + LinkedProject::InlineJsonProject(v) } } @@ -167,6 +168,7 @@ impl Default for Config { lens: LensConfig::default(), hover: HoverConfig::default(), linked_projects: Vec::new(), + root_path: PathBuf::new(), } } } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 8ec571b70..cc9bb1726 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -121,7 +121,12 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { }) .ok() } - LinkedProject::JsonProject(it) => Some(it.clone().into()), + LinkedProject::InlineJsonProject(it) => { + Some(ra_project_model::ProjectWorkspace::Json { + project: it.clone(), + project_location: config.root_path.clone(), + }) + } }) .collect::>() }; -- cgit v1.2.3