Replicate diagnostics to remote buffers

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2021-11-01 15:28:37 -07:00
parent 40c861c249
commit 0e62ddbb65
6 changed files with 197 additions and 51 deletions

View file

@ -9,7 +9,7 @@ pub use self::{
language::{BracketPair, Language, LanguageConfig, LanguageRegistry},
};
use anyhow::{anyhow, Result};
pub use buffer::{Buffer as TextBuffer, *};
pub use buffer::{Buffer as TextBuffer, Operation as _, *};
use clock::ReplicaId;
use futures::FutureExt as _;
use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task};
@ -99,6 +99,12 @@ struct LanguageServerSnapshot {
path: Arc<Path>,
}
#[derive(Clone)]
pub enum Operation {
Buffer(buffer::Operation),
UpdateDiagnostics(AnchorRangeMultimap<Diagnostic>),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Event {
Edited,
@ -256,7 +262,7 @@ impl Buffer {
let ops = message
.history
.into_iter()
.map(|op| Operation::Edit(proto::deserialize_edit_operation(op)));
.map(|op| buffer::Operation::Edit(proto::deserialize_edit_operation(op)));
buffer.apply_ops(ops)?;
for set in message.selections {
let set = proto::deserialize_selection_set(set);
@ -278,6 +284,7 @@ impl Buffer {
.selection_sets()
.map(|(_, set)| proto::serialize_selection_set(set))
.collect(),
diagnostics: Some(proto::serialize_diagnostics(&self.diagnostics)),
}
}
@ -761,6 +768,7 @@ impl Buffer {
}
self.diagnostics_update_count += 1;
self.send_operation(Operation::UpdateDiagnostics(self.diagnostics.clone()), cx);
cx.notify();
Ok(())
}
@ -1240,7 +1248,7 @@ impl Buffer {
}
self.end_transaction(None, cx).unwrap();
self.send_operation(Operation::Edit(edit), cx);
self.send_operation(Operation::Buffer(buffer::Operation::Edit(edit)), cx);
}
fn did_edit(
@ -1269,10 +1277,10 @@ impl Buffer {
cx: &mut ModelContext<Self>,
) -> SelectionSetId {
let operation = self.text.add_selection_set(selections);
if let Operation::UpdateSelections { set_id, .. } = &operation {
if let buffer::Operation::UpdateSelections { set_id, .. } = &operation {
let set_id = *set_id;
cx.notify();
self.send_operation(operation, cx);
self.send_operation(Operation::Buffer(operation), cx);
set_id
} else {
unreachable!()
@ -1287,7 +1295,7 @@ impl Buffer {
) -> Result<()> {
let operation = self.text.update_selection_set(set_id, selections)?;
cx.notify();
self.send_operation(operation, cx);
self.send_operation(Operation::Buffer(operation), cx);
Ok(())
}
@ -1297,7 +1305,7 @@ impl Buffer {
cx: &mut ModelContext<Self>,
) -> Result<()> {
let operation = self.text.set_active_selection_set(set_id)?;
self.send_operation(operation, cx);
self.send_operation(Operation::Buffer(operation), cx);
Ok(())
}
@ -1308,7 +1316,7 @@ impl Buffer {
) -> Result<()> {
let operation = self.text.remove_selection_set(set_id)?;
cx.notify();
self.send_operation(operation, cx);
self.send_operation(Operation::Buffer(operation), cx);
Ok(())
}
@ -1320,7 +1328,17 @@ impl Buffer {
self.pending_autoindent.take();
let was_dirty = self.is_dirty();
let old_version = self.version.clone();
self.text.apply_ops(ops)?;
let buffer_ops = ops
.into_iter()
.filter_map(|op| match op {
Operation::Buffer(op) => Some(op),
Operation::UpdateDiagnostics(diagnostics) => {
self.apply_diagnostic_update(diagnostics, cx);
None
}
})
.collect::<Vec<_>>();
self.text.apply_ops(buffer_ops)?;
self.did_edit(&old_version, was_dirty, cx);
// Notify independently of whether the buffer was edited as the operations could include a
// selection update.
@ -1328,6 +1346,15 @@ impl Buffer {
Ok(())
}
fn apply_diagnostic_update(
&mut self,
diagnostics: AnchorRangeMultimap<Diagnostic>,
cx: &mut ModelContext<Self>,
) {
self.diagnostics = diagnostics;
cx.notify();
}
#[cfg(not(test))]
pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
if let Some(file) = &self.file {
@ -1350,7 +1377,7 @@ impl Buffer {
let old_version = self.version.clone();
for operation in self.text.undo() {
self.send_operation(operation, cx);
self.send_operation(Operation::Buffer(operation), cx);
}
self.did_edit(&old_version, was_dirty, cx);
@ -1361,7 +1388,7 @@ impl Buffer {
let old_version = self.version.clone();
for operation in self.text.redo() {
self.send_operation(operation, cx);
self.send_operation(Operation::Buffer(operation), cx);
}
self.did_edit(&old_version, was_dirty, cx);