mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-04 06:34:26 +00:00
Compute minimal version_in_range
on edit and account for undo
This commit is contained in:
parent
c20935de91
commit
7b6fbe1d89
2 changed files with 27 additions and 24 deletions
|
@ -56,7 +56,7 @@ type HashMap<K, V> = std::collections::HashMap<K, V>;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
type HashSet<T> = std::collections::HashSet<T>;
|
type HashSet<T> = std::collections::HashSet<T>;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default, Debug)]
|
||||||
struct UndoMap(HashMap<time::Local, Vec<UndoOperation>>);
|
struct UndoMap(HashMap<time::Local, Vec<UndoOperation>>);
|
||||||
|
|
||||||
impl UndoMap {
|
impl UndoMap {
|
||||||
|
@ -177,6 +177,7 @@ struct Fragment {
|
||||||
insertion: Insertion,
|
insertion: Insertion,
|
||||||
text: Text,
|
text: Text,
|
||||||
deletions: HashSet<time::Local>,
|
deletions: HashSet<time::Local>,
|
||||||
|
undos: HashSet<time::Local>,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +273,7 @@ impl Buffer {
|
||||||
insertion: base_insertion.clone(),
|
insertion: base_insertion.clone(),
|
||||||
text: base_insertion.text.slice(0..0),
|
text: base_insertion.text.slice(0..0),
|
||||||
deletions: HashSet::default(),
|
deletions: HashSet::default(),
|
||||||
|
undos: HashSet::default(),
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -291,6 +293,7 @@ impl Buffer {
|
||||||
text: base_insertion.text.clone(),
|
text: base_insertion.text.clone(),
|
||||||
insertion: base_insertion,
|
insertion: base_insertion,
|
||||||
deletions: HashSet::default(),
|
deletions: HashSet::default(),
|
||||||
|
undos: HashSet::default(),
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -787,9 +790,11 @@ impl Buffer {
|
||||||
undo,
|
undo,
|
||||||
lamport_timestamp,
|
lamport_timestamp,
|
||||||
} => {
|
} => {
|
||||||
self.apply_undo(undo)?;
|
if !self.version.observed(undo.id) {
|
||||||
self.version.observe(undo.id);
|
self.apply_undo(undo)?;
|
||||||
self.lamport_clock.observe(lamport_timestamp);
|
self.version.observe(undo.id);
|
||||||
|
self.lamport_clock.observe(lamport_timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Operation::UpdateSelections {
|
Operation::UpdateSelections {
|
||||||
set_id,
|
set_id,
|
||||||
|
@ -877,7 +882,7 @@ impl Buffer {
|
||||||
new_fragments.push(fragment);
|
new_fragments.push(fragment);
|
||||||
}
|
}
|
||||||
if let Some(mut fragment) = within_range {
|
if let Some(mut fragment) = within_range {
|
||||||
if version_in_range.observed(fragment.insertion.id) {
|
if fragment.was_visible(&version_in_range, &self.undo_map) {
|
||||||
fragment.deletions.insert(local_timestamp);
|
fragment.deletions.insert(local_timestamp);
|
||||||
fragment.visible = false;
|
fragment.visible = false;
|
||||||
}
|
}
|
||||||
|
@ -897,7 +902,8 @@ impl Buffer {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if fragment.id < end_fragment_id && version_in_range.observed(fragment.insertion.id)
|
if fragment.id < end_fragment_id
|
||||||
|
&& fragment.was_visible(&version_in_range, &self.undo_map)
|
||||||
{
|
{
|
||||||
fragment.deletions.insert(local_timestamp);
|
fragment.deletions.insert(local_timestamp);
|
||||||
fragment.visible = false;
|
fragment.visible = false;
|
||||||
|
@ -955,17 +961,6 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_undo(&mut self, undo: UndoOperation) -> Result<()> {
|
fn apply_undo(&mut self, undo: UndoOperation) -> Result<()> {
|
||||||
// let mut new_fragments = SumTree::new();
|
|
||||||
|
|
||||||
// self.undos.insert(undo);
|
|
||||||
// let edit = &self.edit_ops[&undo.edit_id];
|
|
||||||
// let start_fragment_id = self.resolve_fragment_id(edit.start_id, edit.start_offset)?;
|
|
||||||
// let end_fragment_id = self.resolve_fragment_id(edit.end_id, edit.end_offset)?;
|
|
||||||
// let mut cursor = self.fragments.cursor::<FragmentIdRef, ()>();
|
|
||||||
|
|
||||||
// for fragment in cursor {}
|
|
||||||
// self.fragments = new_fragments;
|
|
||||||
|
|
||||||
let mut new_fragments;
|
let mut new_fragments;
|
||||||
|
|
||||||
self.undo_map.insert(undo);
|
self.undo_map.insert(undo);
|
||||||
|
@ -984,6 +979,7 @@ impl Buffer {
|
||||||
loop {
|
loop {
|
||||||
let mut fragment = cursor.item().unwrap().clone();
|
let mut fragment = cursor.item().unwrap().clone();
|
||||||
fragment.visible = fragment.is_visible(&self.undo_map);
|
fragment.visible = fragment.is_visible(&self.undo_map);
|
||||||
|
fragment.undos.insert(undo.id);
|
||||||
new_fragments.push(fragment);
|
new_fragments.push(fragment);
|
||||||
cursor.next();
|
cursor.next();
|
||||||
if let Some(split_id) = insertion_splits.next() {
|
if let Some(split_id) = insertion_splits.next() {
|
||||||
|
@ -1004,6 +1000,7 @@ impl Buffer {
|
||||||
|| fragment.insertion.id == undo.edit_id
|
|| fragment.insertion.id == undo.edit_id
|
||||||
{
|
{
|
||||||
fragment.visible = fragment.is_visible(&self.undo_map);
|
fragment.visible = fragment.is_visible(&self.undo_map);
|
||||||
|
fragment.undos.insert(undo.id);
|
||||||
}
|
}
|
||||||
new_fragments.push(fragment);
|
new_fragments.push(fragment);
|
||||||
cursor.next();
|
cursor.next();
|
||||||
|
@ -1110,6 +1107,7 @@ impl Buffer {
|
||||||
|
|
||||||
while cur_range.is_some() && cursor.item().is_some() {
|
while cur_range.is_some() && cursor.item().is_some() {
|
||||||
let mut fragment = cursor.item().unwrap().clone();
|
let mut fragment = cursor.item().unwrap().clone();
|
||||||
|
let fragment_summary = cursor.item_summary().unwrap();
|
||||||
let mut fragment_start = *cursor.start();
|
let mut fragment_start = *cursor.start();
|
||||||
let mut fragment_end = fragment_start + fragment.visible_len();
|
let mut fragment_end = fragment_start + fragment.visible_len();
|
||||||
|
|
||||||
|
@ -1169,6 +1167,7 @@ impl Buffer {
|
||||||
prefix.set_end_offset(prefix.start_offset() + (range.end - fragment_start));
|
prefix.set_end_offset(prefix.start_offset() + (range.end - fragment_start));
|
||||||
prefix.id =
|
prefix.id =
|
||||||
FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
|
FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
|
||||||
|
version_in_range.observe_all(&fragment_summary.max_version);
|
||||||
if fragment.visible {
|
if fragment.visible {
|
||||||
prefix.deletions.insert(local_timestamp);
|
prefix.deletions.insert(local_timestamp);
|
||||||
prefix.visible = false;
|
prefix.visible = false;
|
||||||
|
@ -1182,10 +1181,9 @@ impl Buffer {
|
||||||
fragment_start = range.end;
|
fragment_start = range.end;
|
||||||
end_id = Some(fragment.insertion.id);
|
end_id = Some(fragment.insertion.id);
|
||||||
end_offset = Some(fragment.start_offset());
|
end_offset = Some(fragment.start_offset());
|
||||||
version_in_range.observe(fragment.insertion.id);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
version_in_range.observe(fragment.insertion.id);
|
version_in_range.observe_all(&fragment_summary.max_version);
|
||||||
if fragment.visible {
|
if fragment.visible {
|
||||||
fragment.deletions.insert(local_timestamp);
|
fragment.deletions.insert(local_timestamp);
|
||||||
fragment.visible = false;
|
fragment.visible = false;
|
||||||
|
@ -1238,15 +1236,16 @@ impl Buffer {
|
||||||
cursor.next();
|
cursor.next();
|
||||||
if let Some(range) = cur_range.clone() {
|
if let Some(range) = cur_range.clone() {
|
||||||
while let Some(fragment) = cursor.item() {
|
while let Some(fragment) = cursor.item() {
|
||||||
|
let fragment_summary = cursor.item_summary().unwrap();
|
||||||
fragment_start = *cursor.start();
|
fragment_start = *cursor.start();
|
||||||
fragment_end = fragment_start + fragment.visible_len();
|
fragment_end = fragment_start + fragment.visible_len();
|
||||||
if range.start < fragment_start && range.end >= fragment_end {
|
if range.start < fragment_start && range.end >= fragment_end {
|
||||||
let mut new_fragment = fragment.clone();
|
let mut new_fragment = fragment.clone();
|
||||||
|
version_in_range.observe_all(&fragment_summary.max_version);
|
||||||
if new_fragment.visible {
|
if new_fragment.visible {
|
||||||
new_fragment.deletions.insert(local_timestamp);
|
new_fragment.deletions.insert(local_timestamp);
|
||||||
new_fragment.visible = false;
|
new_fragment.visible = false;
|
||||||
}
|
}
|
||||||
version_in_range.observe(new_fragment.insertion.id);
|
|
||||||
new_fragments.push(new_fragment);
|
new_fragments.push(new_fragment);
|
||||||
cursor.next();
|
cursor.next();
|
||||||
|
|
||||||
|
@ -1927,6 +1926,7 @@ impl Fragment {
|
||||||
text: insertion.text.clone(),
|
text: insertion.text.clone(),
|
||||||
insertion,
|
insertion,
|
||||||
deletions: HashSet::default(),
|
deletions: HashSet::default(),
|
||||||
|
undos: HashSet::default(),
|
||||||
visible: true,
|
visible: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1989,6 +1989,9 @@ impl sum_tree::Item for Fragment {
|
||||||
for deletion in &self.deletions {
|
for deletion in &self.deletions {
|
||||||
max_version.observe(*deletion);
|
max_version.observe(*deletion);
|
||||||
}
|
}
|
||||||
|
for undo in &self.undos {
|
||||||
|
max_version.observe(*undo);
|
||||||
|
}
|
||||||
|
|
||||||
if self.visible {
|
if self.visible {
|
||||||
FragmentSummary {
|
FragmentSummary {
|
||||||
|
@ -2845,9 +2848,9 @@ mod tests {
|
||||||
fn test_random_concurrent_edits() {
|
fn test_random_concurrent_edits() {
|
||||||
use crate::test::Network;
|
use crate::test::Network;
|
||||||
|
|
||||||
const PEERS: usize = 2;
|
const PEERS: usize = 5;
|
||||||
|
|
||||||
for seed in 0..1000 {
|
for seed in 0..100 {
|
||||||
println!("{:?}", seed);
|
println!("{:?}", seed);
|
||||||
let mut rng = &mut StdRng::seed_from_u64(seed);
|
let mut rng = &mut StdRng::seed_from_u64(seed);
|
||||||
|
|
||||||
|
@ -2865,7 +2868,7 @@ mod tests {
|
||||||
network.add_peer(i as u16);
|
network.add_peer(i as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mutation_count = 3;
|
let mut mutation_count = 10;
|
||||||
loop {
|
loop {
|
||||||
let replica_index = rng.gen_range(0..PEERS);
|
let replica_index = rng.gen_range(0..PEERS);
|
||||||
let replica_id = replica_ids[replica_index];
|
let replica_id = replica_ids[replica_index];
|
||||||
|
|
|
@ -77,7 +77,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_summary(&self) -> Option<&'a T::Summary> {
|
pub fn item_summary(&self) -> Option<&'a T::Summary> {
|
||||||
assert!(self.did_seek, "Must seek before calling this method");
|
assert!(self.did_seek, "Must seek before calling this method");
|
||||||
if let Some(entry) = self.stack.last() {
|
if let Some(entry) = self.stack.last() {
|
||||||
match *entry.tree.0 {
|
match *entry.tree.0 {
|
||||||
|
|
Loading…
Reference in a new issue