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/src') 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