Make Buffer::apply_ops infallible (#18089)

This PR makes the `Buffer::apply_ops` method infallible for
`text::Buffer` and `language::Buffer`.

We discovered that `text::Buffer::apply_ops` was only fallible due to
`apply_undo`, which didn't actually need to be fallible.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-09-19 13:14:15 -04:00 committed by GitHub
parent 8074fba76b
commit 1fc391f696
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 85 additions and 108 deletions

View file

@ -515,25 +515,25 @@ fn test_undo_redo() {
let entries = buffer.history.undo_stack.clone();
assert_eq!(entries.len(), 3);
buffer.undo_or_redo(entries[0].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[0].transaction.clone());
assert_eq!(buffer.text(), "1cdef234");
buffer.undo_or_redo(entries[0].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[0].transaction.clone());
assert_eq!(buffer.text(), "1abcdef234");
buffer.undo_or_redo(entries[1].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[1].transaction.clone());
assert_eq!(buffer.text(), "1abcdx234");
buffer.undo_or_redo(entries[2].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[2].transaction.clone());
assert_eq!(buffer.text(), "1abx234");
buffer.undo_or_redo(entries[1].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[1].transaction.clone());
assert_eq!(buffer.text(), "1abyzef234");
buffer.undo_or_redo(entries[2].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[2].transaction.clone());
assert_eq!(buffer.text(), "1abcdef234");
buffer.undo_or_redo(entries[2].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[2].transaction.clone());
assert_eq!(buffer.text(), "1abyzef234");
buffer.undo_or_redo(entries[0].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[0].transaction.clone());
assert_eq!(buffer.text(), "1yzef234");
buffer.undo_or_redo(entries[1].transaction.clone()).unwrap();
buffer.undo_or_redo(entries[1].transaction.clone());
assert_eq!(buffer.text(), "1234");
}
@ -692,12 +692,12 @@ fn test_concurrent_edits() {
let buf3_op = buffer3.edit([(5..6, "56")]);
assert_eq!(buffer3.text(), "abcde56");
buffer1.apply_op(buf2_op.clone()).unwrap();
buffer1.apply_op(buf3_op.clone()).unwrap();
buffer2.apply_op(buf1_op.clone()).unwrap();
buffer2.apply_op(buf3_op).unwrap();
buffer3.apply_op(buf1_op).unwrap();
buffer3.apply_op(buf2_op).unwrap();
buffer1.apply_op(buf2_op.clone());
buffer1.apply_op(buf3_op.clone());
buffer2.apply_op(buf1_op.clone());
buffer2.apply_op(buf3_op);
buffer3.apply_op(buf1_op);
buffer3.apply_op(buf2_op);
assert_eq!(buffer1.text(), "a12c34e56");
assert_eq!(buffer2.text(), "a12c34e56");
@ -756,7 +756,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
replica_id,
ops.len()
);
buffer.apply_ops(ops).unwrap();
buffer.apply_ops(ops);
}
}
_ => {}

View file

