Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21164 from Wilfred/multiple_discover_requests
fix: Allow multiple discover operations
Lukas Wirth 5 months ago
parent 686320c · parent d2505d9 · commit 42d6802
-rw-r--r--crates/rust-analyzer/src/command.rs18
-rw-r--r--crates/rust-analyzer/src/discover.rs4
-rw-r--r--crates/rust-analyzer/src/global_state.rs8
-rw-r--r--crates/rust-analyzer/src/main_loop.rs65
-rw-r--r--crates/rust-analyzer/src/reload.rs4
5 files changed, 69 insertions, 30 deletions
diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs
index 41055272b1..2f052618cd 100644
--- a/crates/rust-analyzer/src/command.rs
+++ b/crates/rust-analyzer/src/command.rs
@@ -197,4 +197,22 @@ impl<T: Sized + Send + 'static> CommandHandle<T> {
)))
}
}
+
+ pub(crate) fn has_exited(&mut self) -> bool {
+ match self.child.0.try_wait() {
+ Ok(Some(_exit_code)) => {
+ // We have an exit code.
+ true
+ }
+ Ok(None) => {
+ // Hasn't exited yet.
+ false
+ }
+ Err(_) => {
+ // Couldn't get an exit code. Assume that we've
+ // exited.
+ true
+ }
+ }
+ }
}
diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs
index 0e96eff278..4aef5b0b7f 100644
--- a/crates/rust-analyzer/src/discover.rs
+++ b/crates/rust-analyzer/src/discover.rs
@@ -67,7 +67,7 @@ impl DiscoverCommand {
cmd.args(args);
Ok(DiscoverHandle {
- _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?,
+ handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?,
span: info_span!("discover_command").entered(),
})
}
@@ -76,7 +76,7 @@ impl DiscoverCommand {
/// A handle to a spawned [Discover].
#[derive(Debug)]
pub(crate) struct DiscoverHandle {
- _handle: CommandHandle<DiscoverProjectMessage>,
+ pub(crate) handle: CommandHandle<DiscoverProjectMessage>,
#[allow(dead_code)] // not accessed, but used to log on drop.
span: EnteredSpan,
}
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 9f58c17ac0..7828f50844 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -121,9 +121,10 @@ pub(crate) struct GlobalState {
pub(crate) test_run_remaining_jobs: usize,
// Project loading
- pub(crate) discover_handle: Option<discover::DiscoverHandle>,
+ pub(crate) discover_handles: Vec<discover::DiscoverHandle>,
pub(crate) discover_sender: Sender<discover::DiscoverProjectMessage>,
pub(crate) discover_receiver: Receiver<discover::DiscoverProjectMessage>,
+ pub(crate) discover_jobs_active: u32,
// Debouncing channel for fetching the workspace
// we want to delay it until the VFS looks stable-ish (and thus is not currently in the middle
@@ -175,7 +176,6 @@ pub(crate) struct GlobalState {
pub(crate) fetch_build_data_queue: OpQueue<(), FetchBuildDataResponse>,
pub(crate) fetch_proc_macros_queue: OpQueue<(ChangeWithProcMacros, Vec<ProcMacroPaths>), bool>,
pub(crate) prime_caches_queue: OpQueue,
- pub(crate) discover_workspace_queue: OpQueue,
/// A deferred task queue.
///
@@ -292,9 +292,10 @@ impl GlobalState {
test_run_receiver,
test_run_remaining_jobs: 0,
- discover_handle: None,
+ discover_handles: vec![],
discover_sender,
discover_receiver,
+ discover_jobs_active: 0,
fetch_ws_receiver: None,
@@ -313,7 +314,6 @@ impl GlobalState {
fetch_proc_macros_queue: OpQueue::default(),
prime_caches_queue: OpQueue::default(),
- discover_workspace_queue: OpQueue::default(),
deferred_task_queue,
incomplete_crate_graph: false,
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 04c416267f..77dedf1272 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -531,6 +531,8 @@ impl GlobalState {
}
}
+ self.cleanup_discover_handles();
+
if let Some(diagnostic_changes) = self.diagnostics.take_changes() {
for file_id in diagnostic_changes {
let uri = file_id_to_url(&self.vfs.read().0, file_id);
@@ -806,33 +808,34 @@ impl GlobalState {
self.report_progress("Fetching", state, msg, None, None);
}
Task::DiscoverLinkedProjects(arg) => {
- if let Some(cfg) = self.config.discover_workspace_config()
- && !self.discover_workspace_queue.op_in_progress()
- {
+ if let Some(cfg) = self.config.discover_workspace_config() {
// the clone is unfortunately necessary to avoid a borrowck error when
// `self.report_progress` is called later
let title = &cfg.progress_label.clone();
let command = cfg.command.clone();
let discover = DiscoverCommand::new(self.discover_sender.clone(), command);
- self.report_progress(title, Progress::Begin, None, None, None);
- self.discover_workspace_queue
- .request_op("Discovering workspace".to_owned(), ());
- let _ = self.discover_workspace_queue.should_start_op();
+ if self.discover_jobs_active == 0 {
+ self.report_progress(title, Progress::Begin, None, None, None);
+ }
+ self.discover_jobs_active += 1;
let arg = match arg {
DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
};
- let handle = discover.spawn(
- arg,
- &std::env::current_dir()
- .expect("Failed to get cwd during project discovery"),
- );
- self.discover_handle = Some(handle.unwrap_or_else(|e| {
- panic!("Failed to spawn project discovery command: {e}")
- }));
+ let handle = discover
+ .spawn(
+ arg,
+ &std::env::current_dir()
+ .expect("Failed to get cwd during project discovery"),
+ )
+ .unwrap_or_else(|e| {
+ panic!("Failed to spawn project discovery command: {e}")
+ });
+
+ self.discover_handles.push(handle);
}
}
Task::FetchBuildData(progress) => {
@@ -1036,25 +1039,43 @@ impl GlobalState {
.expect("No title could be found; this is a bug");
match message {
DiscoverProjectMessage::Finished { project, buildfile } => {
- self.discover_handle = None;
- self.report_progress(&title, Progress::End, None, None, None);
- self.discover_workspace_queue.op_completed(());
+ self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1);
+ if self.discover_jobs_active == 0 {
+ self.report_progress(&title, Progress::End, None, None, None);
+ }
let mut config = Config::clone(&*self.config);
config.add_discovered_project_from_command(project, buildfile);
self.update_configuration(config);
}
DiscoverProjectMessage::Progress { message } => {
- self.report_progress(&title, Progress::Report, Some(message), None, None)
+ if self.discover_jobs_active > 0 {
+ self.report_progress(&title, Progress::Report, Some(message), None, None)
+ }
}
DiscoverProjectMessage::Error { error, source } => {
- self.discover_handle = None;
let message = format!("Project discovery failed: {error}");
- self.discover_workspace_queue.op_completed(());
self.show_and_log_error(message.clone(), source);
- self.report_progress(&title, Progress::End, Some(message), None, None)
+
+ self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1);
+ if self.discover_jobs_active == 0 {
+ self.report_progress(&title, Progress::End, Some(message), None, None)
+ }
+ }
+ }
+ }
+
+ /// Drop any discover command processes that have exited, due to
+ /// finishing or erroring.
+ fn cleanup_discover_handles(&mut self) {
+ let mut active_handles = vec![];
+
+ for mut discover_handle in self.discover_handles.drain(..) {
+ if !discover_handle.handle.has_exited() {
+ active_handles.push(discover_handle);
}
}
+ self.discover_handles = active_handles;
}
fn handle_cargo_test_msg(&mut self, message: CargoTestMessage) {
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 8876b850be..317c112365 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -74,7 +74,7 @@ impl GlobalState {
&& !self.fetch_workspaces_queue.op_in_progress()
&& !self.fetch_build_data_queue.op_in_progress()
&& !self.fetch_proc_macros_queue.op_in_progress()
- && !self.discover_workspace_queue.op_in_progress()
+ && self.discover_jobs_active == 0
&& self.vfs_progress_config_version >= self.vfs_config_version
}
@@ -297,7 +297,7 @@ impl GlobalState {
.collect();
let cargo_config = self.config.cargo(None);
let discover_command = self.config.discover_workspace_config().cloned();
- let is_quiescent = !(self.discover_workspace_queue.op_in_progress()
+ let is_quiescent = !(self.discover_jobs_active > 0
|| self.vfs_progress_config_version < self.vfs_config_version
|| !self.vfs_done);