diff options
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop.rs')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 70 |
1 files changed, 27 insertions, 43 deletions
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 0184c8546..e3cae94f4 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | mod handlers; | 1 | mod handlers; |
2 | mod subscriptions; | 2 | mod subscriptions; |
3 | pub(crate) mod pending_requests; | ||
3 | 4 | ||
4 | use std::{fmt, path::PathBuf, sync::Arc, time::Instant, any::TypeId}; | 5 | use std::{fmt, path::PathBuf, sync::Arc, time::Instant, any::TypeId}; |
5 | 6 | ||
@@ -12,16 +13,18 @@ use gen_lsp_server::{ | |||
12 | use lsp_types::NumberOrString; | 13 | use lsp_types::NumberOrString; |
13 | use ra_ide_api::{Canceled, FileId, LibraryData}; | 14 | use ra_ide_api::{Canceled, FileId, LibraryData}; |
14 | use ra_vfs::VfsTask; | 15 | use ra_vfs::VfsTask; |
15 | use rustc_hash::FxHashMap; | ||
16 | use serde::{de::DeserializeOwned, Serialize}; | 16 | use serde::{de::DeserializeOwned, Serialize}; |
17 | use threadpool::ThreadPool; | 17 | use threadpool::ThreadPool; |
18 | use ra_prof::profile; | 18 | use ra_prof::profile; |
19 | 19 | ||
20 | use crate::{ | 20 | use crate::{ |
21 | main_loop::subscriptions::Subscriptions, | 21 | main_loop::{ |
22 | subscriptions::Subscriptions, | ||
23 | pending_requests::{PendingRequests, PendingRequest}, | ||
24 | }, | ||
22 | project_model::workspace_loader, | 25 | project_model::workspace_loader, |
23 | req, | 26 | req, |
24 | server_world::{ServerWorld, ServerWorldState, CompletedRequest}, | 27 | server_world::{ServerWorld, ServerWorldState}, |
25 | Result, | 28 | Result, |
26 | InitializationOptions, | 29 | InitializationOptions, |
27 | }; | 30 | }; |
@@ -42,37 +45,12 @@ impl LspError { | |||
42 | } | 45 | } |
43 | } | 46 | } |
44 | 47 | ||
45 | #[derive(Debug)] | ||
46 | enum Task { | ||
47 | Respond(RawResponse), | ||
48 | Notify(RawNotification), | ||
49 | } | ||
50 | |||
51 | struct PendingRequest { | ||
52 | id: u64, | ||
53 | received: Instant, | ||
54 | method: String, | ||
55 | } | ||
56 | |||
57 | impl From<PendingRequest> for CompletedRequest { | ||
58 | fn from(pending: PendingRequest) -> CompletedRequest { | ||
59 | CompletedRequest { | ||
60 | id: pending.id, | ||
61 | method: pending.method, | ||
62 | duration: pending.received.elapsed(), | ||
63 | } | ||
64 | } | ||
65 | } | ||
66 | |||
67 | pub fn main_loop( | 48 | pub fn main_loop( |
68 | ws_roots: Vec<PathBuf>, | 49 | ws_roots: Vec<PathBuf>, |
69 | options: InitializationOptions, | 50 | options: InitializationOptions, |
70 | msg_receiver: &Receiver<RawMessage>, | 51 | msg_receiver: &Receiver<RawMessage>, |
71 | msg_sender: &Sender<RawMessage>, | 52 | msg_sender: &Sender<RawMessage>, |
72 | ) -> Result<()> { | 53 | ) -> Result<()> { |
73 | let pool = ThreadPool::new(THREADPOOL_SIZE); | ||
74 | let (task_sender, task_receiver) = unbounded::<Task>(); | ||
75 | |||
76 | // FIXME: support dynamic workspace loading. | 54 | // FIXME: support dynamic workspace loading. |
77 | let workspaces = { | 55 | let workspaces = { |
78 | let ws_worker = workspace_loader(); | 56 | let ws_worker = workspace_loader(); |
@@ -97,10 +75,12 @@ pub fn main_loop( | |||
97 | 75 | ||
98 | let mut state = ServerWorldState::new(ws_roots, workspaces); | 76 | let mut state = ServerWorldState::new(ws_roots, workspaces); |
99 | 77 | ||
100 | log::info!("server initialized, serving requests"); | 78 | let pool = ThreadPool::new(THREADPOOL_SIZE); |
79 | let (task_sender, task_receiver) = unbounded::<Task>(); | ||
80 | let mut pending_requests = PendingRequests::default(); | ||
81 | let mut subs = Subscriptions::default(); | ||
101 | 82 | ||
102 | let mut pending_requests = FxHashMap::default(); | 83 | log::info!("server initialized, serving requests"); |
103 | let mut subs = Subscriptions::new(); | ||
104 | let main_res = main_loop_inner( | 84 | let main_res = main_loop_inner( |
105 | options, | 85 | options, |
106 | &pool, | 86 | &pool, |
@@ -128,6 +108,12 @@ pub fn main_loop( | |||
128 | main_res | 108 | main_res |
129 | } | 109 | } |
130 | 110 | ||
111 | #[derive(Debug)] | ||
112 | enum Task { | ||
113 | Respond(RawResponse), | ||
114 | Notify(RawNotification), | ||
115 | } | ||
116 | |||
131 | enum Event { | 117 | enum Event { |
132 | Msg(RawMessage), | 118 | Msg(RawMessage), |
133 | Task(Task), | 119 | Task(Task), |
@@ -178,7 +164,7 @@ fn main_loop_inner( | |||
178 | task_sender: Sender<Task>, | 164 | task_sender: Sender<Task>, |
179 | task_receiver: Receiver<Task>, | 165 | task_receiver: Receiver<Task>, |
180 | state: &mut ServerWorldState, | 166 | state: &mut ServerWorldState, |
181 | pending_requests: &mut FxHashMap<u64, PendingRequest>, | 167 | pending_requests: &mut PendingRequests, |
182 | subs: &mut Subscriptions, | 168 | subs: &mut Subscriptions, |
183 | ) -> Result<()> { | 169 | ) -> Result<()> { |
184 | // We try not to index more than MAX_IN_FLIGHT_LIBS libraries at the same | 170 | // We try not to index more than MAX_IN_FLIGHT_LIBS libraries at the same |
@@ -202,15 +188,16 @@ fn main_loop_inner( | |||
202 | }, | 188 | }, |
203 | recv(libdata_receiver) -> data => Event::Lib(data.unwrap()) | 189 | recv(libdata_receiver) -> data => Event::Lib(data.unwrap()) |
204 | }; | 190 | }; |
205 | // NOTE: don't count blocking select! call as a loop-turn time | ||
206 | let _p = profile("main_loop_inner/loop-turn"); | ||
207 | let loop_start = Instant::now(); | 191 | let loop_start = Instant::now(); |
208 | 192 | ||
193 | // NOTE: don't count blocking select! call as a loop-turn time | ||
194 | let _p = profile("main_loop_inner/loop-turn"); | ||
209 | log::info!("loop turn = {:?}", event); | 195 | log::info!("loop turn = {:?}", event); |
210 | let queue_count = pool.queued_count(); | 196 | let queue_count = pool.queued_count(); |
211 | if queue_count > 0 { | 197 | if queue_count > 0 { |
212 | log::info!("queued count = {}", queue_count); | 198 | log::info!("queued count = {}", queue_count); |
213 | } | 199 | } |
200 | |||
214 | let mut state_changed = false; | 201 | let mut state_changed = false; |
215 | match event { | 202 | match event { |
216 | Event::Task(task) => { | 203 | Event::Task(task) => { |
@@ -311,13 +298,12 @@ fn main_loop_inner( | |||
311 | fn on_task( | 298 | fn on_task( |
312 | task: Task, | 299 | task: Task, |
313 | msg_sender: &Sender<RawMessage>, | 300 | msg_sender: &Sender<RawMessage>, |
314 | pending_requests: &mut FxHashMap<u64, PendingRequest>, | 301 | pending_requests: &mut PendingRequests, |
315 | state: &mut ServerWorldState, | 302 | state: &mut ServerWorldState, |
316 | ) { | 303 | ) { |
317 | match task { | 304 | match task { |
318 | Task::Respond(response) => { | 305 | Task::Respond(response) => { |
319 | if let Some(pending) = pending_requests.remove(&response.id) { | 306 | if let Some(completed) = pending_requests.finish(response.id) { |
320 | let completed = CompletedRequest::from(pending); | ||
321 | log::info!("handled req#{} in {:?}", completed.id, completed.duration); | 307 | log::info!("handled req#{} in {:?}", completed.id, completed.duration); |
322 | state.complete_request(completed); | 308 | state.complete_request(completed); |
323 | msg_sender.send(response.into()).unwrap(); | 309 | msg_sender.send(response.into()).unwrap(); |
@@ -331,7 +317,7 @@ fn on_task( | |||
331 | 317 | ||
332 | fn on_request( | 318 | fn on_request( |
333 | world: &mut ServerWorldState, | 319 | world: &mut ServerWorldState, |
334 | pending_requests: &mut FxHashMap<u64, PendingRequest>, | 320 | pending_requests: &mut PendingRequests, |
335 | pool: &ThreadPool, | 321 | pool: &ThreadPool, |
336 | sender: &Sender<Task>, | 322 | sender: &Sender<Task>, |
337 | request_received: Instant, | 323 | request_received: Instant, |
@@ -371,9 +357,7 @@ fn on_request( | |||
371 | .finish(); | 357 | .finish(); |
372 | match req { | 358 | match req { |
373 | Ok(id) => { | 359 | Ok(id) => { |
374 | let prev = pending_requests | 360 | pending_requests.start(PendingRequest { id, method, received: request_received }); |
375 | .insert(id, PendingRequest { id, method, received: request_received }); | ||
376 | assert!(prev.is_none(), "duplicate request: {}", id); | ||
377 | Ok(None) | 361 | Ok(None) |
378 | } | 362 | } |
379 | Err(req) => Ok(Some(req)), | 363 | Err(req) => Ok(Some(req)), |
@@ -383,7 +367,7 @@ fn on_request( | |||
383 | fn on_notification( | 367 | fn on_notification( |
384 | msg_sender: &Sender<RawMessage>, | 368 | msg_sender: &Sender<RawMessage>, |
385 | state: &mut ServerWorldState, | 369 | state: &mut ServerWorldState, |
386 | pending_requests: &mut FxHashMap<u64, PendingRequest>, | 370 | pending_requests: &mut PendingRequests, |
387 | subs: &mut Subscriptions, | 371 | subs: &mut Subscriptions, |
388 | not: RawNotification, | 372 | not: RawNotification, |
389 | ) -> Result<()> { | 373 | ) -> Result<()> { |
@@ -395,7 +379,7 @@ fn on_notification( | |||
395 | panic!("string id's not supported: {:?}", id); | 379 | panic!("string id's not supported: {:?}", id); |
396 | } | 380 | } |
397 | }; | 381 | }; |
398 | if pending_requests.remove(&id).is_some() { | 382 | if pending_requests.cancel(id) { |
399 | let response = RawResponse::err( | 383 | let response = RawResponse::err( |
400 | id, | 384 | id, |
401 | ErrorCode::RequestCanceled as i32, | 385 | ErrorCode::RequestCanceled as i32, |