aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs38
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs12
-rw-r--r--crates/ra_lsp_server/src/server_world.rs29
3 files changed, 67 insertions, 12 deletions
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index c3580ab67..e65bb0972 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -20,7 +20,7 @@ use crate::{
20 main_loop::subscriptions::Subscriptions, 20 main_loop::subscriptions::Subscriptions,
21 project_model::workspace_loader, 21 project_model::workspace_loader,
22 req, 22 req,
23 server_world::{ServerWorld, ServerWorldState}, 23 server_world::{ServerWorld, ServerWorldState, CompletedRequest},
24 Result, 24 Result,
25 InitializationOptions, 25 InitializationOptions,
26}; 26};
@@ -45,6 +45,17 @@ enum Task {
45 Notify(RawNotification), 45 Notify(RawNotification),
46} 46}
47 47
48struct PendingRequest {
49 received: Instant,
50 method: String,
51}
52
53impl From<(u64, PendingRequest)> for CompletedRequest {
54 fn from((id, pending): (u64, PendingRequest)) -> CompletedRequest {
55 CompletedRequest { id, method: pending.method, duration: pending.received.elapsed() }
56 }
57}
58
48const THREADPOOL_SIZE: usize = 8; 59const THREADPOOL_SIZE: usize = 8;
49 60
50pub fn main_loop( 61pub fn main_loop(
@@ -97,7 +108,9 @@ pub fn main_loop(
97 ); 108 );
98 109
99 log::info!("waiting for tasks to finish..."); 110 log::info!("waiting for tasks to finish...");
100 task_receiver.into_iter().for_each(|task| on_task(task, msg_sender, &mut pending_requests)); 111 task_receiver
112 .into_iter()
113 .for_each(|task| on_task(task, msg_sender, &mut pending_requests, &mut state));
101 log::info!("...tasks have finished"); 114 log::info!("...tasks have finished");
102 log::info!("joining threadpool..."); 115 log::info!("joining threadpool...");
103 drop(pool); 116 drop(pool);
@@ -159,7 +172,7 @@ fn main_loop_inner(
159 task_sender: Sender<Task>, 172 task_sender: Sender<Task>,
160 task_receiver: Receiver<Task>, 173 task_receiver: Receiver<Task>,
161 state: &mut ServerWorldState, 174 state: &mut ServerWorldState,
162 pending_requests: &mut FxHashMap<u64, Instant>, 175 pending_requests: &mut FxHashMap<u64, PendingRequest>,
163 subs: &mut Subscriptions, 176 subs: &mut Subscriptions,
164) -> Result<()> { 177) -> Result<()> {
165 // We try not to index more than THREADPOOL_SIZE - 3 libraries at the same 178 // We try not to index more than THREADPOOL_SIZE - 3 libraries at the same
@@ -195,7 +208,7 @@ fn main_loop_inner(
195 let mut state_changed = false; 208 let mut state_changed = false;
196 match event { 209 match event {
197 Event::Task(task) => { 210 Event::Task(task) => {
198 on_task(task, msg_sender, pending_requests); 211 on_task(task, msg_sender, pending_requests, state);
199 state.maybe_collect_garbage(); 212 state.maybe_collect_garbage();
200 } 213 }
201 Event::Vfs(task) => { 214 Event::Vfs(task) => {
@@ -292,12 +305,15 @@ fn main_loop_inner(
292fn on_task( 305fn on_task(
293 task: Task, 306 task: Task,
294 msg_sender: &Sender<RawMessage>, 307 msg_sender: &Sender<RawMessage>,
295 pending_requests: &mut FxHashMap<u64, Instant>, 308 pending_requests: &mut FxHashMap<u64, PendingRequest>,
309 state: &mut ServerWorldState,
296) { 310) {
297 match task { 311 match task {
298 Task::Respond(response) => { 312 Task::Respond(response) => {
299 if let Some(request_received) = pending_requests.remove(&response.id) { 313 if let Some(pending) = pending_requests.remove(&response.id) {
300 log::info!("handled req#{} in {:?}", response.id, request_received.elapsed()); 314 let completed = CompletedRequest::from((response.id, pending));
315 log::info!("handled req#{} in {:?}", completed.id, completed.duration);
316 state.complete_request(completed);
301 msg_sender.send(response.into()).unwrap(); 317 msg_sender.send(response.into()).unwrap();
302 } 318 }
303 } 319 }
@@ -309,12 +325,13 @@ fn on_task(
309 325
310fn on_request( 326fn on_request(
311 world: &mut ServerWorldState, 327 world: &mut ServerWorldState,
312 pending_requests: &mut FxHashMap<u64, Instant>, 328 pending_requests: &mut FxHashMap<u64, PendingRequest>,
313 pool: &ThreadPool, 329 pool: &ThreadPool,
314 sender: &Sender<Task>, 330 sender: &Sender<Task>,
315 request_received: Instant, 331 request_received: Instant,
316 req: RawRequest, 332 req: RawRequest,
317) -> Result<Option<RawRequest>> { 333) -> Result<Option<RawRequest>> {
334 let method = req.method.clone();
318 let mut pool_dispatcher = PoolDispatcher { req: Some(req), res: None, pool, world, sender }; 335 let mut pool_dispatcher = PoolDispatcher { req: Some(req), res: None, pool, world, sender };
319 let req = pool_dispatcher 336 let req = pool_dispatcher
320 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)? 337 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)?
@@ -348,7 +365,8 @@ fn on_request(
348 .finish(); 365 .finish();
349 match req { 366 match req {
350 Ok(id) => { 367 Ok(id) => {
351 let prev = pending_requests.insert(id, request_received); 368 let prev =
369 pending_requests.insert(id, PendingRequest { method, received: request_received });
352 assert!(prev.is_none(), "duplicate request: {}", id); 370 assert!(prev.is_none(), "duplicate request: {}", id);
353 Ok(None) 371 Ok(None)
354 } 372 }
@@ -359,7 +377,7 @@ fn on_request(
359fn on_notification( 377fn on_notification(
360 msg_sender: &Sender<RawMessage>, 378 msg_sender: &Sender<RawMessage>,
361 state: &mut ServerWorldState, 379 state: &mut ServerWorldState,
362 pending_requests: &mut FxHashMap<u64, Instant>, 380 pending_requests: &mut FxHashMap<u64, PendingRequest>,
363 subs: &mut Subscriptions, 381 subs: &mut Subscriptions,
364 not: RawNotification, 382 not: RawNotification,
365) -> Result<()> { 383) -> Result<()> {
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index e36db12b3..dc817f2d9 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -1,3 +1,5 @@
1use std::{io::Write as _, fmt::Write as _};
2
1use gen_lsp_server::ErrorCode; 3use gen_lsp_server::ErrorCode;
2use lsp_types::{ 4use lsp_types::{
3 CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, CodeAction, 5 CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, CodeAction,
@@ -16,7 +18,6 @@ use ra_prof::profile;
16use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
17use serde::{Serialize, Deserialize}; 19use serde::{Serialize, Deserialize};
18use serde_json::to_value; 20use serde_json::to_value;
19use std::io::Write;
20use url_serde::Ser; 21use url_serde::Ser;
21 22
22use crate::{ 23use crate::{
@@ -28,7 +29,14 @@ use crate::{
28}; 29};
29 30
30pub fn handle_analyzer_status(world: ServerWorld, _: ()) -> Result<String> { 31pub fn handle_analyzer_status(world: ServerWorld, _: ()) -> Result<String> {
31 Ok(world.status()) 32 let mut buf = world.status();
33 writeln!(buf, "\n\nrequests:").unwrap();
34 let requests = world.latest_completed_requests.read();
35 for (idx, r) in requests.iter().enumerate() {
36 let current = if idx == world.request_idx { "*" } else { " " };
37 writeln!(buf, "{:4}{}{:<36}: {:?}", r.id, current, r.method, r.duration).unwrap();
38 }
39 Ok(buf)
32} 40}
33 41
34pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result<String> { 42pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result<String> {
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index b2808b817..b63927a4f 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -1,6 +1,7 @@
1use std::{ 1use std::{
2 path::{Path, PathBuf}, 2 path::{Path, PathBuf},
3 sync::Arc, 3 sync::Arc,
4 time::Duration,
4}; 5};
5 6
6use lsp_types::Url; 7use lsp_types::Url;
@@ -28,12 +29,26 @@ pub struct ServerWorldState {
28 pub workspaces: Arc<Vec<ProjectWorkspace>>, 29 pub workspaces: Arc<Vec<ProjectWorkspace>>,
29 pub analysis_host: AnalysisHost, 30 pub analysis_host: AnalysisHost,
30 pub vfs: Arc<RwLock<Vfs>>, 31 pub vfs: Arc<RwLock<Vfs>>,
32 // hand-rolling VecDeque here to print things in a nicer way
33 pub latest_completed_requests: Arc<RwLock<[CompletedRequest; N_COMPLETED_REQUESTS]>>,
34 pub request_idx: usize,
31} 35}
32 36
37const N_COMPLETED_REQUESTS: usize = 10;
38
33pub struct ServerWorld { 39pub struct ServerWorld {
34 pub workspaces: Arc<Vec<ProjectWorkspace>>, 40 pub workspaces: Arc<Vec<ProjectWorkspace>>,
35 pub analysis: Analysis, 41 pub analysis: Analysis,
36 pub vfs: Arc<RwLock<Vfs>>, 42 pub vfs: Arc<RwLock<Vfs>>,
43 pub latest_completed_requests: Arc<RwLock<[CompletedRequest; N_COMPLETED_REQUESTS]>>,
44 pub request_idx: usize,
45}
46
47#[derive(Debug, Default)]
48pub struct CompletedRequest {
49 pub id: u64,
50 pub method: String,
51 pub duration: Duration,
37} 52}
38 53
39impl ServerWorldState { 54impl ServerWorldState {
@@ -73,6 +88,8 @@ impl ServerWorldState {
73 workspaces: Arc::new(workspaces), 88 workspaces: Arc::new(workspaces),
74 analysis_host, 89 analysis_host,
75 vfs: Arc::new(RwLock::new(vfs)), 90 vfs: Arc::new(RwLock::new(vfs)),
91 latest_completed_requests: Default::default(),
92 request_idx: 0,
76 } 93 }
77 } 94 }
78 95
@@ -137,6 +154,8 @@ impl ServerWorldState {
137 workspaces: Arc::clone(&self.workspaces), 154 workspaces: Arc::clone(&self.workspaces),
138 analysis: self.analysis_host.analysis(), 155 analysis: self.analysis_host.analysis(),
139 vfs: Arc::clone(&self.vfs), 156 vfs: Arc::clone(&self.vfs),
157 latest_completed_requests: Arc::clone(&self.latest_completed_requests),
158 request_idx: self.request_idx.checked_sub(1).unwrap_or(N_COMPLETED_REQUESTS - 1),
140 } 159 }
141 } 160 }
142 161
@@ -147,6 +166,16 @@ impl ServerWorldState {
147 pub fn collect_garbage(&mut self) { 166 pub fn collect_garbage(&mut self) {
148 self.analysis_host.collect_garbage() 167 self.analysis_host.collect_garbage()
149 } 168 }
169
170 pub fn complete_request(&mut self, request: CompletedRequest) {
171 // special case: don't track status request itself
172 if request.method == "rust-analyzer/analyzerStatus" {
173 return;
174 }
175 let idx = self.request_idx;
176 self.latest_completed_requests.write()[idx] = request;
177 self.request_idx = (idx + 1) % N_COMPLETED_REQUESTS;
178 }
150} 179}
151 180
152impl ServerWorld { 181impl ServerWorld {