]> git.lizzy.rs Git - rust.git/commitdiff
Drag detached files towards loading
authorKirill Bulatov <mail4score@gmail.com>
Sun, 23 May 2021 17:56:54 +0000 (20:56 +0300)
committerKirill Bulatov <mail4score@gmail.com>
Sun, 23 May 2021 19:46:20 +0000 (22:46 +0300)
crates/project_model/src/lib.rs
crates/project_model/src/sysroot.rs
crates/project_model/src/workspace.rs
crates/rust-analyzer/src/config.rs
crates/rust-analyzer/src/global_state.rs
crates/rust-analyzer/src/reload.rs

index c2fde00d5216cae18a63000678bf517fee039027..8c6cf94c249fa73e7f43914d4bd29b14bc6f6c42 100644 (file)
@@ -50,7 +50,6 @@
 pub enum ProjectManifest {
     ProjectJson(AbsPathBuf),
     CargoToml(AbsPathBuf),
-    DetachedFile(AbsPathBuf),
 }
 
 impl ProjectManifest {
index 3b0ff506d49a1914cdf13fd97c4bd1ce01baccbc..c89e2f6e1bf908784cfd5fa7c7df8d2e896bc791 100644 (file)
@@ -50,7 +50,9 @@ pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIte
 
     pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
         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)?;
index 5fd6487106810108aa1b357189f0446e35cd12d6..ad4c202f2008cf57189563ddd1cae09a7b60bd63 100644 (file)
@@ -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<Sysroot>, rustc_cfg: Vec<CfgFlag> },
+    /// TODO kb docs
+    DetachedFiles { files: Vec<AbsPathBuf>, sysroot: Sysroot, rustc_cfg: Vec<CfgFlag> },
 }
 
 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<AbsPathBuf>) -> Result<ProjectWorkspace> {
+        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<PackageRoot>
                     })
                 }))
                 .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<CfgFlag>,
+    load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    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<FileId>,
index 570534c9a008dbc4b1c363e11c4ada32d63149ae..7c02a507cdea50f92037607e3add819ce69b6281 100644 (file)
@@ -236,7 +236,7 @@ fn default() -> Self {
 pub struct Config {
     caps: lsp_types::ClientCapabilities,
     data: ConfigData,
-    detached_files: Vec<ProjectManifest>,
+    detached_files: Vec<AbsPathBuf>,
     pub discovered_projects: Option<Vec<ProjectManifest>>,
     pub root_path: AbsPathBuf,
 }
@@ -345,7 +345,6 @@ pub fn update(&mut self, mut json: serde_json::Value) {
         self.detached_files = get_field::<Vec<PathBuf>>(&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<LinkedProject> {
         }
     }
 
-    pub fn detached_files(&self) -> &[ProjectManifest] {
+    pub fn detached_files(&self) -> &[AbsPathBuf] {
         &self.detached_files
     }
 
index 6f2f482c150636de271fc84efe0aa92e36c7165e..6a36d29d4d8f1a02af04f0c9146040bc022496b3 100644 (file)
@@ -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,
         })
     }
 }
index cfa95275d1f38656d8fb62fbd65318a8c6562882..7a53e4a8b955e8a7b0515a40d3d82c528580b067 100644 (file)
@@ -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::<Vec<_>>();
 
+                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();