Merge pull request #1247 from zed-industries/ignore-non-created-progress-tokens

Ignore tokens that were not created via `WorkDoneProgressCreate`
This commit is contained in:
Antonio Scandurra 2022-06-28 10:14:42 +02:00 committed by GitHub
commit a53de67e6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 40 deletions

View file

@ -2995,6 +2995,7 @@ async fn test_language_server_statuses(
.unwrap(); .unwrap();
let fake_language_server = fake_language_servers.next().await.unwrap(); let fake_language_server = fake_language_servers.next().await.unwrap();
fake_language_server.start_progress("the-token").await;
fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams { fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
token: lsp::NumberOrString::String("the-token".to_string()), token: lsp::NumberOrString::String("the-token".to_string()),
value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report( value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(

View file

@ -655,6 +655,14 @@ impl FakeLanguageServer {
self.server.notify::<T>(params).ok(); self.server.notify::<T>(params).ok();
} }
pub async fn request<T>(&self, params: T::Params) -> Result<T::Result>
where
T: request::Request,
T::Result: 'static + Send,
{
self.server.request::<T>(params).await
}
pub async fn receive_notification<T: notification::Notification>(&mut self) -> T::Params { pub async fn receive_notification<T: notification::Notification>(&mut self) -> T::Params {
self.try_receive_notification::<T>().await.unwrap() self.try_receive_notification::<T>().await.unwrap()
} }
@ -708,14 +716,20 @@ impl FakeLanguageServer {
self.server.remove_request_handler::<T>(); self.server.remove_request_handler::<T>();
} }
pub async fn start_progress(&mut self, token: impl Into<String>) { pub async fn start_progress(&self, token: impl Into<String>) {
let token = token.into();
self.request::<request::WorkDoneProgressCreate>(WorkDoneProgressCreateParams {
token: NumberOrString::String(token.clone()),
})
.await
.unwrap();
self.notify::<notification::Progress>(ProgressParams { self.notify::<notification::Progress>(ProgressParams {
token: NumberOrString::String(token.into()), token: NumberOrString::String(token),
value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(Default::default())), value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(Default::default())),
}); });
} }
pub async fn end_progress(&mut self, token: impl Into<String>) { pub fn end_progress(&self, token: impl Into<String>) {
self.notify::<notification::Progress>(ProgressParams { self.notify::<notification::Progress>(ProgressParams {
token: NumberOrString::String(token.into()), token: NumberOrString::String(token.into()),
value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(Default::default())), value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(Default::default())),

View file

@ -178,7 +178,8 @@ pub enum Event {
pub struct LanguageServerStatus { pub struct LanguageServerStatus {
pub name: String, pub name: String,
pub pending_work: BTreeMap<String, LanguageServerProgress>, pub pending_work: BTreeMap<String, LanguageServerProgress>,
pub pending_diagnostic_updates: isize, pub has_pending_diagnostic_updates: bool,
progress_tokens: HashSet<String>,
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
@ -546,7 +547,8 @@ impl Project {
LanguageServerStatus { LanguageServerStatus {
name: server.name, name: server.name,
pending_work: Default::default(), pending_work: Default::default(),
pending_diagnostic_updates: 0, has_pending_diagnostic_updates: false,
progress_tokens: Default::default(),
}, },
) )
}) })
@ -2025,8 +2027,23 @@ impl Project {
// avoid stalling any language server like `gopls` which waits for a response // avoid stalling any language server like `gopls` which waits for a response
// to these requests when initializing. // to these requests when initializing.
language_server language_server
.on_request::<lsp::request::WorkDoneProgressCreate, _, _>(|_, _| async { .on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
Ok(()) let this = this.downgrade();
move |params, mut cx| async move {
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, _| {
if let Some(status) =
this.language_server_statuses.get_mut(&server_id)
{
if let lsp::NumberOrString::String(token) = params.token
{
status.progress_tokens.insert(token);
}
}
});
}
Ok(())
}
}) })
.detach(); .detach();
language_server language_server
@ -2079,7 +2096,8 @@ impl Project {
LanguageServerStatus { LanguageServerStatus {
name: language_server.name().to_string(), name: language_server.name().to_string(),
pending_work: Default::default(), pending_work: Default::default(),
pending_diagnostic_updates: 0, has_pending_diagnostic_updates: false,
progress_tokens: Default::default(),
}, },
); );
language_server language_server
@ -2291,19 +2309,22 @@ impl Project {
} else { } else {
return; return;
}; };
if !language_server_status.progress_tokens.contains(&token) {
return;
}
match progress { match progress {
lsp::WorkDoneProgress::Begin(report) => { lsp::WorkDoneProgress::Begin(report) => {
if Some(token.as_str()) == disk_based_diagnostics_progress_token { if Some(token.as_str()) == disk_based_diagnostics_progress_token {
language_server_status.pending_diagnostic_updates += 1; language_server_status.has_pending_diagnostic_updates = true;
if language_server_status.pending_diagnostic_updates == 1 { self.disk_based_diagnostics_started(server_id, cx);
self.disk_based_diagnostics_started(server_id, cx); self.broadcast_language_server_update(
self.broadcast_language_server_update( server_id,
server_id, proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( proto::LspDiskBasedDiagnosticsUpdating {},
proto::LspDiskBasedDiagnosticsUpdating {}, ),
), );
);
}
} else { } else {
self.on_lsp_work_start( self.on_lsp_work_start(
server_id, server_id,
@ -2350,17 +2371,17 @@ impl Project {
} }
} }
lsp::WorkDoneProgress::End(_) => { lsp::WorkDoneProgress::End(_) => {
language_server_status.progress_tokens.remove(&token);
if Some(token.as_str()) == disk_based_diagnostics_progress_token { if Some(token.as_str()) == disk_based_diagnostics_progress_token {
language_server_status.pending_diagnostic_updates -= 1; language_server_status.has_pending_diagnostic_updates = false;
if language_server_status.pending_diagnostic_updates == 0 { self.disk_based_diagnostics_finished(server_id, cx);
self.disk_based_diagnostics_finished(server_id, cx); self.broadcast_language_server_update(
self.broadcast_language_server_update( server_id,
server_id, proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( proto::LspDiskBasedDiagnosticsUpdated {},
proto::LspDiskBasedDiagnosticsUpdated {}, ),
), );
);
}
} else { } else {
self.on_lsp_work_end(server_id, token.clone(), cx); self.on_lsp_work_end(server_id, token.clone(), cx);
self.broadcast_language_server_update( self.broadcast_language_server_update(
@ -4216,7 +4237,7 @@ impl Project {
self.language_server_statuses self.language_server_statuses
.iter() .iter()
.filter_map(|(id, status)| { .filter_map(|(id, status)| {
if status.pending_diagnostic_updates > 0 { if status.has_pending_diagnostic_updates {
Some(*id) Some(*id)
} else { } else {
None None
@ -4616,7 +4637,8 @@ impl Project {
LanguageServerStatus { LanguageServerStatus {
name: server.name, name: server.name,
pending_work: Default::default(), pending_work: Default::default(),
pending_diagnostic_updates: 0, has_pending_diagnostic_updates: false,
progress_tokens: Default::default(),
}, },
); );
cx.notify(); cx.notify();
@ -6431,7 +6453,7 @@ mod tests {
let mut events = subscribe(&project, cx); let mut events = subscribe(&project, cx);
let mut fake_server = fake_servers.next().await.unwrap(); let fake_server = fake_servers.next().await.unwrap();
fake_server.start_progress(progress_token).await; fake_server.start_progress(progress_token).await;
assert_eq!( assert_eq!(
events.next().await.unwrap(), events.next().await.unwrap(),
@ -6440,10 +6462,6 @@ mod tests {
} }
); );
fake_server.start_progress(progress_token).await;
fake_server.end_progress(progress_token).await;
fake_server.start_progress(progress_token).await;
fake_server.notify::<lsp::notification::PublishDiagnostics>( fake_server.notify::<lsp::notification::PublishDiagnostics>(
lsp::PublishDiagnosticsParams { lsp::PublishDiagnosticsParams {
uri: Url::from_file_path("/dir/a.rs").unwrap(), uri: Url::from_file_path("/dir/a.rs").unwrap(),
@ -6464,8 +6482,7 @@ mod tests {
} }
); );
fake_server.end_progress(progress_token).await; fake_server.end_progress(progress_token);
fake_server.end_progress(progress_token).await;
assert_eq!( assert_eq!(
events.next().await.unwrap(), events.next().await.unwrap(),
Event::DiskBasedDiagnosticsFinished { Event::DiskBasedDiagnosticsFinished {
@ -6555,7 +6572,7 @@ mod tests {
.unwrap(); .unwrap();
// Simulate diagnostics starting to update. // Simulate diagnostics starting to update.
let mut fake_server = fake_servers.next().await.unwrap(); let fake_server = fake_servers.next().await.unwrap();
fake_server.start_progress(progress_token).await; fake_server.start_progress(progress_token).await;
// Restart the server before the diagnostics finish updating. // Restart the server before the diagnostics finish updating.
@ -6565,7 +6582,7 @@ mod tests {
let mut events = subscribe(&project, cx); let mut events = subscribe(&project, cx);
// Simulate the newly started server sending more diagnostics. // Simulate the newly started server sending more diagnostics.
let mut fake_server = fake_servers.next().await.unwrap(); let fake_server = fake_servers.next().await.unwrap();
fake_server.start_progress(progress_token).await; fake_server.start_progress(progress_token).await;
assert_eq!( assert_eq!(
events.next().await.unwrap(), events.next().await.unwrap(),
@ -6584,7 +6601,7 @@ mod tests {
// All diagnostics are considered done, despite the old server's diagnostic // All diagnostics are considered done, despite the old server's diagnostic
// task never completing. // task never completing.
fake_server.end_progress(progress_token).await; fake_server.end_progress(progress_token);
assert_eq!( assert_eq!(
events.next().await.unwrap(), events.next().await.unwrap(),
Event::DiskBasedDiagnosticsFinished { Event::DiskBasedDiagnosticsFinished {