aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-01-29 09:46:56 +0000
committerAleksey Kladov <[email protected]>2020-01-29 10:03:59 +0000
commit2d2585e03feeaa4a83d59a7ea2cdfbe948526840 (patch)
tree87b2ca2cdf113dedf3a6b28a99ded52e50238b69 /crates/ra_lsp_server
parent3bdf2e0972a1458c28b3095f8d57e580130d09d3 (diff)
Don't compute diagnostics on the main thread
closes #2909
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs56
1 files changed, 28 insertions, 28 deletions
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 15bf519c9..52c7e2bdb 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -9,7 +9,7 @@ use std::{error::Error, fmt, panic, path::PathBuf, sync::Arc, time::Instant};
9 9
10use crossbeam_channel::{select, unbounded, RecvError, Sender}; 10use crossbeam_channel::{select, unbounded, RecvError, Sender};
11use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; 11use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
12use lsp_types::{ClientCapabilities, NumberOrString, Url}; 12use lsp_types::{ClientCapabilities, NumberOrString};
13use ra_cargo_watch::{CheckOptions, CheckTask}; 13use ra_cargo_watch::{CheckOptions, CheckTask};
14use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; 14use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId};
15use ra_prof::profile; 15use ra_prof::profile;
@@ -352,7 +352,7 @@ fn loop_turn(
352 world_state.maybe_collect_garbage(); 352 world_state.maybe_collect_garbage();
353 loop_state.in_flight_libraries -= 1; 353 loop_state.in_flight_libraries -= 1;
354 } 354 }
355 Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?, 355 Event::CheckWatcher(task) => on_check_task(pool, task, world_state, task_sender)?,
356 Event::Msg(msg) => match msg { 356 Event::Msg(msg) => match msg {
357 Message::Request(req) => on_request( 357 Message::Request(req) => on_request(
358 world_state, 358 world_state,
@@ -602,31 +602,23 @@ fn on_notification(
602} 602}
603 603
604fn on_check_task( 604fn on_check_task(
605 pool: &ThreadPool,
605 task: CheckTask, 606 task: CheckTask,
606 world_state: &mut WorldState, 607 world_state: &mut WorldState,
607 task_sender: &Sender<Task>, 608 task_sender: &Sender<Task>,
608) -> Result<()> { 609) -> Result<()> {
609 match task { 610 let urls = match task {
610 CheckTask::ClearDiagnostics => { 611 CheckTask::ClearDiagnostics => {
611 let state = Arc::get_mut(&mut world_state.check_watcher.state) 612 let state = Arc::get_mut(&mut world_state.check_watcher.state)
612 .expect("couldn't get check watcher state as mutable"); 613 .expect("couldn't get check watcher state as mutable");
613 let cleared_files = state.clear(); 614 state.clear()
614
615 // Send updated diagnostics for each cleared file
616 for url in cleared_files {
617 publish_diagnostics_for_url(&url, world_state, task_sender)?;
618 }
619 } 615 }
620 616
621 CheckTask::AddDiagnostic(url, diagnostic) => { 617 CheckTask::AddDiagnostic(url, diagnostic) => {
622 let state = Arc::get_mut(&mut world_state.check_watcher.state) 618 let state = Arc::get_mut(&mut world_state.check_watcher.state)
623 .expect("couldn't get check watcher state as mutable"); 619 .expect("couldn't get check watcher state as mutable");
624 state.add_diagnostic_with_fixes(url.clone(), diagnostic); 620 state.add_diagnostic_with_fixes(url.clone(), diagnostic);
625 621 vec![url]
626 // We manually send a diagnostic update when the watcher asks
627 // us to, to avoid the issue of having to change the file to
628 // receive updated diagnostics.
629 publish_diagnostics_for_url(&url, world_state, task_sender)?;
630 } 622 }
631 623
632 CheckTask::Status(progress) => { 624 CheckTask::Status(progress) => {
@@ -636,22 +628,30 @@ fn on_check_task(
636 }; 628 };
637 let not = notification_new::<req::Progress>(params); 629 let not = notification_new::<req::Progress>(params);
638 task_sender.send(Task::Notify(not)).unwrap(); 630 task_sender.send(Task::Notify(not)).unwrap();
631 Vec::new()
639 } 632 }
640 } 633 };
641 Ok(()) 634
642} 635 let subscriptions = urls
636 .into_iter()
637 .map(|url| {
638 let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?;
639 Ok(world_state.vfs.read().path2file(&path).map(|it| FileId(it.0)))
640 })
641 .filter_map(|res| res.transpose())
642 .collect::<Result<Vec<_>>>()?;
643
644 // We manually send a diagnostic update when the watcher asks
645 // us to, to avoid the issue of having to change the file to
646 // receive updated diagnostics.
647 update_file_notifications_on_threadpool(
648 pool,
649 world_state.snapshot(),
650 false,
651 task_sender.clone(),
652 subscriptions,
653 );
643 654
644fn publish_diagnostics_for_url(
645 url: &Url,
646 world_state: &WorldState,
647 task_sender: &Sender<Task>,
648) -> Result<()> {
649 let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?;
650 if let Some(file_id) = world_state.vfs.read().path2file(&path) {
651 let params = handlers::publish_diagnostics(&world_state.snapshot(), FileId(file_id.0))?;
652 let not = notification_new::<req::PublishDiagnostics>(params);
653 task_sender.send(Task::Notify(not)).unwrap();
654 }
655 Ok(()) 655 Ok(())
656} 656}
657 657