Skip to content

Commit cdb7fc7

Browse files
committed
switch to a task-based approach
1 parent f95e042 commit cdb7fc7

File tree

4 files changed

+59
-53
lines changed

4 files changed

+59
-53
lines changed

crates/rust-analyzer/src/global_state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub(crate) struct GlobalState {
8383
pub(crate) last_flycheck_error: Option<String>,
8484

8585
// VFS
86-
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
86+
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle + Send>, Receiver<vfs::loader::Message>>,
8787
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, IntMap<FileId, LineEndings>)>>,
8888
pub(crate) vfs_config_version: u32,
8989
pub(crate) vfs_progress_config_version: u32,
@@ -149,7 +149,7 @@ impl GlobalState {
149149
let (sender, receiver) = unbounded::<vfs::loader::Message>();
150150
let handle: vfs_notify::NotifyHandle =
151151
vfs::loader::Handle::spawn(Box::new(move |msg| sender.send(msg).unwrap()));
152-
let handle = Box::new(handle) as Box<dyn vfs::loader::Handle>;
152+
let handle = Box::new(handle) as Box<dyn vfs::loader::Handle + Send>;
153153
Handle { handle, receiver }
154154
};
155155

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

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ use lsp_types::{
99
DidChangeWatchedFilesParams, DidChangeWorkspaceFoldersParams, DidCloseTextDocumentParams,
1010
DidOpenTextDocumentParams, DidSaveTextDocumentParams, WorkDoneProgressCancelParams,
1111
};
12+
use stdx::thread::ThreadIntent;
1213
use triomphe::Arc;
1314
use vfs::{AbsPathBuf, ChangeKind, VfsPath};
1415

1516
use crate::{
1617
config::Config,
1718
global_state::GlobalState,
18-
lsp::{ext, from_proto, utils::apply_document_changes},
19+
lsp::{from_proto, utils::apply_document_changes},
1920
lsp_ext::RunFlycheckParams,
21+
main_loop::Task,
2022
mem_docs::DocumentData,
2123
reload,
2224
};
@@ -64,13 +66,15 @@ pub(crate) fn handle_did_open_text_document(
6466
if already_exists {
6567
tracing::error!("duplicate DidOpenTextDocument: {}", path);
6668
}
67-
{
68-
let vfs = &mut state.vfs.write().0;
69-
vfs.set_file_contents(path.clone(), Some(params.text_document.text.into_bytes()));
70-
}
69+
70+
let vfs = &mut state.vfs.write().0;
71+
vfs.set_file_contents(path, Some(params.text_document.text.into_bytes()));
7172

7273
if state.config.notifications().unindexed_project {
73-
run_unindexed_project(state, params.text_document.uri)
74+
state.task_pool.handle.spawn(ThreadIntent::Worker, || {
75+
tracing::debug!("dispatching task");
76+
Task::FileIndexState(params.text_document.uri)
77+
});
7478
}
7579
}
7680
Ok(())
@@ -348,25 +352,3 @@ pub(crate) fn handle_run_flycheck(
348352
}
349353
Ok(())
350354
}
351-
352-
pub(crate) fn run_unindexed_project(state: &mut GlobalState, uri: lsp_types::Url) {
353-
let _p = profile::span("run_unindexed_project");
354-
355-
if state.is_quiescent() {
356-
tracing::debug!(processed_changes = state.process_changes());
357-
let id = from_proto::file_id(&state.snapshot(), &uri).expect("Unable to get file ID");
358-
if let Ok(crates) = state.snapshot().analysis.crates_for(id) {
359-
if crates.is_empty() {
360-
tracing::debug!(?uri, "rust-analyzer does not track this file");
361-
let text_documents = vec![lsp_types::TextDocumentIdentifier { uri: uri }];
362-
state.send_notification::<ext::UnindexedProject>(ext::UnindexedProjectParams {
363-
text_documents,
364-
});
365-
} else {
366-
tracing::debug!(?uri, "file is indexed by rust-analyzer")
367-
}
368-
} else {
369-
tracing::warn!("was unable to get analysis for crate")
370-
}
371-
}
372-
}

