Send language server updates via the same task that sends buffer operations
Co-authored-by: Julia Risley <julia@zed.dev>
This commit is contained in:
parent
ce34bf62fe
commit
a8ddba55d8
1 changed files with 137 additions and 88 deletions
|
@ -142,6 +142,10 @@ enum BufferMessage {
|
||||||
buffer_id: u64,
|
buffer_id: u64,
|
||||||
operation: proto::Operation,
|
operation: proto::Operation,
|
||||||
},
|
},
|
||||||
|
LanguageServerUpdate {
|
||||||
|
language_server_id: LanguageServerId,
|
||||||
|
message: proto::update_language_server::Variant,
|
||||||
|
},
|
||||||
Resync,
|
Resync,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1791,9 +1795,35 @@ impl Project {
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
const MAX_BATCH_SIZE: usize = 128;
|
const MAX_BATCH_SIZE: usize = 128;
|
||||||
|
|
||||||
let mut needs_resync_with_host = false;
|
|
||||||
let mut operations_by_buffer_id = HashMap::default();
|
let mut operations_by_buffer_id = HashMap::default();
|
||||||
|
async fn flush_operations(
|
||||||
|
this: &ModelHandle<Project>,
|
||||||
|
operations_by_buffer_id: &mut HashMap<u64, Vec<proto::Operation>>,
|
||||||
|
needs_resync_with_host: &mut bool,
|
||||||
|
is_local: bool,
|
||||||
|
cx: &AsyncAppContext,
|
||||||
|
) {
|
||||||
|
for (buffer_id, operations) in operations_by_buffer_id.drain() {
|
||||||
|
let request = this.read_with(cx, |this, _| {
|
||||||
|
let project_id = this.remote_id()?;
|
||||||
|
Some(this.client.request(proto::UpdateBuffer {
|
||||||
|
buffer_id,
|
||||||
|
project_id,
|
||||||
|
operations,
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
if let Some(request) = request {
|
||||||
|
if request.await.is_err() && !is_local {
|
||||||
|
*needs_resync_with_host = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut needs_resync_with_host = false;
|
||||||
let mut changes = rx.ready_chunks(MAX_BATCH_SIZE);
|
let mut changes = rx.ready_chunks(MAX_BATCH_SIZE);
|
||||||
|
|
||||||
while let Some(changes) = changes.next().await {
|
while let Some(changes) = changes.next().await {
|
||||||
let this = this.upgrade(&mut cx)?;
|
let this = this.upgrade(&mut cx)?;
|
||||||
let is_local = this.read_with(&cx, |this, _| this.is_local());
|
let is_local = this.read_with(&cx, |this, _| this.is_local());
|
||||||
|
@ -1813,6 +1843,7 @@ impl Project {
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(operation);
|
.push(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferMessage::Resync => {
|
BufferMessage::Resync => {
|
||||||
operations_by_buffer_id.clear();
|
operations_by_buffer_id.clear();
|
||||||
if this
|
if this
|
||||||
|
@ -1823,25 +1854,43 @@ impl Project {
|
||||||
needs_resync_with_host = false;
|
needs_resync_with_host = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (buffer_id, operations) in operations_by_buffer_id.drain() {
|
BufferMessage::LanguageServerUpdate {
|
||||||
let request = this.read_with(&cx, |this, _| {
|
language_server_id,
|
||||||
let project_id = this.remote_id()?;
|
message,
|
||||||
Some(this.client.request(proto::UpdateBuffer {
|
} => {
|
||||||
buffer_id,
|
flush_operations(
|
||||||
project_id,
|
&this,
|
||||||
operations,
|
&mut operations_by_buffer_id,
|
||||||
}))
|
&mut needs_resync_with_host,
|
||||||
});
|
is_local,
|
||||||
if let Some(request) = request {
|
&cx,
|
||||||
if request.await.is_err() && !is_local {
|
)
|
||||||
needs_resync_with_host = true;
|
.await;
|
||||||
break;
|
|
||||||
|
this.read_with(&cx, |this, _| {
|
||||||
|
if let Some(project_id) = this.remote_id() {
|
||||||
|
this.client
|
||||||
|
.send(proto::UpdateLanguageServer {
|
||||||
|
project_id,
|
||||||
|
language_server_id: language_server_id.0 as u64,
|
||||||
|
variant: Some(message),
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_operations(
|
||||||
|
&this,
|
||||||
|
&mut operations_by_buffer_id,
|
||||||
|
&mut needs_resync_with_host,
|
||||||
|
is_local,
|
||||||
|
&cx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -1962,19 +2011,24 @@ impl Project {
|
||||||
Duration::from_secs(1);
|
Duration::from_secs(1);
|
||||||
|
|
||||||
let task = cx.spawn_weak(|this, mut cx| async move {
|
let task = cx.spawn_weak(|this, mut cx| async move {
|
||||||
cx.background().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await;
|
cx.background().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await;
|
||||||
if let Some(this) = this.upgrade(&cx) {
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
this.update(&mut cx, |this, cx | {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.disk_based_diagnostics_finished(language_server_id, cx);
|
this.disk_based_diagnostics_finished(
|
||||||
this.broadcast_language_server_update(
|
language_server_id,
|
||||||
language_server_id,
|
cx,
|
||||||
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
|
);
|
||||||
proto::LspDiskBasedDiagnosticsUpdated {},
|
this.buffer_changes_tx
|
||||||
),
|
.unbounded_send(
|
||||||
);
|
BufferMessage::LanguageServerUpdate {
|
||||||
});
|
language_server_id,
|
||||||
}
|
message:proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(Default::default())
|
||||||
});
|
},
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
*simulate_disk_based_diagnostics_completion = Some(task);
|
*simulate_disk_based_diagnostics_completion = Some(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2609,7 +2663,7 @@ impl Project {
|
||||||
fn on_lsp_progress(
|
fn on_lsp_progress(
|
||||||
&mut self,
|
&mut self,
|
||||||
progress: lsp::ProgressParams,
|
progress: lsp::ProgressParams,
|
||||||
server_id: LanguageServerId,
|
language_server_id: LanguageServerId,
|
||||||
disk_based_diagnostics_progress_token: Option<String>,
|
disk_based_diagnostics_progress_token: Option<String>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
|
@ -2622,7 +2676,7 @@ impl Project {
|
||||||
};
|
};
|
||||||
let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
|
let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
|
||||||
let language_server_status =
|
let language_server_status =
|
||||||
if let Some(status) = self.language_server_statuses.get_mut(&server_id) {
|
if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
|
||||||
status
|
status
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -2642,16 +2696,16 @@ impl Project {
|
||||||
lsp::WorkDoneProgress::Begin(report) => {
|
lsp::WorkDoneProgress::Begin(report) => {
|
||||||
if is_disk_based_diagnostics_progress {
|
if is_disk_based_diagnostics_progress {
|
||||||
language_server_status.has_pending_diagnostic_updates = true;
|
language_server_status.has_pending_diagnostic_updates = true;
|
||||||
self.disk_based_diagnostics_started(server_id, cx);
|
self.disk_based_diagnostics_started(language_server_id, cx);
|
||||||
self.broadcast_language_server_update(
|
self.buffer_changes_tx
|
||||||
server_id,
|
.unbounded_send(BufferMessage::LanguageServerUpdate {
|
||||||
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
|
language_server_id,
|
||||||
proto::LspDiskBasedDiagnosticsUpdating {},
|
message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(Default::default())
|
||||||
),
|
})
|
||||||
);
|
.ok();
|
||||||
} else {
|
} else {
|
||||||
self.on_lsp_work_start(
|
self.on_lsp_work_start(
|
||||||
server_id,
|
language_server_id,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
LanguageServerProgress {
|
LanguageServerProgress {
|
||||||
message: report.message.clone(),
|
message: report.message.clone(),
|
||||||
|
@ -2660,20 +2714,24 @@ impl Project {
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
self.broadcast_language_server_update(
|
self.buffer_changes_tx
|
||||||
server_id,
|
.unbounded_send(BufferMessage::LanguageServerUpdate {
|
||||||
proto::update_language_server::Variant::WorkStart(proto::LspWorkStart {
|
language_server_id,
|
||||||
token,
|
message: proto::update_language_server::Variant::WorkStart(
|
||||||
message: report.message,
|
proto::LspWorkStart {
|
||||||
percentage: report.percentage.map(|p| p as u32),
|
token,
|
||||||
}),
|
message: report.message,
|
||||||
);
|
percentage: report.percentage.map(|p| p as u32),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lsp::WorkDoneProgress::Report(report) => {
|
lsp::WorkDoneProgress::Report(report) => {
|
||||||
if !is_disk_based_diagnostics_progress {
|
if !is_disk_based_diagnostics_progress {
|
||||||
self.on_lsp_work_progress(
|
self.on_lsp_work_progress(
|
||||||
server_id,
|
language_server_id,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
LanguageServerProgress {
|
LanguageServerProgress {
|
||||||
message: report.message.clone(),
|
message: report.message.clone(),
|
||||||
|
@ -2682,16 +2740,18 @@ impl Project {
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
self.broadcast_language_server_update(
|
self.buffer_changes_tx
|
||||||
server_id,
|
.unbounded_send(BufferMessage::LanguageServerUpdate {
|
||||||
proto::update_language_server::Variant::WorkProgress(
|
language_server_id,
|
||||||
proto::LspWorkProgress {
|
message: proto::update_language_server::Variant::WorkProgress(
|
||||||
token,
|
proto::LspWorkProgress {
|
||||||
message: report.message,
|
token,
|
||||||
percentage: report.percentage.map(|p| p as u32),
|
message: report.message,
|
||||||
},
|
percentage: report.percentage.map(|p| p as u32),
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lsp::WorkDoneProgress::End(_) => {
|
lsp::WorkDoneProgress::End(_) => {
|
||||||
|
@ -2699,21 +2759,26 @@ impl Project {
|
||||||
|
|
||||||
if is_disk_based_diagnostics_progress {
|
if is_disk_based_diagnostics_progress {
|
||||||
language_server_status.has_pending_diagnostic_updates = false;
|
language_server_status.has_pending_diagnostic_updates = false;
|
||||||
self.disk_based_diagnostics_finished(server_id, cx);
|
self.disk_based_diagnostics_finished(language_server_id, cx);
|
||||||
self.broadcast_language_server_update(
|
self.buffer_changes_tx
|
||||||
server_id,
|
.unbounded_send(BufferMessage::LanguageServerUpdate {
|
||||||
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
|
language_server_id,
|
||||||
proto::LspDiskBasedDiagnosticsUpdated {},
|
message:
|
||||||
),
|
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
|
||||||
);
|
Default::default(),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
} else {
|
} else {
|
||||||
self.on_lsp_work_end(server_id, token.clone(), cx);
|
self.on_lsp_work_end(language_server_id, token.clone(), cx);
|
||||||
self.broadcast_language_server_update(
|
self.buffer_changes_tx
|
||||||
server_id,
|
.unbounded_send(BufferMessage::LanguageServerUpdate {
|
||||||
proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd {
|
language_server_id,
|
||||||
token,
|
message: proto::update_language_server::Variant::WorkEnd(
|
||||||
}),
|
proto::LspWorkEnd { token },
|
||||||
);
|
),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2822,22 +2887,6 @@ impl Project {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn broadcast_language_server_update(
|
|
||||||
&self,
|
|
||||||
language_server_id: LanguageServerId,
|
|
||||||
event: proto::update_language_server::Variant,
|
|
||||||
) {
|
|
||||||
if let Some(project_id) = self.remote_id() {
|
|
||||||
self.client
|
|
||||||
.send(proto::UpdateLanguageServer {
|
|
||||||
project_id,
|
|
||||||
language_server_id: language_server_id.0 as u64,
|
|
||||||
variant: Some(event),
|
|
||||||
})
|
|
||||||
.log_err();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn language_server_statuses(
|
pub fn language_server_statuses(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = &LanguageServerStatus> {
|
) -> impl DoubleEndedIterator<Item = &LanguageServerStatus> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue