Skip to content

Commit 448eafb

Browse files
committed
Create a TaskQueue that runs only after GlobalState::process_changes runs
1 parent 437baf6 commit 448eafb

File tree

4 files changed

+70
-27
lines changed

4 files changed

+70
-27
lines changed

crates/rust-analyzer/src/global_state.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::{
3232
mem_docs::MemDocs,
3333
op_queue::OpQueue,
3434
reload,
35-
task_pool::TaskPool,
35+
task_pool::{TaskPool, TaskQueue},
3636
};
3737

3838
// Enforces drop order
@@ -125,6 +125,11 @@ pub(crate) struct GlobalState {
125125
pub(crate) fetch_proc_macros_queue: OpQueue<Vec<ProcMacroPaths>, bool>,
126126
pub(crate) prime_caches_queue: OpQueue,
127127

128+
/// a deferred task queue. this should only be used if the enqueued Task
129+
/// can only run *after* [`GlobalState::process_changes`] has been called.
130+
pub(crate) task_queue: TaskQueue,
131+
}
132+
128133
#[derive(Clone)]
129134
pub(crate) struct Conn {
130135
pub(crate) sender: Sender<lsp_server::Message>,
@@ -170,13 +175,18 @@ impl GlobalState {
170175
Handle { handle, receiver }
171176
};
172177

178+
let task_queue = {
179+
let (sender, receiver) = unbounded();
180+
TaskQueue { sender, receiver }
181+
};
182+
173183
let mut analysis_host = AnalysisHost::new(config.lru_parse_query_capacity());
174184
if let Some(capacities) = config.lru_query_capacities() {
175185
analysis_host.update_lru_capacities(capacities);
176186
}
177187
let (flycheck_sender, flycheck_receiver) = unbounded();
178188
let mut this = GlobalState {
179-
conn: server,
189+
conn,
180190
task_pool,
181191
fmt_pool,
182192
loader,
@@ -214,6 +224,8 @@ impl GlobalState {
214224
fetch_proc_macros_queue: OpQueue::default(),
215225

216226
prime_caches_queue: OpQueue::default(),
227+
228+
task_queue,
217229
};
218230
// Apply any required database inputs from the config.
219231
this.update_configuration(config);

crates/rust-analyzer/src/handlers/notification.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use lsp_types::{
99
DidChangeWatchedFilesParams, DidChangeWorkspaceFoldersParams, DidCloseTextDocumentParams,
1010
DidOpenTextDocumentParams, DidSaveTextDocumentParams, WorkDoneProgressCancelParams,
1111
};
12-
use stdx::thread::ThreadIntent;
1312
use triomphe::Arc;
1413
use vfs::{AbsPathBuf, ChangeKind, VfsPath};
1514

@@ -18,7 +17,6 @@ use crate::{
1817
global_state::GlobalState,
1918
lsp::{from_proto, utils::apply_document_changes},
2019
lsp_ext::RunFlycheckParams,
21-
main_loop::Task,
2220
mem_docs::DocumentData,
2321
reload,
2422
};
@@ -68,12 +66,12 @@ pub(crate) fn handle_did_open_text_document(
6866
}
6967

7068
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
71-
7269
if state.config.notifications().unindexed_project {
73-
state.task_pool.handle.spawn(ThreadIntent::Worker, || {
74-
tracing::debug!("dispatching task");
75-
Task::FileIndexState(params.text_document.uri)
76-
});
70+
tracing::debug!("queuing task");
71+
let _ = state
72+
.task_queue
73+
.sender
74+
.send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri));
7775
}
7876
}
7977
Ok(())

crates/rust-analyzer/src/main_loop.rs

