diff options
author | Edwin Cheng <[email protected]> | 2021-01-07 17:08:46 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2021-01-07 17:18:58 +0000 |
commit | 2b2d699b35d69375def80fe51c6a8c3bfbe53828 (patch) | |
tree | 1c10b2986017fc1e756d2bce75250546cce9310b | |
parent | 54eb87de0363cfba1d7104b8d37898fc120c029b (diff) |
Report progress for cargo metadata and output-dir
-rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 26 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 22 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 34 |
5 files changed, 77 insertions, 18 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index 0e6679542..2ee4e88b2 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -3,9 +3,10 @@ | |||
3 | use std::{ | 3 | use std::{ |
4 | convert::TryInto, | 4 | convert::TryInto, |
5 | ffi::OsStr, | 5 | ffi::OsStr, |
6 | io::BufReader, | ||
6 | ops, | 7 | ops, |
7 | path::{Path, PathBuf}, | 8 | path::{Path, PathBuf}, |
8 | process::Command, | 9 | process::{Command, Stdio}, |
9 | }; | 10 | }; |
10 | 11 | ||
11 | use anyhow::{Context, Result}; | 12 | use anyhow::{Context, Result}; |
@@ -15,6 +16,7 @@ use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId} | |||
15 | use itertools::Itertools; | 16 | use itertools::Itertools; |
16 | use paths::{AbsPath, AbsPathBuf}; | 17 | use paths::{AbsPath, AbsPathBuf}; |
17 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | use stdx::JodChild; | ||
18 | 20 | ||
19 | use crate::cfg_flag::CfgFlag; | 21 | use crate::cfg_flag::CfgFlag; |
20 | use crate::utf8_stdout; | 22 | use crate::utf8_stdout; |
@@ -171,6 +173,7 @@ impl CargoWorkspace { | |||
171 | pub fn from_cargo_metadata( | 173 | pub fn from_cargo_metadata( |
172 | cargo_toml: &AbsPath, | 174 | cargo_toml: &AbsPath, |
173 | config: &CargoConfig, | 175 | config: &CargoConfig, |
176 | progress: &dyn Fn(String), | ||
174 | ) -> Result<CargoWorkspace> { | 177 | ) -> Result<CargoWorkspace> { |
175 | let mut meta = MetadataCommand::new(); | 178 | let mut meta = MetadataCommand::new(); |
176 | meta.cargo_path(toolchain::cargo()); | 179 | meta.cargo_path(toolchain::cargo()); |
@@ -220,6 +223,9 @@ impl CargoWorkspace { | |||
220 | meta.other_options(vec![String::from("--filter-platform"), target]); | 223 | meta.other_options(vec![String::from("--filter-platform"), target]); |
221 | } | 224 | } |
222 | 225 | ||
226 | // FIXME: Currently MetadataCommand is not based on parse_stream, | ||
227 | // So we just report it as a whole | ||
228 | progress("metadata".to_string()); | ||
223 | let mut meta = meta.exec().with_context(|| { | 229 | let mut meta = meta.exec().with_context(|| { |
224 | let cwd: Option<AbsPathBuf> = | 230 | let cwd: Option<AbsPathBuf> = |
225 | std::env::current_dir().ok().and_then(|p| p.try_into().ok()); | 231 | std::env::current_dir().ok().and_then(|p| p.try_into().ok()); |
@@ -243,7 +249,7 @@ impl CargoWorkspace { | |||
243 | let mut envs = FxHashMap::default(); | 249 | let mut envs = FxHashMap::default(); |
244 | let mut proc_macro_dylib_paths = FxHashMap::default(); | 250 | let mut proc_macro_dylib_paths = FxHashMap::default(); |
245 | if config.load_out_dirs_from_check { | 251 | if config.load_out_dirs_from_check { |
246 | let resources = load_extern_resources(cargo_toml, config)?; | 252 | let resources = load_extern_resources(cargo_toml, config, progress)?; |
247 | out_dir_by_id = resources.out_dirs; | 253 | out_dir_by_id = resources.out_dirs; |
248 | cfgs = resources.cfgs; | 254 | cfgs = resources.cfgs; |
249 | envs = resources.env; | 255 | envs = resources.env; |
@@ -368,6 +374,7 @@ pub(crate) struct ExternResources { | |||
368 | pub(crate) fn load_extern_resources( | 374 | pub(crate) fn load_extern_resources( |
369 | cargo_toml: &Path, | 375 | cargo_toml: &Path, |
370 | cargo_features: &CargoConfig, | 376 | cargo_features: &CargoConfig, |
377 | progress: &dyn Fn(String), | ||
371 | ) -> Result<ExternResources> { | 378 | ) -> Result<ExternResources> { |
372 | let mut cmd = Command::new(toolchain::cargo()); | 379 | let mut cmd = Command::new(toolchain::cargo()); |
373 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); | 380 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); |
@@ -395,11 +402,14 @@ pub(crate) fn load_extern_resources( | |||
395 | } | 402 | } |
396 | } | 403 | } |
397 | 404 | ||
398 | let output = cmd.output()?; | 405 | cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); |
399 | 406 | ||
400 | let mut res = ExternResources::default(); | 407 | let mut child = cmd.spawn().map(JodChild)?; |
408 | let child_stdout = child.stdout.take().unwrap(); | ||
409 | let stdout = BufReader::new(child_stdout); | ||
401 | 410 | ||
402 | for message in cargo_metadata::Message::parse_stream(output.stdout.as_slice()) { | 411 | let mut res = ExternResources::default(); |
412 | for message in cargo_metadata::Message::parse_stream(stdout) { | ||
403 | if let Ok(message) = message { | 413 | if let Ok(message) = message { |
404 | match message { | 414 | match message { |
405 | Message::BuildScriptExecuted(BuildScript { | 415 | Message::BuildScriptExecuted(BuildScript { |
@@ -432,6 +442,8 @@ pub(crate) fn load_extern_resources( | |||
432 | res.env.insert(package_id, env); | 442 | res.env.insert(package_id, env); |
433 | } | 443 | } |
434 | Message::CompilerArtifact(message) => { | 444 | Message::CompilerArtifact(message) => { |
445 | progress(format!("metadata {}", message.target.name)); | ||
446 | |||
435 | if message.target.kind.contains(&"proc-macro".to_string()) { | 447 | if message.target.kind.contains(&"proc-macro".to_string()) { |
436 | let package_id = message.package_id; | 448 | let package_id = message.package_id; |
437 | // Skip rmeta file | 449 | // Skip rmeta file |
@@ -442,7 +454,9 @@ pub(crate) fn load_extern_resources( | |||
442 | } | 454 | } |
443 | } | 455 | } |
444 | } | 456 | } |
445 | Message::CompilerMessage(_) => (), | 457 | Message::CompilerMessage(message) => { |
458 | progress(message.target.name.clone()); | ||
459 | } | ||
446 | Message::Unknown => (), | 460 | Message::Unknown => (), |
447 | Message::BuildFinished(_) => {} | 461 | Message::BuildFinished(_) => {} |
448 | Message::TextLine(_) => {} | 462 | Message::TextLine(_) => {} |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 68a235ce3..06a0be284 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -64,7 +64,11 @@ impl fmt::Debug for ProjectWorkspace { | |||
64 | } | 64 | } |
65 | 65 | ||
66 | impl ProjectWorkspace { | 66 | impl ProjectWorkspace { |
67 | pub fn load(manifest: ProjectManifest, config: &CargoConfig) -> Result<ProjectWorkspace> { | 67 | pub fn load( |
68 | manifest: ProjectManifest, | ||
69 | config: &CargoConfig, | ||
70 | progress: &dyn Fn(String), | ||
71 | ) -> Result<ProjectWorkspace> { | ||
68 | let res = match manifest { | 72 | let res = match manifest { |
69 | ProjectManifest::ProjectJson(project_json) => { | 73 | ProjectManifest::ProjectJson(project_json) => { |
70 | let file = fs::read_to_string(&project_json).with_context(|| { | 74 | let file = fs::read_to_string(&project_json).with_context(|| { |
@@ -84,15 +88,14 @@ impl ProjectWorkspace { | |||
84 | cmd | 88 | cmd |
85 | })?; | 89 | })?; |
86 | 90 | ||
87 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, config).with_context( | 91 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, config, progress) |
88 | || { | 92 | .with_context(|| { |
89 | format!( | 93 | format!( |
90 | "Failed to read Cargo metadata from Cargo.toml file {}, {}", | 94 | "Failed to read Cargo metadata from Cargo.toml file {}, {}", |
91 | cargo_toml.display(), | 95 | cargo_toml.display(), |
92 | cargo_version | 96 | cargo_version |
93 | ) | 97 | ) |
94 | }, | 98 | })?; |
95 | )?; | ||
96 | let sysroot = if config.no_sysroot { | 99 | let sysroot = if config.no_sysroot { |
97 | Sysroot::default() | 100 | Sysroot::default() |
98 | } else { | 101 | } else { |
@@ -105,9 +108,12 @@ impl ProjectWorkspace { | |||
105 | }; | 108 | }; |
106 | 109 | ||
107 | let rustc = if let Some(rustc_dir) = &config.rustc_source { | 110 | let rustc = if let Some(rustc_dir) = &config.rustc_source { |
108 | Some(CargoWorkspace::from_cargo_metadata(&rustc_dir, config).with_context( | 111 | Some( |
109 | || format!("Failed to read Cargo metadata for Rust sources"), | 112 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) |
110 | )?) | 113 | .with_context(|| { |
114 | format!("Failed to read Cargo metadata for Rust sources") | ||
115 | })?, | ||
116 | ) | ||
111 | } else { | 117 | } else { |
112 | None | 118 | None |
113 | }; | 119 | }; |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index e5ab6c73b..31a16ca46 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -21,6 +21,7 @@ pub fn load_cargo( | |||
21 | let ws = ProjectWorkspace::load( | 21 | let ws = ProjectWorkspace::load( |
22 | root, | 22 | root, |
23 | &CargoConfig { load_out_dirs_from_check, ..Default::default() }, | 23 | &CargoConfig { load_out_dirs_from_check, ..Default::default() }, |
24 | &|_| {}, | ||
24 | )?; | 25 | )?; |
25 | 26 | ||
26 | let (sender, receiver) = unbounded(); | 27 | let (sender, receiver) = unbounded(); |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 7ac6acf70..22ee96775 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -22,6 +22,7 @@ use crate::{ | |||
22 | global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, | 22 | global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, |
23 | handlers, lsp_ext, | 23 | handlers, lsp_ext, |
24 | lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress}, | 24 | lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress}, |
25 | reload::ProjectWorkspaceProgress, | ||
25 | Result, | 26 | Result, |
26 | }; | 27 | }; |
27 | 28 | ||
@@ -63,6 +64,7 @@ pub(crate) enum Task { | |||
63 | Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>), | 64 | Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>), |
64 | Workspaces(Vec<anyhow::Result<ProjectWorkspace>>), | 65 | Workspaces(Vec<anyhow::Result<ProjectWorkspace>>), |
65 | PrimeCaches(PrimeCachesProgress), | 66 | PrimeCaches(PrimeCachesProgress), |
67 | FetchWorkspace(ProjectWorkspaceProgress), | ||
66 | } | 68 | } |
67 | 69 | ||
68 | impl fmt::Debug for Event { | 70 | impl fmt::Debug for Event { |
@@ -216,6 +218,16 @@ impl GlobalState { | |||
216 | } | 218 | } |
217 | PrimeCachesProgress::Finished => prime_caches_progress.push(progress), | 219 | PrimeCachesProgress::Finished => prime_caches_progress.push(progress), |
218 | }, | 220 | }, |
221 | Task::FetchWorkspace(progress) => { | ||
222 | let (state, msg) = match progress { | ||
223 | ProjectWorkspaceProgress::Begin => (Progress::Begin, None), | ||
224 | ProjectWorkspaceProgress::Report(msg) => { | ||
225 | (Progress::Report, Some(msg)) | ||
226 | } | ||
227 | ProjectWorkspaceProgress::End => (Progress::End, None), | ||
228 | }; | ||
229 | self.report_progress("fetching", state, msg, None); | ||
230 | } | ||
219 | } | 231 | } |
220 | // Coalesce multiple task events into one loop turn | 232 | // Coalesce multiple task events into one loop turn |
221 | task = match self.task_pool.receiver.try_recv() { | 233 | task = match self.task_pool.receiver.try_recv() { |
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 76b50931a..f4e084741 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -15,6 +15,13 @@ use crate::{ | |||
15 | }; | 15 | }; |
16 | use lsp_ext::StatusParams; | 16 | use lsp_ext::StatusParams; |
17 | 17 | ||
18 | #[derive(Debug)] | ||
19 | pub(crate) enum ProjectWorkspaceProgress { | ||
20 | Begin, | ||
21 | Report(String), | ||
22 | End, | ||
23 | } | ||
24 | |||
18 | impl GlobalState { | 25 | impl GlobalState { |
19 | pub(crate) fn update_configuration(&mut self, config: Config) { | 26 | pub(crate) fn update_configuration(&mut self, config: Config) { |
20 | let _p = profile::span("GlobalState::update_configuration"); | 27 | let _p = profile::span("GlobalState::update_configuration"); |
@@ -93,23 +100,42 @@ impl GlobalState { | |||
93 | } | 100 | } |
94 | pub(crate) fn fetch_workspaces(&mut self) { | 101 | pub(crate) fn fetch_workspaces(&mut self) { |
95 | log::info!("will fetch workspaces"); | 102 | log::info!("will fetch workspaces"); |
96 | self.task_pool.handle.spawn({ | 103 | |
104 | self.task_pool.handle.spawn_with_sender({ | ||
97 | let linked_projects = self.config.linked_projects(); | 105 | let linked_projects = self.config.linked_projects(); |
98 | let cargo_config = self.config.cargo(); | 106 | let cargo_config = self.config.cargo(); |
99 | move || { | 107 | |
108 | move |sender| { | ||
109 | let progress = { | ||
110 | let sender = sender.clone(); | ||
111 | move |msg| { | ||
112 | sender | ||
113 | .send(Task::FetchWorkspace(ProjectWorkspaceProgress::Report(msg))) | ||
114 | .unwrap() | ||
115 | } | ||
116 | }; | ||
117 | |||
118 | sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap(); | ||
119 | |||
100 | let workspaces = linked_projects | 120 | let workspaces = linked_projects |
101 | .iter() | 121 | .iter() |
102 | .map(|project| match project { | 122 | .map(|project| match project { |
103 | LinkedProject::ProjectManifest(manifest) => { | 123 | LinkedProject::ProjectManifest(manifest) => { |
104 | project_model::ProjectWorkspace::load(manifest.clone(), &cargo_config) | 124 | project_model::ProjectWorkspace::load( |
125 | manifest.clone(), | ||
126 | &cargo_config, | ||
127 | &progress, | ||
128 | ) | ||
105 | } | 129 | } |
106 | LinkedProject::InlineJsonProject(it) => { | 130 | LinkedProject::InlineJsonProject(it) => { |
107 | project_model::ProjectWorkspace::load_inline(it.clone()) | 131 | project_model::ProjectWorkspace::load_inline(it.clone()) |
108 | } | 132 | } |
109 | }) | 133 | }) |
110 | .collect::<Vec<_>>(); | 134 | .collect::<Vec<_>>(); |
135 | |||
136 | sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::End)).unwrap(); | ||
111 | log::info!("did fetch workspaces {:?}", workspaces); | 137 | log::info!("did fetch workspaces {:?}", workspaces); |
112 | Task::Workspaces(workspaces) | 138 | sender.send(Task::Workspaces(workspaces)).unwrap() |
113 | } | 139 | } |
114 | }); | 140 | }); |
115 | } | 141 | } |