diff options
author | Kirill Bulatov <[email protected]> | 2021-05-23 18:56:54 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2021-05-23 20:46:20 +0100 |
commit | de090749d9643a8035135092e2546cd0ddb854a6 (patch) | |
tree | 01f0564f53a7763ecf28a46860997c294a042f3c | |
parent | 695569d9784b4a7d6e91451a0cc354f8bd009b59 (diff) |
Drag detached files towards loading
-rw-r--r-- | crates/project_model/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/project_model/src/sysroot.rs | 4 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 73 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 10 |
6 files changed, 83 insertions, 11 deletions
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; | |||
50 | pub enum ProjectManifest { | 50 | pub enum ProjectManifest { |
51 | ProjectJson(AbsPathBuf), | 51 | ProjectJson(AbsPathBuf), |
52 | CargoToml(AbsPathBuf), | 52 | CargoToml(AbsPathBuf), |
53 | DetachedFile(AbsPathBuf), | ||
54 | } | 53 | } |
55 | 54 | ||
56 | impl ProjectManifest { | 55 | 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 { | |||
50 | 50 | ||
51 | pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> { | 51 | pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> { |
52 | log::debug!("Discovering sysroot for {}", cargo_toml.display()); | 52 | log::debug!("Discovering sysroot for {}", cargo_toml.display()); |
53 | let current_dir = cargo_toml.parent().unwrap(); | 53 | let current_dir = cargo_toml.parent().ok_or_else(|| { |
54 | format_err!("Failed to find the parent directory for file {:?}", cargo_toml) | ||
55 | })?; | ||
54 | let sysroot_dir = discover_sysroot_dir(current_dir)?; | 56 | let sysroot_dir = discover_sysroot_dir(current_dir)?; |
55 | let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?; | 57 | let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?; |
56 | let res = Sysroot::load(&sysroot_src_dir)?; | 58 | 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 @@ | |||
4 | 4 | ||
5 | use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; | 5 | use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; |
6 | 6 | ||
7 | use anyhow::{Context, Result}; | 7 | use anyhow::{format_err, Context, Result}; |
8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; | 8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; |
9 | use cargo_workspace::DepKind; | 9 | use cargo_workspace::DepKind; |
10 | use cfg::CfgOptions; | 10 | use cfg::CfgOptions; |
@@ -49,6 +49,8 @@ pub enum ProjectWorkspace { | |||
49 | }, | 49 | }, |
50 | /// Project workspace was manually specified using a `rust-project.json` file. | 50 | /// Project workspace was manually specified using a `rust-project.json` file. |
51 | Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, | 51 | Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, |
52 | /// TODO kb docs | ||
53 | DetachedFiles { files: Vec<AbsPathBuf>, sysroot: Sysroot, rustc_cfg: Vec<CfgFlag> }, | ||
52 | } | 54 | } |
53 | 55 | ||
54 | impl fmt::Debug for ProjectWorkspace { | 56 | impl fmt::Debug for ProjectWorkspace { |
@@ -75,6 +77,12 @@ impl fmt::Debug for ProjectWorkspace { | |||
75 | debug_struct.field("n_rustc_cfg", &rustc_cfg.len()); | 77 | debug_struct.field("n_rustc_cfg", &rustc_cfg.len()); |
76 | debug_struct.finish() | 78 | debug_struct.finish() |
77 | } | 79 | } |
80 | ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => f | ||
81 | .debug_struct("DetachedFiles") | ||
82 | .field("n_files", &files.len()) | ||
83 | .field("n_sysroot_crates", &sysroot.crates().len()) | ||
84 | .field("n_rustc_cfg", &rustc_cfg.len()) | ||
85 | .finish(), | ||
78 | } | 86 | } |
79 | } | 87 | } |
80 | } | 88 | } |
@@ -148,9 +156,6 @@ impl ProjectWorkspace { | |||
148 | let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); | 156 | let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); |
149 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } | 157 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } |
150 | } | 158 | } |
151 | ProjectManifest::DetachedFile(_) => { | ||
152 | todo!("TODO kb") | ||
153 | } | ||
154 | }; | 159 | }; |
155 | 160 | ||
156 | Ok(res) | 161 | Ok(res) |
@@ -168,6 +173,14 @@ impl ProjectWorkspace { | |||
168 | Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) | 173 | Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) |
169 | } | 174 | } |
170 | 175 | ||
176 | pub fn load_detached_files(detached_files: Vec<AbsPathBuf>) -> Result<ProjectWorkspace> { | ||
177 | let sysroot = Sysroot::discover( | ||
178 | &detached_files.first().ok_or_else(|| format_err!("No detached files to load"))?, | ||
179 | )?; | ||
180 | let rustc_cfg = rustc_cfg::get(None, None); | ||
181 | Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg }) | ||
182 | } | ||
183 | |||
171 | /// Returns the roots for the current `ProjectWorkspace` | 184 | /// Returns the roots for the current `ProjectWorkspace` |
172 | /// The return type contains the path and whether or not | 185 | /// The return type contains the path and whether or not |
173 | /// the root is a member of the current workspace | 186 | /// the root is a member of the current workspace |
@@ -227,6 +240,19 @@ impl ProjectWorkspace { | |||
227 | }) | 240 | }) |
228 | })) | 241 | })) |
229 | .collect(), | 242 | .collect(), |
243 | ProjectWorkspace::DetachedFiles { files, sysroot, .. } => files | ||
244 | .into_iter() | ||
245 | .map(|detached_file| PackageRoot { | ||
246 | is_member: true, | ||
247 | include: vec![detached_file.clone()], | ||
248 | exclude: Vec::new(), | ||
249 | }) | ||
250 | .chain(sysroot.crates().map(|krate| PackageRoot { | ||
251 | is_member: false, | ||
252 | include: vec![sysroot[krate].root_dir().to_path_buf()], | ||
253 | exclude: Vec::new(), | ||
254 | })) | ||
255 | .collect(), | ||
230 | } | 256 | } |
231 | } | 257 | } |
232 | 258 | ||
@@ -237,6 +263,9 @@ impl ProjectWorkspace { | |||
237 | let rustc_package_len = rustc.as_ref().map_or(0, |rc| rc.packages().len()); | 263 | let rustc_package_len = rustc.as_ref().map_or(0, |rc| rc.packages().len()); |
238 | cargo.packages().len() + sysroot.crates().len() + rustc_package_len | 264 | cargo.packages().len() + sysroot.crates().len() + rustc_package_len |
239 | } | 265 | } |
266 | ProjectWorkspace::DetachedFiles { sysroot, files, .. } => { | ||
267 | sysroot.crates().len() + files.len() | ||
268 | } | ||
240 | } | 269 | } |
241 | } | 270 | } |
242 | 271 | ||
@@ -270,6 +299,9 @@ impl ProjectWorkspace { | |||
270 | rustc, | 299 | rustc, |
271 | rustc.as_ref().zip(build_data).and_then(|(it, map)| map.get(it.workspace_root())), | 300 | rustc.as_ref().zip(build_data).and_then(|(it, map)| map.get(it.workspace_root())), |
272 | ), | 301 | ), |
302 | ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => { | ||
303 | detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot) | ||
304 | } | ||
273 | }; | 305 | }; |
274 | if crate_graph.patch_cfg_if() { | 306 | if crate_graph.patch_cfg_if() { |
275 | log::debug!("Patched std to depend on cfg-if") | 307 | log::debug!("Patched std to depend on cfg-if") |
@@ -477,6 +509,39 @@ fn cargo_to_crate_graph( | |||
477 | crate_graph | 509 | crate_graph |
478 | } | 510 | } |
479 | 511 | ||
512 | // TODO kb refactor and check for correctness | ||
513 | fn detached_files_to_crate_graph( | ||
514 | rustc_cfg: Vec<CfgFlag>, | ||
515 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | ||
516 | detached_files: &[AbsPathBuf], | ||
517 | sysroot: &Sysroot, | ||
518 | ) -> CrateGraph { | ||
519 | let _p = profile::span("detached_files_to_crate_graph"); | ||
520 | let mut crate_graph = CrateGraph::default(); | ||
521 | let (public_deps, _libproc_macro) = | ||
522 | sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); | ||
523 | |||
524 | let mut cfg_options = CfgOptions::default(); | ||
525 | cfg_options.extend(rustc_cfg); | ||
526 | |||
527 | for detached_file in detached_files { | ||
528 | let file_id = load(&detached_file).unwrap(); | ||
529 | let detached_file_crate = crate_graph.add_crate_root( | ||
530 | file_id, | ||
531 | Edition::Edition2018, | ||
532 | None, | ||
533 | cfg_options.clone(), | ||
534 | Env::default(), | ||
535 | Vec::new(), | ||
536 | ); | ||
537 | |||
538 | for (name, krate) in public_deps.iter() { | ||
539 | add_dep(&mut crate_graph, detached_file_crate, name.clone(), *krate); | ||
540 | } | ||
541 | } | ||
542 | crate_graph | ||
543 | } | ||
544 | |||
480 | fn handle_rustc_crates( | 545 | fn handle_rustc_crates( |
481 | rustc_workspace: &CargoWorkspace, | 546 | rustc_workspace: &CargoWorkspace, |
482 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | 547 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 570534c9a..7c02a507c 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -236,7 +236,7 @@ impl Default for ConfigData { | |||
236 | pub struct Config { | 236 | pub struct Config { |
237 | caps: lsp_types::ClientCapabilities, | 237 | caps: lsp_types::ClientCapabilities, |
238 | data: ConfigData, | 238 | data: ConfigData, |
239 | detached_files: Vec<ProjectManifest>, | 239 | detached_files: Vec<AbsPathBuf>, |
240 | pub discovered_projects: Option<Vec<ProjectManifest>>, | 240 | pub discovered_projects: Option<Vec<ProjectManifest>>, |
241 | pub root_path: AbsPathBuf, | 241 | pub root_path: AbsPathBuf, |
242 | } | 242 | } |
@@ -345,7 +345,6 @@ impl Config { | |||
345 | self.detached_files = get_field::<Vec<PathBuf>>(&mut json, "detachedFiles", None, "[]") | 345 | self.detached_files = get_field::<Vec<PathBuf>>(&mut json, "detachedFiles", None, "[]") |
346 | .into_iter() | 346 | .into_iter() |
347 | .map(AbsPathBuf::assert) | 347 | .map(AbsPathBuf::assert) |
348 | .map(ProjectManifest::DetachedFile) | ||
349 | .collect(); | 348 | .collect(); |
350 | self.data = ConfigData::from_json(json); | 349 | self.data = ConfigData::from_json(json); |
351 | } | 350 | } |
@@ -399,7 +398,7 @@ impl Config { | |||
399 | } | 398 | } |
400 | } | 399 | } |
401 | 400 | ||
402 | pub fn detached_files(&self) -> &[ProjectManifest] { | 401 | pub fn detached_files(&self) -> &[AbsPathBuf] { |
403 | &self.detached_files | 402 | &self.detached_files |
404 | } | 403 | } |
405 | 404 | ||
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 6f2f482c1..6a36d29d4 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -312,6 +312,7 @@ impl GlobalStateSnapshot { | |||
312 | cargo.target_by_root(&path).map(|it| (cargo, it)) | 312 | cargo.target_by_root(&path).map(|it| (cargo, it)) |
313 | } | 313 | } |
314 | ProjectWorkspace::Json { .. } => None, | 314 | ProjectWorkspace::Json { .. } => None, |
315 | ProjectWorkspace::DetachedFiles { .. } => None, | ||
315 | }) | 316 | }) |
316 | } | 317 | } |
317 | } | 318 | } |
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index cfa95275d..7a53e4a8b 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -146,8 +146,8 @@ impl GlobalState { | |||
146 | log::info!("will fetch workspaces"); | 146 | log::info!("will fetch workspaces"); |
147 | 147 | ||
148 | self.task_pool.handle.spawn_with_sender({ | 148 | self.task_pool.handle.spawn_with_sender({ |
149 | // TODO kb reload workspace here? | ||
150 | let linked_projects = self.config.linked_projects(); | 149 | let linked_projects = self.config.linked_projects(); |
150 | let detached_files = self.config.detached_files().to_vec(); | ||
151 | let cargo_config = self.config.cargo(); | 151 | let cargo_config = self.config.cargo(); |
152 | 152 | ||
153 | move |sender| { | 153 | move |sender| { |
@@ -162,7 +162,7 @@ impl GlobalState { | |||
162 | 162 | ||
163 | sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap(); | 163 | sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap(); |
164 | 164 | ||
165 | let workspaces = linked_projects | 165 | let mut workspaces = linked_projects |
166 | .iter() | 166 | .iter() |
167 | .map(|project| match project { | 167 | .map(|project| match project { |
168 | LinkedProject::ProjectManifest(manifest) => { | 168 | LinkedProject::ProjectManifest(manifest) => { |
@@ -181,6 +181,11 @@ impl GlobalState { | |||
181 | }) | 181 | }) |
182 | .collect::<Vec<_>>(); | 182 | .collect::<Vec<_>>(); |
183 | 183 | ||
184 | if !detached_files.is_empty() { | ||
185 | workspaces | ||
186 | .push(project_model::ProjectWorkspace::load_detached_files(detached_files)); | ||
187 | } | ||
188 | |||
184 | log::info!("did fetch workspaces {:?}", workspaces); | 189 | log::info!("did fetch workspaces {:?}", workspaces); |
185 | sender | 190 | sender |
186 | .send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(workspaces))) | 191 | .send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(workspaces))) |
@@ -408,6 +413,7 @@ impl GlobalState { | |||
408 | _ => None, | 413 | _ => None, |
409 | } | 414 | } |
410 | } | 415 | } |
416 | ProjectWorkspace::DetachedFiles { .. } => None, | ||
411 | }) | 417 | }) |
412 | .map(|(id, root)| { | 418 | .map(|(id, root)| { |
413 | let sender = sender.clone(); | 419 | let sender = sender.clone(); |