From: Kirill Bulatov Date: Sun, 23 May 2021 17:56:54 +0000 (+0300) Subject: Drag detached files towards loading X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=de090749d9643a8035135092e2546cd0ddb854a6;p=rust.git Drag detached files towards loading --- diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index c2fde00d521..8c6cf94c249 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs @@ -50,7 +50,6 @@ 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 3b0ff506d49..c89e2f6e1bf 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs @@ -50,7 +50,9 @@ pub fn crates<'a>(&'a self) -> impl Iterator + ExactSizeIte 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 5fd64871068..ad4c202f200 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 @@ pub fn load( 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 @@ pub fn load_inline( 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 @@ pub fn to_roots(&self, build_data: Option<&BuildDataResult>) -> Vec }) })) .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 @@ pub fn n_packages(&self) -> usize { 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 @@ pub fn to_crate_graph( 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, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 570534c9a00..7c02a507cde 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -236,7 +236,7 @@ fn default() -> Self { pub struct Config { caps: lsp_types::ClientCapabilities, data: ConfigData, - detached_files: Vec, + detached_files: Vec, pub discovered_projects: Option>, pub root_path: AbsPathBuf, } @@ -345,7 +345,6 @@ pub fn update(&mut self, mut json: serde_json::Value) { self.detached_files = get_field::>(&mut json, "detachedFiles", None, "[]") .into_iter() .map(AbsPathBuf::assert) - .map(ProjectManifest::DetachedFile) .collect(); self.data = ConfigData::from_json(json); } @@ -399,7 +398,7 @@ pub fn linked_projects(&self) -> Vec { } } - pub fn detached_files(&self) -> &[ProjectManifest] { + pub fn detached_files(&self) -> &[AbsPathBuf] { &self.detached_files } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 6f2f482c150..6a36d29d4d8 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -312,6 +312,7 @@ pub(crate) fn cargo_target_for_crate_root( cargo.target_by_root(&path).map(|it| (cargo, it)) } ProjectWorkspace::Json { .. } => None, + ProjectWorkspace::DetachedFiles { .. } => None, }) } } diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index cfa95275d1f..7a53e4a8b95 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -146,8 +146,8 @@ pub(crate) fn fetch_workspaces_if_needed(&mut self) { log::info!("will fetch workspaces"); self.task_pool.handle.spawn_with_sender({ - // TODO kb reload workspace here? let linked_projects = self.config.linked_projects(); + let detached_files = self.config.detached_files().to_vec(); let cargo_config = self.config.cargo(); move |sender| { @@ -162,7 +162,7 @@ pub(crate) fn fetch_workspaces_if_needed(&mut self) { sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap(); - let workspaces = linked_projects + let mut workspaces = linked_projects .iter() .map(|project| match project { LinkedProject::ProjectManifest(manifest) => { @@ -181,6 +181,11 @@ pub(crate) fn fetch_workspaces_if_needed(&mut self) { }) .collect::>(); + if !detached_files.is_empty() { + workspaces + .push(project_model::ProjectWorkspace::load_detached_files(detached_files)); + } + log::info!("did fetch workspaces {:?}", workspaces); sender .send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(workspaces))) @@ -408,6 +413,7 @@ fn reload_flycheck(&mut self) { _ => None, } } + ProjectWorkspace::DetachedFiles { .. } => None, }) .map(|(id, root)| { let sender = sender.clone();