2933: Don't compute diagnostics on the main thread r=matklad a=matklad

closes #2909

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-01-29 10:14:12 +00:00 committed by GitHub
commit 3ea8940d94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,7 +9,7 @@ use std::{error::Error, fmt, panic, path::PathBuf, sync::Arc, time::Instant};
use crossbeam_channel::{select, unbounded, RecvError, Sender};
use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
use lsp_types::{ClientCapabilities, NumberOrString, Url};
use lsp_types::{ClientCapabilities, NumberOrString};
use ra_cargo_watch::{CheckOptions, CheckTask};
use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId};
use ra_prof::profile;
@ -352,7 +352,7 @@ fn loop_turn(
world_state.maybe_collect_garbage();
loop_state.in_flight_libraries -= 1;
}
Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?,
Event::CheckWatcher(task) => on_check_task(pool, task, world_state, task_sender)?,
Event::Msg(msg) => match msg {
Message::Request(req) => on_request(
world_state,
@ -602,31 +602,23 @@ fn on_notification(
}
fn on_check_task(
pool: &ThreadPool,
task: CheckTask,
world_state: &mut WorldState,
task_sender: &Sender<Task>,
) -> Result<()> {
match task {
let urls = match task {
CheckTask::ClearDiagnostics => {
let state = Arc::get_mut(&mut world_state.check_watcher.state)
.expect("couldn't get check watcher state as mutable");
let cleared_files = state.clear();
// Send updated diagnostics for each cleared file
for url in cleared_files {
publish_diagnostics_for_url(&url, world_state, task_sender)?;
}
state.clear()
}
CheckTask::AddDiagnostic(url, diagnostic) => {
let state = Arc::get_mut(&mut world_state.check_watcher.state)
.expect("couldn't get check watcher state as mutable");
state.add_diagnostic_with_fixes(url.clone(), diagnostic);
// We manually send a diagnostic update when the watcher asks
// us to, to avoid the issue of having to change the file to
// receive updated diagnostics.
publish_diagnostics_for_url(&url, world_state, task_sender)?;
vec![url]
}
CheckTask::Status(progress) => {
@ -636,22 +628,30 @@ fn on_check_task(
};
let not = notification_new::<req::Progress>(params);
task_sender.send(Task::Notify(not)).unwrap();
Vec::new()
}
}
Ok(())
}
};
let subscriptions = urls
.into_iter()
.map(|url| {
let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?;
Ok(world_state.vfs.read().path2file(&path).map(|it| FileId(it.0)))
})
.filter_map(|res| res.transpose())
.collect::<Result<Vec<_>>>()?;
// We manually send a diagnostic update when the watcher asks
// us to, to avoid the issue of having to change the file to
// receive updated diagnostics.
update_file_notifications_on_threadpool(
pool,
world_state.snapshot(),
false,
task_sender.clone(),
subscriptions,
);
fn publish_diagnostics_for_url(
url: &Url,
world_state: &WorldState,
task_sender: &Sender<Task>,
) -> Result<()> {
let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?;
if let Some(file_id) = world_state.vfs.read().path2file(&path) {
let params = handlers::publish_diagnostics(&world_state.snapshot(), FileId(file_id.0))?;
let not = notification_new::<req::PublishDiagnostics>(params);
task_sender.send(Task::Notify(not)).unwrap();
}
Ok(())
}