crates/rust-analyzer/src/main_loop.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! The main loop of `rust-analyzer` responsible for dispatching LSP
22
//! requests/replies and notifications back to the client.
3+
use crate::lsp::ext;
34
use std::{
45
fmt,
56
time::{Duration, Instant},
@@ -65,6 +66,7 @@ pub(crate) enum Task {
6566
Response(lsp_server::Response),
6667
Retry(lsp_server::Request),
6768
Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
69+
FileIndexState(lsp_types::Url),
6870
PrimeCaches(PrimeCachesProgress),
6971
FetchWorkspace(ProjectWorkspaceProgress),
7072
FetchBuildData(BuildDataProgress),
@@ -199,7 +201,7 @@ impl GlobalState {
199201
let _p = profile::span("GlobalState::handle_event");
200202

201203
let event_dbg_msg = format!("{event:?}");
202-
tracing::debug!("{:?} handle_event({})", loop_start, event_dbg_msg);
204+
tracing::debug!(?loop_start, ?event, "handle_event");
203205
if tracing::enabled!(tracing::Level::INFO) {
204206
let task_queue_len = self.task_pool.handle.len();
205207
if task_queue_len > 0 {
@@ -486,6 +488,27 @@ impl GlobalState {
486488
// Only retry requests that haven't been cancelled. Otherwise we do unnecessary work.
487489
Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
488490
Task::Retry(_) => (),
491+
Task::FileIndexState(uri) => {
492+
let _p = profile::span("run_unindexed_project");
493+
494+
tracing::debug!(changes = self.process_changes(), "processes changes");
495+
let snap = self.snapshot();
496+
let id =
497+
crate::lsp::from_proto::file_id(&snap, &uri).expect("Unable to get file ID");
498+
499+
if let Ok(crates) = &snap.analysis.crates_for(id) {
500+
if crates.is_empty() {
501+
tracing::debug!(?uri, "rust-analyzer does not track this file");
502+
self.send_notification::<ext::UnindexedProject>(
503+
ext::UnindexedProjectParams {
504+
text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
505+
},
506+
);
507+
} else {
508+
tracing::warn!("was unable to get analysis for crate")
509+
}
510+
}
511+
}
489512
Task::Diagnostics(diagnostics_per_file) => {
490513
for (file_id, diagnostics) in diagnostics_per_file {
491514
self.diagnostics.set_native_diagnostics(file_id, diagnostics)

crates/rust-analyzer/tests/slow-tests/support.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -203,30 +203,31 @@ impl Server {
203203
N: lsp_types::notification::Notification,
204204
N::Params: Serialize,
205205
{
206-
let msg = recv_timeout(&self.client.receiver).unwrap_or_else(|_| panic!("timed out"));
207-
208-
let Some(Message::Notification(actual)) = msg else {
209-
panic!("did not get a notification");
210-
};
211-
212-
if actual.method == N::METHOD {
213-
let actual = actual
214-
.clone()
215-
.extract::<Value>(N::METHOD)
216-
.expect("was not able to extract notification");
217-
218-
if let Some((expected_part, actual_part)) = find_mismatch(&expected, &actual) {
219-
panic!(
220-
"JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
221-
to_string_pretty(&expected).unwrap(),
222-
to_string_pretty(&actual).unwrap(),
223-
to_string_pretty(expected_part).unwrap(),
224-
to_string_pretty(actual_part).unwrap(),
225-
);
206+
while let Some(Message::Notification(actual)) =
207+
recv_timeout(&self.client.receiver).unwrap_or_else(|_| panic!("timed out"))
208+
{
209+
if actual.method == N::METHOD {
210+
let actual = actual
211+
.clone()
212+
.extract::<Value>(N::METHOD)
213+
.expect("was not able to extract notification");
214+
215+
if let Some((expected_part, actual_part)) = find_mismatch(&expected, &actual) {
216+
panic!(
217+
"JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
218+
to_string_pretty(&expected).unwrap(),
219+
to_string_pretty(&actual).unwrap(),
220+
to_string_pretty(expected_part).unwrap(),
221+
to_string_pretty(actual_part).unwrap(),
222+
);
223+
} else {
224+
return;
225+
}
226+
} else {
227+
continue;
226228
}
227-
} else {
228-
panic!("mismatched method: {}", actual.method);
229229
}
230+
panic!("never got expected notification");
230231
}
231232

232233
#[track_caller]

0 commit comments

Comments
 (0)