mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-16 09:48:10 +00:00
Remove RWLock from check watcher.
@matklad mentioned this might be a good idea. So the general idea is that we don't really need the lock, as we can just clone the check watcher state when creating a snapshot. We can then use `Arc::get_mut` to get mutable access to the state from `WorldState` when needed. Running with this it seems to improve responsiveness a bit while cargo is running, but I have no hard numbers to prove it. In any case, a serialization point less is always better when we're trying to be responsive.
This commit is contained in:
parent
2fb8a46122
commit
05aa5b854b
5 changed files with 16 additions and 18 deletions
|
@ -117,7 +117,7 @@ fn is_deprecated(rd: &RustDiagnostic) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SuggestedFix {
|
||||
pub title: String,
|
||||
pub location: Location,
|
||||
|
|
|
@ -7,7 +7,6 @@ use lsp_types::{
|
|||
Diagnostic, Url, WorkDoneProgress, WorkDoneProgressBegin, WorkDoneProgressEnd,
|
||||
WorkDoneProgressReport,
|
||||
};
|
||||
use parking_lot::RwLock;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::PathBuf,
|
||||
|
@ -38,7 +37,7 @@ pub struct CheckOptions {
|
|||
#[derive(Debug)]
|
||||
pub struct CheckWatcher {
|
||||
pub task_recv: Receiver<CheckTask>,
|
||||
pub state: Arc<RwLock<CheckState>>,
|
||||
pub state: Arc<CheckState>,
|
||||
cmd_send: Option<Sender<CheckCommand>>,
|
||||
handle: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
@ -46,7 +45,7 @@ pub struct CheckWatcher {
|
|||
impl CheckWatcher {
|
||||
pub fn new(options: &CheckOptions, workspace_root: PathBuf) -> CheckWatcher {
|
||||
let options = options.clone();
|
||||
let state = Arc::new(RwLock::new(CheckState::new()));
|
||||
let state = Arc::new(CheckState::new());
|
||||
|
||||
let (task_send, task_recv) = unbounded::<CheckTask>();
|
||||
let (cmd_send, cmd_recv) = unbounded::<CheckCommand>();
|
||||
|
@ -59,7 +58,7 @@ impl CheckWatcher {
|
|||
|
||||
/// Returns a CheckWatcher that doesn't actually do anything
|
||||
pub fn dummy() -> CheckWatcher {
|
||||
let state = Arc::new(RwLock::new(CheckState::new()));
|
||||
let state = Arc::new(CheckState::new());
|
||||
CheckWatcher { task_recv: never(), cmd_send: None, handle: None, state }
|
||||
}
|
||||
|
||||
|
@ -87,7 +86,7 @@ impl std::ops::Drop for CheckWatcher {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CheckState {
|
||||
diagnostic_collection: HashMap<Url, Vec<Diagnostic>>,
|
||||
suggested_fix_collection: HashMap<Url, Vec<SuggestedFix>>,
|
||||
|
|
|
@ -586,12 +586,14 @@ fn on_notification(
|
|||
|
||||
fn on_check_task(
|
||||
task: CheckTask,
|
||||
world_state: &WorldState,
|
||||
world_state: &mut WorldState,
|
||||
task_sender: &Sender<Task>,
|
||||
) -> Result<()> {
|
||||
match task {
|
||||
CheckTask::ClearDiagnostics => {
|
||||
let cleared_files = world_state.check_watcher.state.write().clear();
|
||||
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 {
|
||||
|
@ -600,11 +602,9 @@ fn on_check_task(
|
|||
}
|
||||
|
||||
CheckTask::AddDiagnostic(url, diagnostic) => {
|
||||
world_state
|
||||
.check_watcher
|
||||
.state
|
||||
.write()
|
||||
.add_diagnostic_with_fixes(url.clone(), 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
|
||||
|
|
|
@ -674,8 +674,7 @@ pub fn handle_code_action(
|
|||
res.push(action.into());
|
||||
}
|
||||
|
||||
for fix in world.check_watcher.read().fixes_for(¶ms.text_document.uri).into_iter().flatten()
|
||||
{
|
||||
for fix in world.check_watcher.fixes_for(¶ms.text_document.uri).into_iter().flatten() {
|
||||
let fix_range = fix.location.range.conv_with(&line_index);
|
||||
if fix_range.intersection(&range).is_none() {
|
||||
continue;
|
||||
|
@ -895,7 +894,7 @@ pub fn publish_diagnostics(
|
|||
tags: None,
|
||||
})
|
||||
.collect();
|
||||
if let Some(check_diags) = world.check_watcher.read().diagnostics_for(&uri) {
|
||||
if let Some(check_diags) = world.check_watcher.diagnostics_for(&uri) {
|
||||
diagnostics.extend(check_diags.iter().cloned());
|
||||
}
|
||||
Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None })
|
||||
|
|
|
@ -63,7 +63,7 @@ pub struct WorldSnapshot {
|
|||
pub workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
pub analysis: Analysis,
|
||||
pub latest_requests: Arc<RwLock<LatestRequests>>,
|
||||
pub check_watcher: Arc<RwLock<CheckState>>,
|
||||
pub check_watcher: CheckState,
|
||||
vfs: Arc<RwLock<Vfs>>,
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ impl WorldState {
|
|||
analysis: self.analysis_host.analysis(),
|
||||
vfs: Arc::clone(&self.vfs),
|
||||
latest_requests: Arc::clone(&self.latest_requests),
|
||||
check_watcher: self.check_watcher.state.clone(),
|
||||
check_watcher: (*self.check_watcher.state).clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue