aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--crates/flycheck/Cargo.toml1
-rw-r--r--crates/flycheck/src/lib.rs23
-rw-r--r--crates/project_model/src/cargo_workspace.rs26
-rw-r--r--crates/project_model/src/workspace.rs22
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs1
-rw-r--r--crates/rust-analyzer/src/main_loop.rs12
-rw-r--r--crates/rust-analyzer/src/reload.rs34
-rw-r--r--crates/stdx/src/lib.rs23
9 files changed, 102 insertions, 41 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6b9020424..57383491a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -427,6 +427,7 @@ dependencies = [
427 "jod-thread", 427 "jod-thread",
428 "log", 428 "log",
429 "serde_json", 429 "serde_json",
430 "stdx",
430 "toolchain", 431 "toolchain",
431] 432]
432 433
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml
index 3d9436d69..1bad64a1b 100644
--- a/crates/flycheck/Cargo.toml
+++ b/crates/flycheck/Cargo.toml
@@ -17,3 +17,4 @@ serde_json = "1.0.48"
17jod-thread = "0.1.1" 17jod-thread = "0.1.1"
18 18
19toolchain = { path = "../toolchain", version = "0.0.0" } 19toolchain = { path = "../toolchain", version = "0.0.0" }
20stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index d982c5f29..4388e8c67 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -5,13 +5,13 @@
5use std::{ 5use std::{
6 fmt, 6 fmt,
7 io::{self, BufReader}, 7 io::{self, BufReader},
8 ops,
9 path::PathBuf, 8 path::PathBuf,
10 process::{self, Command, Stdio}, 9 process::{self, Command, Stdio},
11 time::Duration, 10 time::Duration,
12}; 11};
13 12
14use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; 13use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
14use stdx::JodChild;
15 15
16pub use cargo_metadata::diagnostic::{ 16pub use cargo_metadata::diagnostic::{
17 Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan, 17 Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
@@ -323,24 +323,3 @@ impl CargoActor {
323 Ok(read_at_least_one_message) 323 Ok(read_at_least_one_message)
324 } 324 }
325} 325}
326
327struct JodChild(process::Child);
328
329impl ops::Deref for JodChild {
330 type Target = process::Child;
331 fn deref(&self) -> &process::Child {
332 &self.0
333 }
334}
335
336impl ops::DerefMut for JodChild {
337 fn deref_mut(&mut self) -> &mut process::Child {
338 &mut self.0
339 }
340}
341
342impl Drop for JodChild {
343 fn drop(&mut self) {
344 let _ = self.0.kill();
345 }
346}
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 @@
3use std::{ 3use 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
11use anyhow::{Context, Result}; 12use anyhow::{Context, Result};
@@ -15,6 +16,7 @@ use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}
15use itertools::Itertools; 16use itertools::Itertools;
16use paths::{AbsPath, AbsPathBuf}; 17use paths::{AbsPath, AbsPathBuf};
17use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
19use stdx::JodChild;
18 20
19use crate::cfg_flag::CfgFlag; 21use crate::cfg_flag::CfgFlag;
20use crate::utf8_stdout; 22use 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 {
368pub(crate) fn load_extern_resources( 374pub(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
66impl ProjectWorkspace { 66impl 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
68impl fmt::Debug for Event { 70impl 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};
16use lsp_ext::StatusParams; 16use lsp_ext::StatusParams;
17 17
18#[derive(Debug)]
19pub(crate) enum ProjectWorkspaceProgress {
20 Begin,
21 Report(String),
22 End,
23}
24
18impl GlobalState { 25impl 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 }
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 374ed5910..5332edb09 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,5 +1,5 @@
1//! Missing batteries for standard libraries. 1//! Missing batteries for standard libraries.
2use std::time::Instant; 2use std::{ops, process, time::Instant};
3 3
4mod macros; 4mod macros;
5pub mod panic_context; 5pub mod panic_context;
@@ -147,6 +147,27 @@ where
147 left 147 left
148} 148}
149 149
150pub struct JodChild(pub process::Child);
151
152impl ops::Deref for JodChild {
153 type Target = process::Child;
154 fn deref(&self) -> &process::Child {
155 &self.0
156 }
157}
158
159impl ops::DerefMut for JodChild {
160 fn deref_mut(&mut self) -> &mut process::Child {
161 &mut self.0
162 }
163}
164
165impl Drop for JodChild {
166 fn drop(&mut self) {
167 let _ = self.0.kill();
168 }
169}
170
150#[cfg(test)] 171#[cfg(test)]
151mod tests { 172mod tests {
152 use super::*; 173 use super::*;