Fix maintenance of MultiBuffer's buffer states

This commit is contained in:
Max Brunsfeld 2021-12-21 13:07:43 -08:00
parent 13ecd16685
commit 8492c6e7ac

View file

@ -34,7 +34,7 @@ pub type ExcerptId = Locator;
pub struct MultiBuffer { pub struct MultiBuffer {
snapshot: RefCell<MultiBufferSnapshot>, snapshot: RefCell<MultiBufferSnapshot>,
buffers: HashMap<usize, BufferState>, buffers: RefCell<HashMap<usize, BufferState>>,
subscriptions: Topic, subscriptions: Topic,
singleton: bool, singleton: bool,
replica_id: ReplicaId, replica_id: ReplicaId,
@ -245,9 +245,17 @@ impl MultiBuffer {
self.snapshot.borrow() self.snapshot.borrow()
} }
pub fn as_singleton(&self) -> Option<&ModelHandle<Buffer>> { pub fn as_singleton(&self) -> Option<ModelHandle<Buffer>> {
if self.singleton { if self.singleton {
return Some(&self.buffers.values().next().unwrap().buffer); return Some(
self.buffers
.borrow()
.values()
.next()
.unwrap()
.buffer
.clone(),
);
} else { } else {
None None
} }
@ -364,7 +372,9 @@ impl MultiBuffer {
let new_text = new_text.into(); let new_text = new_text.into();
for (buffer_id, mut edits) in buffer_edits { for (buffer_id, mut edits) in buffer_edits {
edits.sort_unstable_by_key(|(range, _)| range.start); edits.sort_unstable_by_key(|(range, _)| range.start);
self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| { self.buffers.borrow()[&buffer_id]
.buffer
.update(cx, |buffer, cx| {
let mut edits = edits.into_iter().peekable(); let mut edits = edits.into_iter().peekable();
let mut insertions = Vec::new(); let mut insertions = Vec::new();
let mut deletions = Vec::new(); let mut deletions = Vec::new();
@ -414,7 +424,7 @@ impl MultiBuffer {
return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now)); return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
} }
for BufferState { buffer, .. } in self.buffers.values() { for BufferState { buffer, .. } in self.buffers.borrow().values() {
buffer.update(cx, |buffer, _| buffer.start_transaction_at(now)); buffer.update(cx, |buffer, _| buffer.start_transaction_at(now));
} }
self.history.start_transaction(now) self.history.start_transaction(now)
@ -434,7 +444,7 @@ impl MultiBuffer {
} }
let mut buffer_transactions = HashSet::default(); let mut buffer_transactions = HashSet::default();
for BufferState { buffer, .. } in self.buffers.values() { for BufferState { buffer, .. } in self.buffers.borrow().values() {
if let Some(transaction_id) = if let Some(transaction_id) =
buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx)) buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
{ {
@ -490,7 +500,9 @@ impl MultiBuffer {
} }
for (buffer_id, mut selections) in selections_by_buffer { for (buffer_id, mut selections) in selections_by_buffer {
self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| { self.buffers.borrow()[&buffer_id]
.buffer
.update(cx, |buffer, cx| {
selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap()); selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
let mut selections = selections.into_iter().peekable(); let mut selections = selections.into_iter().peekable();
let merged_selections = Arc::from_iter(iter::from_fn(|| { let merged_selections = Arc::from_iter(iter::from_fn(|| {
@ -523,7 +535,7 @@ impl MultiBuffer {
} }
pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) { pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
for buffer in self.buffers.values() { for buffer in self.buffers.borrow().values() {
buffer buffer
.buffer .buffer
.update(cx, |buffer, cx| buffer.remove_active_selections(cx)); .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
@ -538,7 +550,7 @@ impl MultiBuffer {
while let Some(transaction) = self.history.pop_undo() { while let Some(transaction) = self.history.pop_undo() {
let mut undone = false; let mut undone = false;
for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions { for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
if let Some(BufferState { buffer, .. }) = self.buffers.get(&buffer_id) { if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
undone |= buffer.update(cx, |buf, cx| { undone |= buffer.update(cx, |buf, cx| {
buf.undo_transaction(*buffer_transaction_id, cx) buf.undo_transaction(*buffer_transaction_id, cx)
}); });
@ -561,7 +573,7 @@ impl MultiBuffer {
while let Some(transaction) = self.history.pop_redo() { while let Some(transaction) = self.history.pop_redo() {
let mut redone = false; let mut redone = false;
for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions { for (buffer_id, buffer_transaction_id) in &transaction.buffer_transactions {
if let Some(BufferState { buffer, .. }) = self.buffers.get(&buffer_id) { if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) {
redone |= buffer.update(cx, |buf, cx| { redone |= buffer.update(cx, |buf, cx| {
buf.redo_transaction(*buffer_transaction_id, cx) buf.redo_transaction(*buffer_transaction_id, cx)
}); });
@ -613,6 +625,7 @@ impl MultiBuffer {
let excerpt = Excerpt::new(id.clone(), buffer.id(), buffer_snapshot, range, false); let excerpt = Excerpt::new(id.clone(), buffer.id(), buffer_snapshot, range, false);
snapshot.excerpts.push(excerpt, &()); snapshot.excerpts.push(excerpt, &());
self.buffers self.buffers
.borrow_mut()
.entry(props.buffer.id()) .entry(props.buffer.id())
.or_insert_with(|| BufferState { .or_insert_with(|| BufferState {
buffer, buffer,
@ -644,7 +657,7 @@ impl MultiBuffer {
pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Result<Task<Result<()>>> { pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Result<Task<Result<()>>> {
let mut save_tasks = Vec::new(); let mut save_tasks = Vec::new();
for BufferState { buffer, .. } in self.buffers.values() { for BufferState { buffer, .. } in self.buffers.borrow().values() {
save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx))?); save_tasks.push(buffer.update(cx, |buffer, cx| buffer.save(cx))?);
} }
@ -658,6 +671,7 @@ impl MultiBuffer {
pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> { pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
self.buffers self.buffers
.borrow()
.values() .values()
.next() .next()
.and_then(|state| state.buffer.read(cx).language()) .and_then(|state| state.buffer.read(cx).language())
@ -679,18 +693,26 @@ impl MultiBuffer {
let mut diagnostics_updated = false; let mut diagnostics_updated = false;
let mut is_dirty = false; let mut is_dirty = false;
let mut has_conflict = false; let mut has_conflict = false;
for buffer_state in self.buffers.values() { let mut buffers = self.buffers.borrow_mut();
for buffer_state in buffers.values_mut() {
let buffer = buffer_state.buffer.read(cx); let buffer = buffer_state.buffer.read(cx);
let buffer_edited = buffer.version().gt(&buffer_state.last_version); let version = buffer.version();
let buffer_reparsed = buffer.parse_count() > buffer_state.last_parse_count; let parse_count = buffer.parse_count();
let diagnostics_update_count = buffer.diagnostics_update_count();
let buffer_edited = version.gt(&buffer_state.last_version);
let buffer_reparsed = parse_count > buffer_state.last_parse_count;
let buffer_diagnostics_updated = let buffer_diagnostics_updated =
buffer.diagnostics_update_count() > buffer_state.last_diagnostics_update_count; diagnostics_update_count > buffer_state.last_diagnostics_update_count;
if buffer_edited || buffer_reparsed || buffer_diagnostics_updated { if buffer_edited || buffer_reparsed || buffer_diagnostics_updated {
buffer_state.last_version = version;
buffer_state.last_parse_count = parse_count;
buffer_state.last_diagnostics_update_count = diagnostics_update_count;
excerpts_to_edit.extend( excerpts_to_edit.extend(
buffer_state buffer_state
.excerpts .excerpts
.iter() .iter()
.map(|excerpt_id| (excerpt_id, buffer_state, buffer_edited)), .map(|excerpt_id| (excerpt_id, buffer_state.buffer.clone(), buffer_edited)),
); );
} }
@ -714,10 +736,11 @@ impl MultiBuffer {
let mut new_excerpts = SumTree::new(); let mut new_excerpts = SumTree::new();
let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>(); let mut cursor = snapshot.excerpts.cursor::<(Option<&ExcerptId>, usize)>();
for (id, buffer_state, buffer_edited) in excerpts_to_edit { for (id, buffer, buffer_edited) in excerpts_to_edit {
new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &()); new_excerpts.push_tree(cursor.slice(&Some(id), Bias::Left, &()), &());
let old_excerpt = cursor.item().unwrap(); let old_excerpt = cursor.item().unwrap();
let buffer = buffer_state.buffer.read(cx); let buffer_id = buffer.id();
let buffer = buffer.read(cx);
let mut new_excerpt; let mut new_excerpt;
if buffer_edited { if buffer_edited {
@ -740,7 +763,7 @@ impl MultiBuffer {
new_excerpt = Excerpt::new( new_excerpt = Excerpt::new(
id.clone(), id.clone(),
buffer_state.buffer.id(), buffer_id,
buffer.snapshot(), buffer.snapshot(),
old_excerpt.range.clone(), old_excerpt.range.clone(),
old_excerpt.has_trailing_newline, old_excerpt.has_trailing_newline,