@ -38,7 +38,6 @@ pub use subscription::*;
pub use sum_tree::Bias;
use sum_tree::{FilterCursor, SumTree, TreeMap};
use undo_map::UndoMap;
use util::ResultExt;
#[cfg(any(test, feature = "test-support"))]
use util::RandomCharIter;
@ -927,23 +926,22 @@ impl Buffer {
self.snapshot.line_ending = line_ending;
}
pub fn apply_ops<I: IntoIterator<Item = Operation>>(&mut self, ops: I) -> Result<()> {
pub fn apply_ops<I: IntoIterator<Item = Operation>>(&mut self, ops: I) {
let mut deferred_ops = Vec::new();
for op in ops {
self.history.push(op.clone());
if self.can_apply_op(&op) {
self.apply_op(op)?;
self.apply_op(op);
} else {
self.deferred_replicas.insert(op.replica_id());
deferred_ops.push(op);
}
}
self.deferred_ops.insert(deferred_ops);
self.flush_deferred_ops()?;
Ok(())
self.flush_deferred_ops();
}
fn apply_op(&mut self, op: Operation) -> Result<()> {
fn apply_op(&mut self, op: Operation) {
match op {
Operation::Edit(edit) => {
if !self.version.observed(edit.timestamp) {
@ -960,7 +958,7 @@ impl Buffer {
}
Operation::Undo(undo) => {
if !self.version.observed(undo.timestamp) {
self.apply_undo(&undo)?;
self.apply_undo(&undo);
self.snapshot.version.observe(undo.timestamp);
self.lamport_clock.observe(undo.timestamp);
}
@ -974,7 +972,6 @@ impl Buffer {
true
}
});
Ok(())
}
fn apply_remote_edit(
@ -1217,7 +1214,7 @@ impl Buffer {
fragment_ids
}
fn apply_undo(&mut self, undo: &UndoOperation) -> Result<()> {
fn apply_undo(&mut self, undo: &UndoOperation) {
self.snapshot.undo_map.insert(undo);
let mut edits = Patch::default();
@ -1268,22 +1265,20 @@ impl Buffer {
self.snapshot.visible_text = visible_text;
self.snapshot.deleted_text = deleted_text;
self.subscriptions.publish_mut(&edits);
Ok(())
}
fn flush_deferred_ops(&mut self) -> Result<()> {
fn flush_deferred_ops(&mut self) {
self.deferred_replicas.clear();
let mut deferred_ops = Vec::new();
for op in self.deferred_ops.drain().iter().cloned() {
if self.can_apply_op(&op) {
self.apply_op(op)?;
self.apply_op(op);
} else {
self.deferred_replicas.insert(op.replica_id());
deferred_ops.push(op);
}
}
self.deferred_ops.insert(deferred_ops);
Ok(())
}
fn can_apply_op(&self, op: &Operation) -> bool {
@ -1352,7 +1347,7 @@ impl Buffer {
if let Some(entry) = self.history.pop_undo() {
let transaction = entry.transaction.clone();
let transaction_id = transaction.id;
let op = self.undo_or_redo(transaction).unwrap();
let op = self.undo_or_redo(transaction);
Some((transaction_id, op))
} else {
None
@ -1365,7 +1360,7 @@ impl Buffer {
.remove_from_undo(transaction_id)?
.transaction
.clone();
self.undo_or_redo(transaction).log_err()
Some(self.undo_or_redo(transaction))
}
pub fn undo_to_transaction(&mut self, transaction_id: TransactionId) -> Vec<Operation> {
@ -1378,7 +1373,7 @@ impl Buffer {
transactions
.into_iter()
.map(|transaction| self.undo_or_redo(transaction).unwrap())
.map(|transaction| self.undo_or_redo(transaction))
.collect()
}
@ -1394,7 +1389,7 @@ impl Buffer {
if let Some(entry) = self.history.pop_redo() {
let transaction = entry.transaction.clone();
let transaction_id = transaction.id;
let op = self.undo_or_redo(transaction).unwrap();
let op = self.undo_or_redo(transaction);
Some((transaction_id, op))
} else {
None
@ -1411,11 +1406,11 @@ impl Buffer {
transactions
.into_iter()
.map(|transaction| self.undo_or_redo(transaction).unwrap())
.map(|transaction| self.undo_or_redo(transaction))
.collect()
}
fn undo_or_redo(&mut self, transaction: Transaction) -> Result<Operation> {
fn undo_or_redo(&mut self, transaction: Transaction) -> Operation {
let mut counts = HashMap::default();
for edit_id in transaction.edit_ids {
counts.insert(edit_id, self.undo_map.undo_count(edit_id) + 1);
@ -1426,11 +1421,11 @@ impl Buffer {
version: self.version(),
counts,
};
self.apply_undo(&undo)?;
self.apply_undo(&undo);
self.snapshot.version.observe(undo.timestamp);
let operation = Operation::Undo(undo);
self.history.push(operation.clone());
Ok(operation)
operation
}
pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
@ -1762,7 +1757,7 @@ impl Buffer {
self.replica_id,
transaction
);
ops.push(self.undo_or_redo(transaction).unwrap());
ops.push(self.undo_or_redo(transaction));
}
}
ops