+40-18
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,21 @@ pub fn main_loop(config: Config, connection: Connection) -> anyhow::Result<()> {
5757
enum Event {
5858
Lsp(lsp_server::Message),
5959
Task(Task),
60+
QueuedTask(QueuedTask),
6061
Vfs(vfs::loader::Message),
6162
Flycheck(flycheck::Message),
6263
}
6364

65+
#[derive(Debug)]
66+
pub(crate) enum QueuedTask {
67+
CheckIfIndexed(lsp_types::Url),
68+
}
69+
6470
#[derive(Debug)]
6571
pub(crate) enum Task {
6672
Response(lsp_server::Response),
6773
Retry(lsp_server::Request),
6874
Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
69-
FileIndexState(lsp_types::Url),
7075
PrimeCaches(PrimeCachesProgress),
7176
FetchWorkspace(ProjectWorkspaceProgress),
7277
FetchBuildData(BuildDataProgress),
@@ -106,6 +111,7 @@ impl fmt::Debug for Event {
106111
match self {
107112
Event::Lsp(it) => fmt::Debug::fmt(it, f),
108113
Event::Task(it) => fmt::Debug::fmt(it, f),
114+
Event::QueuedTask(it) => fmt::Debug::fmt(it, f),
109115
Event::Vfs(it) => fmt::Debug::fmt(it, f),
110116
Event::Flycheck(it) => fmt::Debug::fmt(it, f),
111117
}
@@ -184,6 +190,9 @@ impl GlobalState {
184190
recv(self.task_pool.receiver) -> task =>
185191
Some(Event::Task(task.unwrap())),
186192

193+
recv(self.task_queue.receiver) -> task =>
194+
Some(Event::QueuedTask(task.unwrap())),
195+
187196
recv(self.fmt_pool.receiver) -> task =>
188197
Some(Event::Task(task.unwrap())),
189198

@@ -216,6 +225,10 @@ impl GlobalState {
216225
lsp_server::Message::Notification(not) => self.on_notification(not)?,
217226
lsp_server::Message::Response(resp) => self.complete_request(resp),
218227
},
228+
Event::QueuedTask(task) => {
229+
let _p = profile::span("GlobalState::handle_event/deferred_task");
230+
self.handle_deferred_task(task);
231+
}
219232
Event::Task(task) => {
220233
let _p = profile::span("GlobalState::handle_event/task");
221234
let mut prime_caches_progress = Vec::new();
@@ -488,23 +501,6 @@ impl GlobalState {
488501
// Only retry requests that haven't been cancelled. Otherwise we do unnecessary work.
489502
Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
490503
Task::Retry(_) => (),
491-
Task::FileIndexState(uri) => {
492-
let _p = profile::span("run_unindexed_project");
493-
let snap = self.snapshot();
494-
let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
495-
if let Ok(crates) = &snap.analysis.crates_for(id) {
496-
if crates.is_empty() {
497-
tracing::debug!(?uri, "rust-analyzer does not track this file");
498-
self.send_notification::<ext::UnindexedProject>(
499-
ext::UnindexedProjectParams {
500-
text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
501-
},
502-
);
503-
} else {
504-
tracing::warn!("was unable to get analysis for crate")
505-
}
506-
}
507-
}
508504
Task::Diagnostics(diagnostics_per_file) => {
509505
for (file_id, diagnostics) in diagnostics_per_file {
510506
self.diagnostics.set_native_diagnostics(file_id, diagnostics)
@@ -626,6 +622,32 @@ impl GlobalState {
626622
}
627623
}
628624

625+
fn handle_deferred_task(&mut self, task: QueuedTask) {
626+
match task {
627+
QueuedTask::CheckIfIndexed(uri) => {
628+
let snap = self.snapshot();
629+
let conn = self.conn.clone();
630+
631+
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |_| {
632+
tracing::debug!(?uri, "handling uri");
633+
let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
634+
if let Ok(crates) = &snap.analysis.crates_for(id) {
635+
if crates.is_empty() {
636+
conn.send_notification::<ext::UnindexedProject>(
637+
ext::UnindexedProjectParams {
638+
text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
639+
},
640+
);
641+
tracing::debug!("sent notification");
642+
} else {
643+
tracing::debug!(?uri, "is indexed");
644+
}
645+
}
646+
});
647+
}
648+
}
649+
}
650+
629651
fn handle_flycheck_msg(&mut self, message: flycheck::Message) {
630652
match message {
631653
flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => {

crates/rust-analyzer/src/task_pool.rs

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
use crossbeam_channel::Sender;
55
use stdx::thread::{Pool, ThreadIntent};
66

7+
use crate::main_loop::QueuedTask;
8+
79
pub(crate) struct TaskPool<T> {
810
sender: Sender<T>,
911
pool: Pool,
@@ -40,3 +42,12 @@ impl<T> TaskPool<T> {
4042
self.pool.len()
4143
}
4244
}
45+
46+
/// `TaskQueue`, like its name suggests, queues tasks.
47+
///
48+
/// This should only be used used if a task must run after [`GlobalState::process_changes`]
49+
/// has been called.
50+
pub(crate) struct TaskQueue {
51+
pub(crate) sender: crossbeam_channel::Sender<QueuedTask>,
52+
pub(crate) receiver: crossbeam_channel::Receiver<QueuedTask>,
53+
}

0 commit comments

Comments
 (0)