From 695569d9784b4a7d6e91451a0cc354f8bd009b59 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 23 May 2021 20:32:22 +0300 Subject: Draft detached files retrieval --- crates/project_model/src/lib.rs | 1 + crates/project_model/src/workspace.rs | 3 +++ 2 files changed, 4 insertions(+) (limited to 'crates/project_model') diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index 8c6cf94c2..c2fde00d5 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs @@ -50,6 +50,7 @@ pub use proc_macro_api::ProcMacroClient; pub enum ProjectManifest { ProjectJson(AbsPathBuf), CargoToml(AbsPathBuf), + DetachedFile(AbsPathBuf), } impl ProjectManifest { diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 607e62ea5..5fd648710 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -148,6 +148,9 @@ impl ProjectWorkspace { let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } } + ProjectManifest::DetachedFile(_) => { + todo!("TODO kb") + } }; Ok(res) -- cgit v1.2.3 From de090749d9643a8035135092e2546cd0ddb854a6 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 23 May 2021 20:56:54 +0300 Subject: Drag detached files towards loading --- crates/project_model/src/lib.rs | 1 - crates/project_model/src/sysroot.rs | 4 +- crates/project_model/src/workspace.rs | 73 +++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 6 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index c2fde00d5..8c6cf94c2 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs @@ -50,7 +50,6 @@ pub use proc_macro_api::ProcMacroClient; pub enum ProjectManifest { ProjectJson(AbsPathBuf), CargoToml(AbsPathBuf), - DetachedFile(AbsPathBuf), } impl ProjectManifest { diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index 3b0ff506d..c89e2f6e1 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs @@ -50,7 +50,9 @@ impl Sysroot { pub fn discover(cargo_toml: &AbsPath) -> Result { log::debug!("Discovering sysroot for {}", cargo_toml.display()); - let current_dir = cargo_toml.parent().unwrap(); + let current_dir = cargo_toml.parent().ok_or_else(|| { + format_err!("Failed to find the parent directory for file {:?}", cargo_toml) + })?; let sysroot_dir = discover_sysroot_dir(current_dir)?; let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?; let res = Sysroot::load(&sysroot_src_dir)?; diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 5fd648710..ad4c202f2 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -4,7 +4,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; -use anyhow::{Context, Result}; +use anyhow::{format_err, Context, Result}; use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; use cargo_workspace::DepKind; use cfg::CfgOptions; @@ -49,6 +49,8 @@ pub enum ProjectWorkspace { }, /// Project workspace was manually specified using a `rust-project.json` file. Json { project: ProjectJson, sysroot: Option, rustc_cfg: Vec }, + /// TODO kb docs + DetachedFiles { files: Vec, sysroot: Sysroot, rustc_cfg: Vec }, } impl fmt::Debug for ProjectWorkspace { @@ -75,6 +77,12 @@ impl fmt::Debug for ProjectWorkspace { debug_struct.field("n_rustc_cfg", &rustc_cfg.len()); debug_struct.finish() } + ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => f + .debug_struct("DetachedFiles") + .field("n_files", &files.len()) + .field("n_sysroot_crates", &sysroot.crates().len()) + .field("n_rustc_cfg", &rustc_cfg.len()) + .finish(), } } } @@ -148,9 +156,6 @@ impl ProjectWorkspace { let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } } - ProjectManifest::DetachedFile(_) => { - todo!("TODO kb") - } }; Ok(res) @@ -168,6 +173,14 @@ impl ProjectWorkspace { Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) } + pub fn load_detached_files(detached_files: Vec) -> Result { + let sysroot = Sysroot::discover( + &detached_files.first().ok_or_else(|| format_err!("No detached files to load"))?, + )?; + let rustc_cfg = rustc_cfg::get(None, None); + Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg }) + } + /// Returns the roots for the current `ProjectWorkspace` /// The return type contains the path and whether or not /// the root is a member of the current workspace @@ -227,6 +240,19 @@ impl ProjectWorkspace { }) })) .collect(), + ProjectWorkspace::DetachedFiles { files, sysroot, .. } => files + .into_iter() + .map(|detached_file| PackageRoot { + is_member: true, + include: vec![detached_file.clone()], + exclude: Vec::new(), + }) + .chain(sysroot.crates().map(|krate| PackageRoot { + is_member: false, + include: vec![sysroot[krate].root_dir().to_path_buf()], + exclude: Vec::new(), + })) + .collect(), } } @@ -237,6 +263,9 @@ impl ProjectWorkspace { let rustc_package_len = rustc.as_ref().map_or(0, |rc| rc.packages().len()); cargo.packages().len() + sysroot.crates().len() + rustc_package_len } + ProjectWorkspace::DetachedFiles { sysroot, files, .. } => { + sysroot.crates().len() + files.len() + } } } @@ -270,6 +299,9 @@ impl ProjectWorkspace { rustc, rustc.as_ref().zip(build_data).and_then(|(it, map)| map.get(it.workspace_root())), ), + ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => { + detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot) + } }; if crate_graph.patch_cfg_if() { log::debug!("Patched std to depend on cfg-if") @@ -477,6 +509,39 @@ fn cargo_to_crate_graph( crate_graph } +// TODO kb refactor and check for correctness +fn detached_files_to_crate_graph( + rustc_cfg: Vec, + load: &mut dyn FnMut(&AbsPath) -> Option, + detached_files: &[AbsPathBuf], + sysroot: &Sysroot, +) -> CrateGraph { + let _p = profile::span("detached_files_to_crate_graph"); + let mut crate_graph = CrateGraph::default(); + let (public_deps, _libproc_macro) = + sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); + + let mut cfg_options = CfgOptions::default(); + cfg_options.extend(rustc_cfg); + + for detached_file in detached_files { + let file_id = load(&detached_file).unwrap(); + let detached_file_crate = crate_graph.add_crate_root( + file_id, + Edition::Edition2018, + None, + cfg_options.clone(), + Env::default(), + Vec::new(), + ); + + for (name, krate) in public_deps.iter() { + add_dep(&mut crate_graph, detached_file_crate, name.clone(), *krate); + } + } + crate_graph +} + fn handle_rustc_crates( rustc_workspace: &CargoWorkspace, load: &mut dyn FnMut(&AbsPath) -> Option, -- cgit v1.2.3 From 72594beca46ac4a05b0c54f26a285f5197192b8b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 23 May 2021 23:29:26 +0300 Subject: Deal with todos --- crates/project_model/src/workspace.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index ad4c202f2..ede82d88b 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -49,7 +49,8 @@ pub enum ProjectWorkspace { }, /// Project workspace was manually specified using a `rust-project.json` file. Json { project: ProjectJson, sysroot: Option, rustc_cfg: Vec }, - /// TODO kb docs + /// Project with a set of disjoint files, not belonging to any particular workspace. + /// Backed by basic sysroot crates for basic completion and highlighting. DetachedFiles { files: Vec, sysroot: Sysroot, rustc_cfg: Vec }, } @@ -509,7 +510,6 @@ fn cargo_to_crate_graph( crate_graph } -// TODO kb refactor and check for correctness fn detached_files_to_crate_graph( rustc_cfg: Vec, load: &mut dyn FnMut(&AbsPath) -> Option, @@ -525,11 +525,21 @@ fn detached_files_to_crate_graph( cfg_options.extend(rustc_cfg); for detached_file in detached_files { - let file_id = load(&detached_file).unwrap(); + let file_id = match load(&detached_file) { + Some(file_id) => file_id, + None => { + log::error!("Failed to load detached file {:?}", detached_file); + continue; + } + }; + let display_name = detached_file + .file_stem() + .and_then(|os_str| os_str.to_str()) + .map(|file_stem| CrateDisplayName::from_canonical_name(file_stem.to_string())); let detached_file_crate = crate_graph.add_crate_root( file_id, Edition::Edition2018, - None, + display_name, cfg_options.clone(), Env::default(), Vec::new(), -- cgit v1.2.3 From d8c36029cc3961ce742aa6e5d59926c5a7e7170a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 24 May 2021 14:47:20 +0300 Subject: Small file error display fix Co-authored-by: Aleksey Kladov --- crates/project_model/src/sysroot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index c89e2f6e1..4e39d6dd3 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs @@ -51,7 +51,7 @@ impl Sysroot { pub fn discover(cargo_toml: &AbsPath) -> Result { log::debug!("Discovering sysroot for {}", cargo_toml.display()); let current_dir = cargo_toml.parent().ok_or_else(|| { - format_err!("Failed to find the parent directory for file {:?}", cargo_toml) + format_err!("Failed to find the parent directory for {}", cargo_toml.display()) })?; let sysroot_dir = discover_sysroot_dir(current_dir)?; let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?; -- cgit v1.2.3 From 5c0369b1d0c5351672f2a16e9a0d17beee84bcbe Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 24 May 2021 14:52:57 +0300 Subject: Add a FIXME --- crates/project_model/src/workspace.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index ede82d88b..84990075f 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -49,6 +49,15 @@ pub enum ProjectWorkspace { }, /// Project workspace was manually specified using a `rust-project.json` file. Json { project: ProjectJson, sysroot: Option, rustc_cfg: Vec }, + + // FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning. + // That's not the end user experience we should strive for. + // Ideally, you should be able to just open a random detached file in existing cargo projects, and get the basic features working. + // That needs some changes on the salsa-level though. + // In particular, we should split the unified CrateGraph (which currently has maximal durability) into proper crate graph, and a set of ad hoc roots (with minimal durability). + // Then, we need to hide the graph behind the queries such that most queries look only at the proper crate graph, and fall back to ad hoc roots only if there's no results. + // After this, we should be able to tweak the logic in reload.rs to add newly opened files, which don't belong to any existing crates, to the set of the detached files. + // // /// Project with a set of disjoint files, not belonging to any particular workspace. /// Backed by basic sysroot crates for basic completion and highlighting. DetachedFiles { files: Vec, sysroot: Sysroot, rustc_cfg: Vec }, -- cgit v1.2.3