Skip to content

Commit 93605c4

Browse files
committed
Centralize handing of in-flight requests
1 parent 0f7961d commit 93605c4

File tree

4 files changed

+188
-170
lines changed

4 files changed

+188
-170
lines changed

crates/rust-analyzer/src/global_state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use stdx::format_to;
2020
use crate::{
2121
config::{Config, FilesWatcher},
2222
diagnostics::{CheckFixes, DiagnosticCollection},
23-
main_loop::pending_requests::{CompletedRequest, LatestRequests},
23+
main_loop::req_queue::{CompletedInRequest, LatestRequests},
2424
to_proto::url_from_abs_path,
2525
vfs_glob::{Glob, RustPackageFilterBuilder},
2626
LspError, Result,
@@ -236,7 +236,7 @@ impl GlobalState {
236236
self.analysis_host.collect_garbage()
237237
}
238238

239-
pub fn complete_request(&mut self, request: CompletedRequest) {
239+
pub(crate) fn complete_request(&mut self, request: CompletedInRequest) {
240240
self.latest_requests.write().record(request)
241241
}
242242
}

crates/rust-analyzer/src/main_loop.rs

Lines changed: 63 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
mod handlers;
55
mod subscriptions;
6-
pub(crate) mod pending_requests;
6+
pub(crate) mod req_queue;
77

88
use std::{
99
borrow::Cow,
@@ -28,7 +28,6 @@ use ra_ide::{Canceled, FileId, LineIndex};
2828
use ra_prof::profile;
2929
use ra_project_model::{PackageRoot, ProjectWorkspace};
3030
use ra_vfs::VfsTask;
31-
use rustc_hash::FxHashSet;
3231
use serde::{de::DeserializeOwned, Serialize};
3332
use threadpool::ThreadPool;
3433

@@ -38,12 +37,10 @@ use crate::{
3837
from_proto,
3938
global_state::{file_id_to_url, GlobalState, GlobalStateSnapshot},
4039
lsp_ext,
41-
main_loop::{
42-
pending_requests::{PendingRequest, PendingRequests},
43-
subscriptions::Subscriptions,
44-
},
40+
main_loop::subscriptions::Subscriptions,
4541
Result,
4642
};
43+
use req_queue::ReqQueue;
4744

4845
#[derive(Debug)]
4946
pub struct LspError {
@@ -153,10 +150,10 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
153150
register_options: Some(serde_json::to_value(registration_options).unwrap()),
154151
};
155152
let params = lsp_types::RegistrationParams { registrations: vec![registration] };
156-
let request = request_new::<lsp_types::request::RegisterCapability>(
157-
loop_state.next_request_id(),
158-
params,
159-
);
153+
let request = loop_state
154+
.req_queue
155+
.outgoing
156+
.register::<lsp_types::request::RegisterCapability>(params, |_, _| ());
160157
connection.sender.send(request.into()).unwrap();
161158
}
162159

@@ -199,7 +196,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
199196
global_state.analysis_host.request_cancellation();
200197
log::info!("waiting for tasks to finish...");
201198
task_receiver.into_iter().for_each(|task| {
202-
on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut global_state)
199+
on_task(task, &connection.sender, &mut loop_state.req_queue.incoming, &mut global_state)
203200
});
204201
log::info!("...tasks have finished");
205202
log::info!("joining threadpool...");
@@ -264,27 +261,14 @@ impl fmt::Debug for Event {
264261
}
265262
}
266263

267-
#[derive(Debug, Default)]
264+
#[derive(Default)]
268265
struct LoopState {
269-
next_request_id: u64,
270-
pending_responses: FxHashSet<RequestId>,
271-
pending_requests: PendingRequests,
266+
req_queue: ReqQueue<fn(&mut GlobalState, lsp_server::Response)>,
272267
subscriptions: Subscriptions,
273268
workspace_loaded: bool,
274269
roots_progress_reported: Option<usize>,
275270
roots_scanned: usize,
276271
roots_total: usize,
277-
configuration_request_id: Option<RequestId>,
278-
}
279-
280-
impl LoopState {
281-
fn next_request_id(&mut self) -> RequestId {
282-
self.next_request_id += 1;
283-
let res: RequestId = self.next_request_id.into();
284-
let inserted = self.pending_responses.insert(res.clone());
285-
assert!(inserted);
286-
res
287-
}
288272
}
289273

