aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/main_loop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop.rs')
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs70
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 @@
1mod handlers; 1mod handlers;
2mod subscriptions; 2mod subscriptions;
3pub(crate) mod pending_requests;
3 4
4use std::{fmt, path::PathBuf, sync::Arc, time::Instant, any::TypeId}; 5use std::{fmt, path::PathBuf, sync::Arc, time::Instant, any::TypeId};
5 6
@@ -12,16 +13,18 @@ use gen_lsp_server::{
12use lsp_types::NumberOrString; 13use lsp_types::NumberOrString;
13use ra_ide_api::{Canceled, FileId, LibraryData}; 14use ra_ide_api::{Canceled, FileId, LibraryData};
14use ra_vfs::VfsTask; 15use ra_vfs::VfsTask;
15use rustc_hash::FxHashMap;
16use serde::{de::DeserializeOwned, Serialize}; 16use serde::{de::DeserializeOwned, Serialize};
17use threadpool::ThreadPool; 17use threadpool::ThreadPool;
18use ra_prof::profile; 18use ra_prof::profile;
19 19
20use crate::{ 20use 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)]
46enum Task {
47 Respond(RawResponse),
48 Notify(RawNotification),
49}
50
51struct PendingRequest {
52 id: u64,
53 received: Instant,
54 method: String,
55}
56
57impl 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
67pub fn main_loop( 48pub 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)]
112enum Task {
113 Respond(RawResponse),
114 Notify(RawNotification),
115}
116
131enum Event { 117enum 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(
311fn on_task( 298fn 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
332fn on_request( 318fn 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(
383fn on_notification( 367fn 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,