aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2021-05-23 18:56:54 +0100
committerKirill Bulatov <[email protected]>2021-05-23 20:46:20 +0100
commitde090749d9643a8035135092e2546cd0ddb854a6 (patch)
tree01f0564f53a7763ecf28a46860997c294a042f3c
parent695569d9784b4a7d6e91451a0cc354f8bd009b59 (diff)
Drag detached files towards loading
-rw-r--r--crates/project_model/src/lib.rs1
-rw-r--r--crates/project_model/src/sysroot.rs4
-rw-r--r--crates/project_model/src/workspace.rs73
-rw-r--r--crates/rust-analyzer/src/config.rs5
-rw-r--r--crates/rust-analyzer/src/global_state.rs1
-rw-r--r--crates/rust-analyzer/src/reload.rs10
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;
50pub enum ProjectManifest { 50pub enum ProjectManifest {
51 ProjectJson(AbsPathBuf), 51 ProjectJson(AbsPathBuf),
52 CargoToml(AbsPathBuf), 52 CargoToml(AbsPathBuf),
53 DetachedFile(AbsPathBuf),
54} 53}
55 54
56impl ProjectManifest { 55impl 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
5use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; 5use std::{collections::VecDeque, fmt, fs, path::Path, process::Command};
6 6
7use anyhow::{Context, Result}; 7use anyhow::{format_err, Context, Result};
8use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; 8use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro};
9use cargo_workspace::DepKind; 9use cargo_workspace::DepKind;
10use cfg::CfgOptions; 10use 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
54impl fmt::Debug for ProjectWorkspace { 56impl 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
513fn 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
480fn handle_rustc_crates( 545fn 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 {
236pub struct Config { 236pub 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();