290274
fn loop_turn(
@@ -307,7 +291,7 @@ fn loop_turn(
307291

308292
match event {
309293
Event::Task(task) => {
310-
on_task(task, &connection.sender, &mut loop_state.pending_requests, global_state);
294+
on_task(task, &connection.sender, &mut loop_state.req_queue.incoming, global_state);
311295
global_state.maybe_collect_garbage();
312296
}
313297
Event::Vfs(task) => {
@@ -317,7 +301,7 @@ fn loop_turn(
317301
Event::Msg(msg) => match msg {
318302
Message::Request(req) => on_request(
319303
global_state,
320-
&mut loop_state.pending_requests,
304+
&mut loop_state.req_queue.incoming,
321305
pool,
322306
task_sender,
323307
&connection.sender,
@@ -328,32 +312,8 @@ fn loop_turn(
328312
on_notification(&connection.sender, global_state, loop_state, not)?;
329313
}
330314
Message::Response(resp) => {
331-
let removed = loop_state.pending_responses.remove(&resp.id);
332-
if !removed {
333-
log::error!("unexpected response: {:?}", resp)
334-
}
335-
336-
if Some(&resp.id) == loop_state.configuration_request_id.as_ref() {
337-
loop_state.configuration_request_id = None;
338-
log::debug!("config update response: '{:?}", resp);
339-
let Response { error, result, .. } = resp;
340-
341-
match (error, result) {
342-
(Some(err), _) => {
343-
log::error!("failed to fetch the server settings: {:?}", err)
344-
}
345-
(None, Some(configs)) => {
346-
if let Some(new_config) = configs.get(0) {
347-
let mut config = global_state.config.clone();
348-
config.update(&new_config);
349-
global_state.update_configuration(config);
350-
}
351-
}
352-
(None, None) => {
353-
log::error!("received empty server settings response from the client")
354-
}
355-
}
356-
}
315+
let handler = loop_state.req_queue.outgoing.complete(resp.id.clone());
316+
handler(global_state, resp)
357317
}
358318
},
359319
};
@@ -407,12 +367,12 @@ fn loop_turn(
407367
fn on_task(
408368
task: Task,
409369
msg_sender: &Sender<Message>,
410-
pending_requests: &mut PendingRequests,
370+
incoming_requests: &mut req_queue::Incoming,
411371
state: &mut GlobalState,
412372
) {
413373
match task {
414374
Task::Respond(response) => {
415-
if let Some(completed) = pending_requests.finish(&response.id) {
375+
if let Some(completed) = incoming_requests.complete(response.id.clone()) {
416376
log::info!("handled req#{} in {:?}", completed.id, completed.duration);
417377
state.complete_request(completed);
418378
msg_sender.send(response.into()).unwrap();
@@ -427,7 +387,7 @@ fn on_task(
427387

428388
fn on_request(
429389
global_state: &mut GlobalState,
430-
pending_requests: &mut PendingRequests,
390+
incoming_requests: &mut req_queue::Incoming,
431391
pool: &ThreadPool,
432392
task_sender: &Sender<Task>,
433393
msg_sender: &Sender<Message>,
@@ -440,7 +400,7 @@ fn on_request(
440400
global_state,
441401
task_sender,
442402
msg_sender,
443-
pending_requests,
403+
incoming_requests,
444404
request_received,
445405
};
446406
pool_dispatcher
@@ -504,12 +464,7 @@ fn on_notification(
504464
NumberOrString::Number(id) => id.into(),
505465
NumberOrString::String(id) => id.into(),
506466
};
507-
if loop_state.pending_requests.cancel(&id) {
508-
let response = Response::new_err(
509-
id,
510-
ErrorCode::RequestCanceled as i32,
511-
"canceled by client".to_string(),
512-
);
467+
if let Some(response) = loop_state.req_queue.incoming.cancel(id) {
513468
msg_sender.send(response.into()).unwrap()
514469
}
515470
return Ok(());
@@ -572,18 +527,38 @@ fn on_notification(
572527
Ok(_) => {
573528
// As stated in https://github.com/microsoft/language-server-protocol/issues/676,
574529
// this notification's parameters should be ignored and the actual config queried separately.
575-
let request_id = loop_state.next_request_id();
576-
let request = request_new::<lsp_types::request::WorkspaceConfiguration>(
577-
request_id.clone(),
578-
lsp_types::ConfigurationParams {
579-
items: vec![lsp_types::ConfigurationItem {
580-
scope_uri: None,
581-
section: Some("rust-analyzer".to_string()),
582-
}],
583-
},
584-
);
530+
let request = loop_state
531+
.req_queue
532+
.outgoing
533+
.register::<lsp_types::request::WorkspaceConfiguration>(
534+
lsp_types::ConfigurationParams {
535+
items: vec![lsp_types::ConfigurationItem {
536+
scope_uri: None,
537+
section: Some("rust-analyzer".to_string()),
538+
}],
539+
},
540+
|global_state, resp| {
541+
log::debug!("config update response: '{:?}", resp);
542+
let Response { error, result, .. } = resp;
543+
544+
match (error, result) {
545+
(Some(err), _) => {
546+
log::error!("failed to fetch the server settings: {:?}", err)
547+
}
548+
(None, Some(configs)) => {
549+
if let Some(new_config) = configs.get(0) {
550+
let mut config = global_state.config.clone();
551+
config.update(&new_config);
552+
global_state.update_configuration(config);
553+
}
554+
}
555+
(None, None) => log::error!(
556+
"received empty server settings response from the client"
557+
),
558+
}
559+
},
560+
);
585561
msg_sender.send(request.into())?;
586-
loop_state.configuration_request_id = Some(request_id);
587562

588563
return Ok(());
589564
}
@@ -752,13 +727,16 @@ fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) {
752727

753728
match (prev, loop_state.workspace_loaded) {
754729
(None, false) => {
755-
let work_done_progress_create = request_new::<lsp_types::request::WorkDoneProgressCreate>(
756-
loop_state.next_request_id(),
757-
WorkDoneProgressCreateParams {
758-
token: lsp_types::ProgressToken::String("rustAnalyzer/startup".into()),
759-
},
760-
);
761-
sender.send(work_done_progress_create.into()).unwrap();
730+
let request = loop_state
731+
.req_queue
732+
.outgoing
733+
.register::<lsp_types::request::WorkDoneProgressCreate>(
734+
WorkDoneProgressCreateParams {
735+
token: lsp_types::ProgressToken::String("rustAnalyzer/startup".into()),
736+
},
737+
|_, _| (),
738+
);
739+
sender.send(request.into()).unwrap();
762740
send_startup_progress_notif(
763741
sender,
764742
WorkDoneProgress::Begin(WorkDoneProgressBegin {
@@ -800,7 +778,7 @@ struct PoolDispatcher<'a> {
800778
req: Option<Request>,
801779
pool: &'a ThreadPool,
802780
global_state: &'a mut GlobalState,
803-
pending_requests: &'a mut PendingRequests,
781+
incoming_requests: &'a mut req_queue::Incoming,
804782
msg_sender: &'a Sender<Message>,
805783
task_sender: &'a Sender<Task>,
806784
request_received: Instant,
@@ -829,7 +807,7 @@ impl<'a> PoolDispatcher<'a> {
829807
result_to_task::<R>(id, result)
830808
})
831809
.map_err(|_| format!("sync task {:?} panicked", R::METHOD))?;
832-
on_task(task, self.msg_sender, self.pending_requests, self.global_state);
810+
on_task(task, self.msg_sender, self.incoming_requests, self.global_state);
833811
Ok(self)
834812
}
835813

@@ -876,7 +854,7 @@ impl<'a> PoolDispatcher<'a> {
876854
return None;
877855
}
878856
};
879-
self.pending_requests.start(PendingRequest {
857+
self.incoming_requests.register(req_queue::PendingInRequest {
880858
id: id.clone(),
881859
method: R::METHOD.to_string(),
882860
received: self.request_received,
@@ -993,14 +971,6 @@ where
993971
Notification::new(N::METHOD.to_string(), params)
994972
}
995973

996-
fn request_new<R>(id: RequestId, params: R::Params) -> Request
997-
where
998-
R: lsp_types::request::Request,
999-
R::Params: Serialize,
1000-
{
1001-
Request::new(id, R::METHOD.to_string(), params)
1002-
}
1003-
1004974
#[cfg(test)]
1005975
mod tests {
1006976
use std::borrow::Cow;

crates/rust-analyzer/src/main_loop/pending_requests.rs

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)