1mod anchor;
2mod point;
3pub mod rope;
4mod selection;
5
6pub use anchor::*;
7use parking_lot::Mutex;
8pub use point::*;
9pub use rope::{Chunks, Rope, TextSummary};
10use seahash::SeaHasher;
11pub use selection::*;
12use similar::{ChangeTag, TextDiff};
13use tree_sitter::{InputEdit, Parser, QueryCursor};
14
15use crate::{
16 editor::Bias,
17 language::{Language, Tree},
18 operation_queue::{self, OperationQueue},
19 settings::{StyleId, ThemeMap},
20 sum_tree::{self, FilterCursor, SeekBias, SumTree},
21 time::{self, ReplicaId},
22 worktree::FileHandle,
23};
24use anyhow::{anyhow, Result};
25use gpui::{AppContext, Entity, ModelContext, Task};
26use lazy_static::lazy_static;
27use std::{
28 cell::RefCell,
29 cmp,
30 hash::BuildHasher,
31 iter::{self, Iterator},
32 mem,
33 ops::Range,
34 str,
35 sync::Arc,
36 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
37};
38
39const UNDO_GROUP_INTERVAL: Duration = Duration::from_millis(300);
40
41#[derive(Clone, Default)]
42struct DeterministicState;
43
44impl BuildHasher for DeterministicState {
45 type Hasher = SeaHasher;
46
47 fn build_hasher(&self) -> Self::Hasher {
48 SeaHasher::new()
49 }
50}
51
52#[cfg(test)]
53type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
54
55#[cfg(test)]
56type HashSet<T> = std::collections::HashSet<T, DeterministicState>;
57
58#[cfg(not(test))]
59type HashMap<K, V> = std::collections::HashMap<K, V>;
60
61#[cfg(not(test))]
62type HashSet<T> = std::collections::HashSet<T>;
63
64thread_local! {
65 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
66}
67
68lazy_static! {
69 static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
70}
71
72pub struct Buffer {
73 fragments: SumTree<Fragment>,
74 visible_text: Rope,
75 deleted_text: Rope,
76 insertion_splits: HashMap<time::Local, SumTree<InsertionSplit>>,
77 pub version: time::Global,
78 saved_version: time::Global,
79 saved_mtime: SystemTime,
80 last_edit: time::Local,
81 undo_map: UndoMap,
82 history: History,
83 file: Option<FileHandle>,
84 language: Option<Arc<Language>>,
85 syntax_tree: Mutex<Option<SyntaxTree>>,
86 is_parsing: bool,
87 selections: HashMap<SelectionSetId, Arc<[Selection]>>,
88 pub selections_last_update: SelectionsVersion,
89 deferred_ops: OperationQueue<Operation>,
90 deferred_replicas: HashSet<ReplicaId>,
91 replica_id: ReplicaId,
92 local_clock: time::Local,
93 lamport_clock: time::Lamport,
94}
95
96#[derive(Clone)]
97struct SyntaxTree {
98 tree: Tree,
99 parsed: bool,
100 version: time::Global,
101}
102
103#[derive(Clone)]
104struct Transaction {
105 start: time::Global,
106 buffer_was_dirty: bool,
107 edits: Vec<time::Local>,
108 selections_before: Option<(SelectionSetId, Arc<[Selection]>)>,
109 selections_after: Option<(SelectionSetId, Arc<[Selection]>)>,
110 first_edit_at: Instant,
111 last_edit_at: Instant,
112}
113
114#[derive(Clone)]
115pub struct History {
116 // TODO: Turn this into a String or Rope, maybe.
117 pub base_text: Arc<str>,
118 ops: HashMap<time::Local, EditOperation>,
119 undo_stack: Vec<Transaction>,
120 redo_stack: Vec<Transaction>,
121 transaction_depth: usize,
122 group_interval: Duration,
123}
124
125impl History {
126 pub fn new(base_text: Arc<str>) -> Self {
127 Self {
128 base_text,
129 ops: Default::default(),
130 undo_stack: Vec::new(),
131 redo_stack: Vec::new(),
132 transaction_depth: 0,
133 group_interval: UNDO_GROUP_INTERVAL,
134 }
135 }
136
137 fn push(&mut self, op: EditOperation) {
138 self.ops.insert(op.id, op);
139 }
140
141 fn start_transaction(
142 &mut self,
143 start: time::Global,
144 buffer_was_dirty: bool,
145 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
146 now: Instant,
147 ) {
148 self.transaction_depth += 1;
149 if self.transaction_depth == 1 {
150 self.undo_stack.push(Transaction {
151 start,
152 buffer_was_dirty,
153 edits: Vec::new(),
154 selections_before: selections,
155 selections_after: None,
156 first_edit_at: now,
157 last_edit_at: now,
158 });
159 }
160 }
161
162 fn end_transaction(
163 &mut self,
164 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
165 now: Instant,
166 ) -> Option<&Transaction> {
167 assert_ne!(self.transaction_depth, 0);
168 self.transaction_depth -= 1;
169 if self.transaction_depth == 0 {
170 let transaction = self.undo_stack.last_mut().unwrap();
171 transaction.selections_after = selections;
172 transaction.last_edit_at = now;
173 Some(transaction)
174 } else {
175 None
176 }
177 }
178
179 fn group(&mut self) {
180 let mut new_len = self.undo_stack.len();
181 let mut transactions = self.undo_stack.iter_mut();
182
183 if let Some(mut transaction) = transactions.next_back() {
184 for prev_transaction in transactions.next_back() {
185 if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
186 {
187 prev_transaction.edits.append(&mut transaction.edits);
188 prev_transaction.last_edit_at = transaction.last_edit_at;
189 prev_transaction.selections_after = transaction.selections_after.take();
190 transaction = prev_transaction;
191 new_len -= 1;
192 } else {
193 break;
194 }
195 }
196 }
197
198 self.undo_stack.truncate(new_len);
199 }
200
201 fn push_undo(&mut self, edit_id: time::Local) {
202 assert_ne!(self.transaction_depth, 0);
203 self.undo_stack.last_mut().unwrap().edits.push(edit_id);
204 }
205
206 fn pop_undo(&mut self) -> Option<&Transaction> {
207 assert_eq!(self.transaction_depth, 0);
208 if let Some(transaction) = self.undo_stack.pop() {
209 self.redo_stack.push(transaction);
210 self.redo_stack.last()
211 } else {
212 None
213 }
214 }
215
216 fn pop_redo(&mut self) -> Option<&Transaction> {
217 assert_eq!(self.transaction_depth, 0);
218 if let Some(transaction) = self.redo_stack.pop() {
219 self.undo_stack.push(transaction);
220 self.undo_stack.last()
221 } else {
222 None
223 }
224 }
225}
226
227#[derive(Clone, Default, Debug)]
228struct UndoMap(HashMap<time::Local, Vec<UndoOperation>>);
229
230impl UndoMap {
231 fn insert(&mut self, undo: UndoOperation) {
232 self.0.entry(undo.edit_id).or_default().push(undo);
233 }
234
235 fn is_undone(&self, edit_id: time::Local) -> bool {
236 self.undo_count(edit_id) % 2 == 1
237 }
238
239 fn was_undone(&self, edit_id: time::Local, version: &time::Global) -> bool {
240 let undo_count = self
241 .0
242 .get(&edit_id)
243 .unwrap_or(&Vec::new())
244 .iter()
245 .filter(|undo| version.observed(undo.id))
246 .map(|undo| undo.count)
247 .max()
248 .unwrap_or(0);
249 undo_count % 2 == 1
250 }
251
252 fn undo_count(&self, edit_id: time::Local) -> u32 {
253 self.0
254 .get(&edit_id)
255 .unwrap_or(&Vec::new())
256 .iter()
257 .map(|undo| undo.count)
258 .max()
259 .unwrap_or(0)
260 }
261}
262
263struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
264 deleted_text: &'a Rope,
265 cursor: FilterCursor<'a, F, Fragment, FragmentTextSummary>,
266 undos: &'a UndoMap,
267 since: time::Global,
268 delta: isize,
269}
270
271#[derive(Clone, Debug, Default, Eq, PartialEq)]
272pub struct Edit {
273 pub old_range: Range<usize>,
274 pub new_range: Range<usize>,
275 pub old_lines: Point,
276}
277
278impl Edit {
279 pub fn delta(&self) -> isize {
280 (self.new_range.end - self.new_range.start) as isize
281 - (self.old_range.end - self.old_range.start) as isize
282 }
283
284 pub fn old_extent(&self) -> usize {
285 self.old_range.end - self.old_range.start
286 }
287}
288
289struct Diff {
290 base_version: time::Global,
291 new_text: Arc<str>,
292 changes: Vec<(ChangeTag, usize)>,
293}
294
295#[derive(Clone, Eq, PartialEq, Debug)]
296pub struct Insertion {
297 id: time::Local,
298 parent_id: time::Local,
299 offset_in_parent: usize,
300 lamport_timestamp: time::Lamport,
301}
302
303#[derive(Eq, PartialEq, Clone, Debug)]
304struct Fragment {
305 id: FragmentId,
306 insertion: Arc<Insertion>,
307 range_in_insertion: Range<usize>,
308 deletions: HashSet<time::Local>,
309 max_undos: time::Global,
310 visible: bool,
311}
312
313#[derive(Eq, PartialEq, Clone, Debug)]
314pub struct FragmentSummary {
315 text: FragmentTextSummary,
316 max_fragment_id: FragmentId,
317 max_version: time::Global,
318}
319
320#[derive(Default, Clone, Debug, PartialEq, Eq)]
321struct FragmentTextSummary {
322 visible: usize,
323 deleted: usize,
324}
325
326impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
327 fn add_summary(&mut self, summary: &'a FragmentSummary) {
328 self.visible += summary.text.visible;
329 self.deleted += summary.text.deleted;
330 }
331}
332
333#[derive(Eq, PartialEq, Clone, Debug)]
334struct InsertionSplit {
335 extent: usize,
336 fragment_id: FragmentId,
337}
338
339#[derive(Eq, PartialEq, Clone, Debug)]
340struct InsertionSplitSummary {
341 extent: usize,
342}
343
344#[derive(Clone, Debug, Eq, PartialEq)]
345pub enum Operation {
346 Edit {
347 edit: EditOperation,
348 lamport_timestamp: time::Lamport,
349 },
350 Undo {
351 undo: UndoOperation,
352 lamport_timestamp: time::Lamport,
353 },
354 UpdateSelections {
355 set_id: SelectionSetId,
356 selections: Option<Arc<[Selection]>>,
357 lamport_timestamp: time::Lamport,
358 },
359}
360
361#[derive(Clone, Debug, Eq, PartialEq)]
362pub struct EditOperation {
363 id: time::Local,
364 start_id: time::Local,
365 start_offset: usize,
366 end_id: time::Local,
367 end_offset: usize,
368 version_in_range: time::Global,
369 new_text: Option<String>,
370}
371
372#[derive(Copy, Clone, Debug, Eq, PartialEq)]
373pub struct UndoOperation {
374 id: time::Local,
375 edit_id: time::Local,
376 count: u32,
377}
378
379impl Buffer {
380 pub fn new<T: Into<Arc<str>>>(
381 replica_id: ReplicaId,
382 base_text: T,
383 ctx: &mut ModelContext<Self>,
384 ) -> Self {
385 Self::build(replica_id, History::new(base_text.into()), None, None, ctx)
386 }
387
388 pub fn from_history(
389 replica_id: ReplicaId,
390 history: History,
391 file: Option<FileHandle>,
392 language: Option<Arc<Language>>,
393 ctx: &mut ModelContext<Self>,
394 ) -> Self {
395 Self::build(replica_id, history, file, language, ctx)
396 }
397
398 fn build(
399 replica_id: ReplicaId,
400 history: History,
401 file: Option<FileHandle>,
402 language: Option<Arc<Language>>,
403 ctx: &mut ModelContext<Self>,
404 ) -> Self {
405 let saved_mtime;
406 if let Some(file) = file.as_ref() {
407 saved_mtime = file.mtime();
408 file.observe_from_model(ctx, |this, file, ctx| {
409 let version = this.version.clone();
410 if this.version == this.saved_version {
411 if file.is_deleted() {
412 ctx.emit(Event::Dirtied);
413 } else {
414 ctx.spawn(|handle, mut ctx| async move {
415 let (current_version, history) = handle.read_with(&ctx, |this, ctx| {
416 (this.version.clone(), file.load_history(ctx.as_ref()))
417 });
418 if let (Ok(history), true) = (history.await, current_version == version)
419 {
420 let diff = handle
421 .read_with(&ctx, |this, ctx| this.diff(history.base_text, ctx))
422 .await;
423 handle.update(&mut ctx, |this, ctx| {
424 if let Some(_ops) = this.set_text_via_diff(diff, ctx) {
425 this.saved_version = this.version.clone();
426 this.saved_mtime = file.mtime();
427 ctx.emit(Event::Reloaded);
428 }
429 });
430 }
431 })
432 .detach();
433 }
434 }
435 ctx.emit(Event::FileHandleChanged);
436 });
437 } else {
438 saved_mtime = UNIX_EPOCH;
439 }
440
441 let mut visible_text = Rope::new();
442 let mut insertion_splits = HashMap::default();
443 let mut fragments = SumTree::new();
444
445 let base_text = Rope::from(history.base_text.as_ref());
446 let base_insertion = Arc::new(Insertion {
447 id: time::Local::default(),
448 parent_id: time::Local::default(),
449 offset_in_parent: 0,
450 lamport_timestamp: time::Lamport::default(),
451 });
452
453 insertion_splits.insert(
454 base_insertion.id,
455 SumTree::from_item(
456 InsertionSplit {
457 fragment_id: FragmentId::min_value().clone(),
458 extent: 0,
459 },
460 &(),
461 ),
462 );
463 fragments.push(
464 Fragment::new(
465 FragmentId::min_value().clone(),
466 base_insertion.clone(),
467 0..0,
468 ),
469 &(),
470 );
471
472 if base_text.len() > 0 {
473 let base_fragment_id =
474 FragmentId::between(&FragmentId::min_value(), &FragmentId::max_value());
475 let range_in_insertion = 0..base_text.len();
476
477 visible_text = base_text.clone();
478 insertion_splits.get_mut(&base_insertion.id).unwrap().push(
479 InsertionSplit {
480 fragment_id: base_fragment_id.clone(),
481 extent: range_in_insertion.end,
482 },
483 &(),
484 );
485 fragments.push(
486 Fragment::new(base_fragment_id, base_insertion, range_in_insertion.clone()),
487 &(),
488 );
489 }
490
491 let mut result = Self {
492 visible_text,
493 deleted_text: Rope::new(),
494 fragments,
495 insertion_splits,
496 version: time::Global::new(),
497 saved_version: time::Global::new(),
498 last_edit: time::Local::default(),
499 undo_map: Default::default(),
500 history,
501 file,
502 syntax_tree: Mutex::new(None),
503 is_parsing: false,
504 language,
505 saved_mtime,
506 selections: HashMap::default(),
507 selections_last_update: 0,
508 deferred_ops: OperationQueue::new(),
509 deferred_replicas: HashSet::default(),
510 replica_id,
511 local_clock: time::Local::new(replica_id),
512 lamport_clock: time::Lamport::new(replica_id),
513 };
514 result.reparse(ctx);
515 result
516 }
517
518 pub fn snapshot(&self) -> Snapshot {
519 let mut cursors = QUERY_CURSORS.lock();
520 Snapshot {
521 text: self.visible_text.clone(),
522 tree: self.syntax_tree(),
523 language: self.language.clone(),
524 query_cursor: Some(cursors.pop().unwrap_or_else(|| QueryCursor::new())),
525 }
526 }
527
528 pub fn file(&self) -> Option<&FileHandle> {
529 self.file.as_ref()
530 }
531
532 pub fn save(
533 &mut self,
534 new_file: Option<FileHandle>,
535 ctx: &mut ModelContext<Self>,
536 ) -> Task<Result<()>> {
537 let text = self.visible_text.clone();
538 let version = self.version.clone();
539 let file = self.file.clone();
540
541 ctx.spawn(|handle, mut ctx| async move {
542 if let Some(file) = new_file.as_ref().or(file.as_ref()) {
543 let result = ctx.read(|ctx| file.save(text, ctx.as_ref())).await;
544 if result.is_ok() {
545 handle.update(&mut ctx, |me, ctx| me.did_save(version, new_file, ctx));
546 }
547 result
548 } else {
549 Ok(())
550 }
551 })
552 }
553
554 fn did_save(
555 &mut self,
556 version: time::Global,
557 file: Option<FileHandle>,
558 ctx: &mut ModelContext<Buffer>,
559 ) {
560 if file.is_some() {
561 self.file = file;
562 }
563 if let Some(file) = &self.file {
564 self.saved_mtime = file.mtime();
565 }
566 self.saved_version = version;
567 ctx.emit(Event::Saved);
568 }
569
570 pub fn syntax_tree(&self) -> Option<Tree> {
571 if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
572 let mut edited = false;
573 let mut delta = 0_isize;
574 for Edit {
575 old_range,
576 new_range,
577 old_lines,
578 } in self.edits_since(syntax_tree.version.clone())
579 {
580 let start_offset = (old_range.start as isize + delta) as usize;
581 let start_point = self.visible_text.to_point(start_offset);
582 let old_bytes = old_range.end - old_range.start;
583 let new_bytes = new_range.end - new_range.start;
584 syntax_tree.tree.edit(&InputEdit {
585 start_byte: start_offset,
586 old_end_byte: start_offset + old_bytes,
587 new_end_byte: start_offset + new_bytes,
588 start_position: start_point.into(),
589 old_end_position: (start_point + old_lines).into(),
590 new_end_position: self.visible_text.to_point(start_offset + new_bytes).into(),
591 });
592 delta += new_bytes as isize - old_bytes as isize;
593 edited = true;
594 }
595 syntax_tree.parsed &= !edited;
596 syntax_tree.version = self.version();
597 Some(syntax_tree.tree.clone())
598 } else {
599 None
600 }
601 }
602
603 pub fn is_parsing(&self) -> bool {
604 self.is_parsing
605 }
606
607 fn should_reparse(&self) -> bool {
608 if let Some(syntax_tree) = self.syntax_tree.lock().as_ref() {
609 !syntax_tree.parsed || syntax_tree.version != self.version
610 } else {
611 self.language.is_some()
612 }
613 }
614
615 fn reparse(&mut self, ctx: &mut ModelContext<Self>) {
616 // Avoid spawning a new parsing task if the buffer is already being reparsed
617 // due to an earlier edit.
618 if self.is_parsing {
619 return;
620 }
621
622 if let Some(language) = self.language.clone() {
623 self.is_parsing = true;
624 ctx.spawn(|handle, mut ctx| async move {
625 while handle.read_with(&ctx, |this, _| this.should_reparse()) {
626 // The parse tree is out of date, so grab the syntax tree to synchronously
627 // splice all the edits that have happened since the last parse.
628 let new_tree = handle.update(&mut ctx, |this, _| this.syntax_tree());
629 let (new_text, new_version) = handle
630 .read_with(&ctx, |this, _| (this.visible_text.clone(), this.version()));
631
632 // Parse the current text in a background thread.
633 let new_tree = ctx
634 .background_executor()
635 .spawn({
636 let language = language.clone();
637 async move { Self::parse_text(&new_text, new_tree, &language) }
638 })
639 .await;
640
641 handle.update(&mut ctx, |this, ctx| {
642 *this.syntax_tree.lock() = Some(SyntaxTree {
643 tree: new_tree,
644 parsed: true,
645 version: new_version,
646 });
647 ctx.emit(Event::Reparsed);
648 ctx.notify();
649 });
650 }
651 handle.update(&mut ctx, |this, _| this.is_parsing = false);
652 })
653 .detach();
654 }
655 }
656
657 fn parse_text(text: &Rope, old_tree: Option<Tree>, language: &Language) -> Tree {
658 PARSER.with(|parser| {
659 let mut parser = parser.borrow_mut();
660 parser
661 .set_language(language.grammar)
662 .expect("incompatible grammar");
663 let mut chunks = text.chunks_in_range(0..text.len());
664 let tree = parser
665 .parse_with(
666 &mut move |offset, _| {
667 chunks.seek(offset);
668 chunks.next().unwrap_or("").as_bytes()
669 },
670 old_tree.as_ref(),
671 )
672 .unwrap();
673 tree
674 })
675 }
676
677 fn diff(&self, new_text: Arc<str>, ctx: &AppContext) -> Task<Diff> {
678 // TODO: it would be nice to not allocate here.
679 let old_text = self.text();
680 let base_version = self.version();
681 ctx.background_executor().spawn(async move {
682 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
683 .iter_all_changes()
684 .map(|c| (c.tag(), c.value().len()))
685 .collect::<Vec<_>>();
686 Diff {
687 base_version,
688 new_text,
689 changes,
690 }
691 })
692 }
693
694 fn set_text_via_diff(
695 &mut self,
696 diff: Diff,
697 ctx: &mut ModelContext<Self>,
698 ) -> Option<Vec<Operation>> {
699 if self.version == diff.base_version {
700 self.start_transaction(None).unwrap();
701 let mut operations = Vec::new();
702 let mut offset = 0;
703 for (tag, len) in diff.changes {
704 let range = offset..(offset + len);
705 match tag {
706 ChangeTag::Equal => offset += len,
707 ChangeTag::Delete => operations
708 .extend_from_slice(&self.edit(Some(range), "", Some(ctx)).unwrap()),
709 ChangeTag::Insert => {
710 operations.extend_from_slice(
711 &self
712 .edit(Some(offset..offset), &diff.new_text[range], Some(ctx))
713 .unwrap(),
714 );
715 offset += len;
716 }
717 }
718 }
719 self.end_transaction(None, Some(ctx)).unwrap();
720 Some(operations)
721 } else {
722 None
723 }
724 }
725
726 pub fn is_dirty(&self) -> bool {
727 self.version > self.saved_version || self.file.as_ref().map_or(false, |f| f.is_deleted())
728 }
729
730 pub fn has_conflict(&self) -> bool {
731 self.version > self.saved_version
732 && self
733 .file
734 .as_ref()
735 .map_or(false, |f| f.mtime() > self.saved_mtime)
736 }
737
738 pub fn version(&self) -> time::Global {
739 self.version.clone()
740 }
741
742 pub fn text_summary(&self) -> TextSummary {
743 self.visible_text.summary()
744 }
745
746 pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
747 self.visible_text.cursor(range.start).summary(range.end)
748 }
749
750 pub fn len(&self) -> usize {
751 self.fragments.extent::<usize>()
752 }
753
754 pub fn line_len(&self, row: u32) -> u32 {
755 let row_start_offset = Point::new(row, 0).to_offset(self);
756 let row_end_offset = if row >= self.max_point().row {
757 self.len()
758 } else {
759 Point::new(row + 1, 0).to_offset(self) - 1
760 };
761 (row_end_offset - row_start_offset) as u32
762 }
763
764 pub fn max_point(&self) -> Point {
765 self.visible_text.max_point()
766 }
767
768 pub fn line(&self, row: u32) -> String {
769 self.chars_at(Point::new(row, 0))
770 .take_while(|c| *c != '\n')
771 .collect()
772 }
773
774 pub fn text(&self) -> String {
775 self.text_for_range(0..self.len()).collect()
776 }
777
778 pub fn text_for_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> Chunks<'a> {
779 let start = range.start.to_offset(self);
780 let end = range.end.to_offset(self);
781 self.visible_text.chunks_in_range(start..end)
782 }
783
784 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
785 self.chars_at(0)
786 }
787
788 pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
789 let offset = position.to_offset(self);
790 self.visible_text.chars_at(offset)
791 }
792
793 pub fn selections_changed_since(&self, since: SelectionsVersion) -> bool {
794 self.selections_last_update != since
795 }
796
797 pub fn edits_since<'a>(&'a self, since: time::Global) -> impl 'a + Iterator<Item = Edit> {
798 let since_2 = since.clone();
799 let cursor = self
800 .fragments
801 .filter(move |summary| summary.max_version.changed_since(&since_2));
802
803 Edits {
804 deleted_text: &self.deleted_text,
805 cursor,
806 undos: &self.undo_map,
807 since,
808 delta: 0,
809 }
810 }
811
812 pub fn deferred_ops_len(&self) -> usize {
813 self.deferred_ops.len()
814 }
815
816 pub fn start_transaction(&mut self, set_id: Option<SelectionSetId>) -> Result<()> {
817 self.start_transaction_at(set_id, Instant::now())
818 }
819
820 fn start_transaction_at(&mut self, set_id: Option<SelectionSetId>, now: Instant) -> Result<()> {
821 let selections = if let Some(set_id) = set_id {
822 let selections = self
823 .selections
824 .get(&set_id)
825 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
826 Some((set_id, selections.clone()))
827 } else {
828 None
829 };
830 self.history
831 .start_transaction(self.version.clone(), self.is_dirty(), selections, now);
832 Ok(())
833 }
834
835 pub fn end_transaction(
836 &mut self,
837 set_id: Option<SelectionSetId>,
838 ctx: Option<&mut ModelContext<Self>>,
839 ) -> Result<()> {
840 self.end_transaction_at(set_id, Instant::now(), ctx)
841 }
842
843 fn end_transaction_at(
844 &mut self,
845 set_id: Option<SelectionSetId>,
846 now: Instant,
847 ctx: Option<&mut ModelContext<Self>>,
848 ) -> Result<()> {
849 let selections = if let Some(set_id) = set_id {
850 let selections = self
851 .selections
852 .get(&set_id)
853 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
854 Some((set_id, selections.clone()))
855 } else {
856 None
857 };
858
859 if let Some(transaction) = self.history.end_transaction(selections, now) {
860 let since = transaction.start.clone();
861 let was_dirty = transaction.buffer_was_dirty;
862 self.history.group();
863
864 if let Some(ctx) = ctx {
865 ctx.notify();
866
867 if self.edits_since(since).next().is_some() {
868 self.did_edit(was_dirty, ctx);
869 self.reparse(ctx);
870 }
871 }
872 }
873
874 Ok(())
875 }
876
877 pub fn edit<I, S, T>(
878 &mut self,
879 old_ranges: I,
880 new_text: T,
881 ctx: Option<&mut ModelContext<Self>>,
882 ) -> Result<Vec<Operation>>
883 where
884 I: IntoIterator<Item = Range<S>>,
885 S: ToOffset,
886 T: Into<String>,
887 {
888 self.start_transaction_at(None, Instant::now())?;
889
890 let new_text = new_text.into();
891 let old_ranges = old_ranges
892 .into_iter()
893 .map(|range| range.start.to_offset(self)..range.end.to_offset(self))
894 .collect::<Vec<Range<usize>>>();
895
896 let new_text = if new_text.len() > 0 {
897 Some(new_text)
898 } else {
899 None
900 };
901
902 let has_new_text = new_text.is_some();
903 let ops = self.splice_fragments(
904 old_ranges
905 .into_iter()
906 .filter(|old_range| has_new_text || old_range.end > old_range.start),
907 new_text.into(),
908 );
909
910 for op in &ops {
911 if let Operation::Edit { edit, .. } = op {
912 self.history.push(edit.clone());
913 self.history.push_undo(edit.id);
914 }
915 }
916
917 if let Some(op) = ops.last() {
918 if let Operation::Edit { edit, .. } = op {
919 self.last_edit = edit.id;
920 self.version.observe(edit.id);
921 } else {
922 unreachable!()
923 }
924 }
925
926 self.end_transaction_at(None, Instant::now(), ctx)?;
927
928 Ok(ops)
929 }
930
931 fn did_edit(&self, was_dirty: bool, ctx: &mut ModelContext<Self>) {
932 ctx.emit(Event::Edited);
933 if !was_dirty {
934 ctx.emit(Event::Dirtied);
935 }
936 }
937
938 pub fn add_selection_set(
939 &mut self,
940 selections: impl Into<Arc<[Selection]>>,
941 ctx: Option<&mut ModelContext<Self>>,
942 ) -> (SelectionSetId, Operation) {
943 let selections = selections.into();
944 let lamport_timestamp = self.lamport_clock.tick();
945 self.selections
946 .insert(lamport_timestamp, Arc::clone(&selections));
947 self.selections_last_update += 1;
948
949 if let Some(ctx) = ctx {
950 ctx.notify();
951 }
952
953 (
954 lamport_timestamp,
955 Operation::UpdateSelections {
956 set_id: lamport_timestamp,
957 selections: Some(selections),
958 lamport_timestamp,
959 },
960 )
961 }
962
963 pub fn update_selection_set(
964 &mut self,
965 set_id: SelectionSetId,
966 selections: impl Into<Arc<[Selection]>>,
967 ctx: Option<&mut ModelContext<Self>>,
968 ) -> Result<Operation> {
969 let selections = selections.into();
970 self.selections.insert(set_id, selections.clone());
971
972 let lamport_timestamp = self.lamport_clock.tick();
973 self.selections_last_update += 1;
974
975 if let Some(ctx) = ctx {
976 ctx.notify();
977 }
978
979 Ok(Operation::UpdateSelections {
980 set_id,
981 selections: Some(selections),
982 lamport_timestamp,
983 })
984 }
985
986 pub fn remove_selection_set(
987 &mut self,
988 set_id: SelectionSetId,
989 ctx: Option<&mut ModelContext<Self>>,
990 ) -> Result<Operation> {
991 self.selections
992 .remove(&set_id)
993 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
994 let lamport_timestamp = self.lamport_clock.tick();
995 self.selections_last_update += 1;
996
997 if let Some(ctx) = ctx {
998 ctx.notify();
999 }
1000
1001 Ok(Operation::UpdateSelections {
1002 set_id,
1003 selections: None,
1004 lamport_timestamp,
1005 })
1006 }
1007
1008 pub fn selections(&self, set_id: SelectionSetId) -> Result<&[Selection]> {
1009 self.selections
1010 .get(&set_id)
1011 .map(|s| s.as_ref())
1012 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))
1013 }
1014
1015 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1016 &mut self,
1017 ops: I,
1018 ctx: Option<&mut ModelContext<Self>>,
1019 ) -> Result<()> {
1020 let was_dirty = self.is_dirty();
1021 let old_version = self.version.clone();
1022
1023 let mut deferred_ops = Vec::new();
1024 for op in ops {
1025 if self.can_apply_op(&op) {
1026 self.apply_op(op)?;
1027 } else {
1028 self.deferred_replicas.insert(op.replica_id());
1029 deferred_ops.push(op);
1030 }
1031 }
1032 self.deferred_ops.insert(deferred_ops);
1033 self.flush_deferred_ops()?;
1034
1035 if let Some(ctx) = ctx {
1036 ctx.notify();
1037 if self.edits_since(old_version).next().is_some() {
1038 self.did_edit(was_dirty, ctx);
1039 self.reparse(ctx);
1040 }
1041 }
1042
1043 Ok(())
1044 }
1045
1046 fn apply_op(&mut self, op: Operation) -> Result<()> {
1047 match op {
1048 Operation::Edit {
1049 edit,
1050 lamport_timestamp,
1051 ..
1052 } => {
1053 if !self.version.observed(edit.id) {
1054 self.apply_edit(
1055 edit.start_id,
1056 edit.start_offset,
1057 edit.end_id,
1058 edit.end_offset,
1059 edit.new_text.as_deref(),
1060 &edit.version_in_range,
1061 edit.id,
1062 lamport_timestamp,
1063 )?;
1064 self.version.observe(edit.id);
1065 self.history.push(edit);
1066 }
1067 }
1068 Operation::Undo {
1069 undo,
1070 lamport_timestamp,
1071 } => {
1072 if !self.version.observed(undo.id) {
1073 self.apply_undo(undo)?;
1074 self.version.observe(undo.id);
1075 self.lamport_clock.observe(lamport_timestamp);
1076 }
1077 }
1078 Operation::UpdateSelections {
1079 set_id,
1080 selections,
1081 lamport_timestamp,
1082 } => {
1083 if let Some(selections) = selections {
1084 self.selections.insert(set_id, selections);
1085 } else {
1086 self.selections.remove(&set_id);
1087 }
1088 self.lamport_clock.observe(lamport_timestamp);
1089 self.selections_last_update += 1;
1090 }
1091 }
1092 Ok(())
1093 }
1094
1095 fn apply_edit(
1096 &mut self,
1097 start_id: time::Local,
1098 start_offset: usize,
1099 end_id: time::Local,
1100 end_offset: usize,
1101 mut new_text: Option<&str>,
1102 version_in_range: &time::Global,
1103 local_timestamp: time::Local,
1104 lamport_timestamp: time::Lamport,
1105 ) -> Result<()> {
1106 let start_fragment_id = self.resolve_fragment_id(start_id, start_offset)?;
1107 let end_fragment_id = self.resolve_fragment_id(end_id, end_offset)?;
1108
1109 let mut old_visible_text = Rope::new();
1110 let mut old_deleted_text = Rope::new();
1111 let mut old_fragments = SumTree::new();
1112 mem::swap(&mut old_visible_text, &mut self.visible_text);
1113 mem::swap(&mut old_deleted_text, &mut self.deleted_text);
1114 mem::swap(&mut old_fragments, &mut self.fragments);
1115
1116 let mut fragments_cursor = old_fragments.cursor::<FragmentIdRef, FragmentTextSummary>();
1117
1118 let mut new_fragments =
1119 fragments_cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &());
1120 let mut new_ropes =
1121 RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
1122 new_ropes.push_tree(new_fragments.summary().text);
1123
1124 let start_fragment = fragments_cursor.item().unwrap();
1125 if start_offset == start_fragment.range_in_insertion.end {
1126 let fragment = fragments_cursor.item().unwrap().clone();
1127 new_ropes.push_fragment(&fragment, fragment.visible);
1128 new_fragments.push(fragment, &());
1129 fragments_cursor.next();
1130 }
1131
1132 while let Some(fragment) = fragments_cursor.item() {
1133 if new_text.is_none() && fragment.id > end_fragment_id {
1134 break;
1135 }
1136
1137 let mut fragment = fragment.clone();
1138
1139 if fragment.id == start_fragment_id || fragment.id == end_fragment_id {
1140 let split_start = if start_fragment_id == fragment.id {
1141 start_offset
1142 } else {
1143 fragment.range_in_insertion.start
1144 };
1145 let split_end = if end_fragment_id == fragment.id {
1146 end_offset
1147 } else {
1148 fragment.range_in_insertion.end
1149 };
1150 let (before_range, within_range, after_range) = self.split_fragment(
1151 fragments_cursor.prev_item().as_ref().unwrap(),
1152 &fragment,
1153 split_start..split_end,
1154 );
1155 let insertion = if let Some(new_text) = new_text {
1156 let prev_fragment = fragments_cursor.prev_item();
1157 Some(self.build_fragment_to_insert(
1158 before_range.as_ref().or(prev_fragment).unwrap(),
1159 within_range.as_ref().or(after_range.as_ref()),
1160 new_text,
1161 local_timestamp,
1162 lamport_timestamp,
1163 ))
1164 } else {
1165 None
1166 };
1167 if let Some(fragment) = before_range {
1168 new_ropes.push_fragment(&fragment, fragment.visible);
1169 new_fragments.push(fragment, &());
1170 }
1171 if let Some(fragment) = insertion {
1172 new_ropes.push_str(new_text.take().unwrap());
1173 new_fragments.push(fragment, &());
1174 }
1175 if let Some(mut fragment) = within_range {
1176 let fragment_was_visible = fragment.visible;
1177 if fragment.was_visible(&version_in_range, &self.undo_map) {
1178 fragment.deletions.insert(local_timestamp);
1179 if fragment.visible {
1180 fragment.visible = false;
1181 }
1182 }
1183
1184 new_ropes.push_fragment(&fragment, fragment_was_visible);
1185 new_fragments.push(fragment, &());
1186 }
1187 if let Some(fragment) = after_range {
1188 new_ropes.push_fragment(&fragment, fragment.visible);
1189 new_fragments.push(fragment, &());
1190 }
1191 } else {
1192 if new_text.is_some() && lamport_timestamp > fragment.insertion.lamport_timestamp {
1193 let new_text = new_text.take().unwrap();
1194 let fragment = self.build_fragment_to_insert(
1195 fragments_cursor.prev_item().as_ref().unwrap(),
1196 Some(&fragment),
1197 new_text,
1198 local_timestamp,
1199 lamport_timestamp,
1200 );
1201 new_ropes.push_str(new_text);
1202 new_fragments.push(fragment, &());
1203 }
1204
1205 let fragment_was_visible = fragment.visible;
1206 if fragment.id < end_fragment_id
1207 && fragment.was_visible(&version_in_range, &self.undo_map)
1208 {
1209 fragment.deletions.insert(local_timestamp);
1210 if fragment.visible {
1211 fragment.visible = false;
1212 }
1213 }
1214
1215 new_ropes.push_fragment(&fragment, fragment_was_visible);
1216 new_fragments.push(fragment, &());
1217 }
1218
1219 fragments_cursor.next();
1220 }
1221
1222 if let Some(new_text) = new_text {
1223 let fragment = self.build_fragment_to_insert(
1224 fragments_cursor.prev_item().as_ref().unwrap(),
1225 None,
1226 new_text,
1227 local_timestamp,
1228 lamport_timestamp,
1229 );
1230 new_ropes.push_str(new_text);
1231 new_fragments.push(fragment, &());
1232 }
1233
1234 let (visible_text, deleted_text) = new_ropes.finish();
1235 new_fragments.push_tree(fragments_cursor.suffix(&()), &());
1236
1237 self.fragments = new_fragments;
1238 self.visible_text = visible_text;
1239 self.deleted_text = deleted_text;
1240 self.local_clock.observe(local_timestamp);
1241 self.lamport_clock.observe(lamport_timestamp);
1242 Ok(())
1243 }
1244
1245 pub fn undo(&mut self, mut ctx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
1246 let was_dirty = self.is_dirty();
1247 let old_version = self.version.clone();
1248
1249 let mut ops = Vec::new();
1250 if let Some(transaction) = self.history.pop_undo() {
1251 let selections = transaction.selections_before.clone();
1252 for edit_id in transaction.edits.clone() {
1253 ops.push(self.undo_or_redo(edit_id).unwrap());
1254 }
1255
1256 if let Some((set_id, selections)) = selections {
1257 let _ = self.update_selection_set(set_id, selections, ctx.as_deref_mut());
1258 }
1259 }
1260
1261 if let Some(ctx) = ctx {
1262 ctx.notify();
1263 if self.edits_since(old_version).next().is_some() {
1264 self.did_edit(was_dirty, ctx);
1265 self.reparse(ctx);
1266 }
1267 }
1268
1269 ops
1270 }
1271
1272 pub fn redo(&mut self, mut ctx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
1273 let was_dirty = self.is_dirty();
1274 let old_version = self.version.clone();
1275
1276 let mut ops = Vec::new();
1277 if let Some(transaction) = self.history.pop_redo() {
1278 let selections = transaction.selections_after.clone();
1279 for edit_id in transaction.edits.clone() {
1280 ops.push(self.undo_or_redo(edit_id).unwrap());
1281 }
1282
1283 if let Some((set_id, selections)) = selections {
1284 let _ = self.update_selection_set(set_id, selections, ctx.as_deref_mut());
1285 }
1286 }
1287
1288 if let Some(ctx) = ctx {
1289 ctx.notify();
1290 if self.edits_since(old_version).next().is_some() {
1291 self.did_edit(was_dirty, ctx);
1292 self.reparse(ctx);
1293 }
1294 }
1295
1296 ops
1297 }
1298
1299 fn undo_or_redo(&mut self, edit_id: time::Local) -> Result<Operation> {
1300 let undo = UndoOperation {
1301 id: self.local_clock.tick(),
1302 edit_id,
1303 count: self.undo_map.undo_count(edit_id) + 1,
1304 };
1305 self.apply_undo(undo)?;
1306 self.version.observe(undo.id);
1307
1308 Ok(Operation::Undo {
1309 undo,
1310 lamport_timestamp: self.lamport_clock.tick(),
1311 })
1312 }
1313
1314 fn apply_undo(&mut self, undo: UndoOperation) -> Result<()> {
1315 let mut new_fragments;
1316 let mut old_visible_text = Rope::new();
1317 let mut old_deleted_text = Rope::new();
1318 mem::swap(&mut old_visible_text, &mut self.visible_text);
1319 mem::swap(&mut old_deleted_text, &mut self.deleted_text);
1320 let mut new_ropes =
1321 RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
1322
1323 self.undo_map.insert(undo);
1324 let edit = &self.history.ops[&undo.edit_id];
1325 let start_fragment_id = self.resolve_fragment_id(edit.start_id, edit.start_offset)?;
1326 let end_fragment_id = self.resolve_fragment_id(edit.end_id, edit.end_offset)?;
1327
1328 let mut fragments_cursor = self.fragments.cursor::<FragmentIdRef, ()>();
1329
1330 if edit.start_id == edit.end_id && edit.start_offset == edit.end_offset {
1331 let splits = &self.insertion_splits[&undo.edit_id];
1332 let mut insertion_splits = splits.cursor::<(), ()>().map(|s| &s.fragment_id).peekable();
1333
1334 let first_split_id = insertion_splits.next().unwrap();
1335 new_fragments =
1336 fragments_cursor.slice(&FragmentIdRef::new(first_split_id), SeekBias::Left, &());
1337 new_ropes.push_tree(new_fragments.summary().text);
1338
1339 loop {
1340 let mut fragment = fragments_cursor.item().unwrap().clone();
1341 let was_visible = fragment.visible;
1342 fragment.visible = fragment.is_visible(&self.undo_map);
1343 fragment.max_undos.observe(undo.id);
1344
1345 new_ropes.push_fragment(&fragment, was_visible);
1346 new_fragments.push(fragment.clone(), &());
1347
1348 fragments_cursor.next();
1349 if let Some(split_id) = insertion_splits.next() {
1350 let slice =
1351 fragments_cursor.slice(&FragmentIdRef::new(split_id), SeekBias::Left, &());
1352 new_ropes.push_tree(slice.summary().text);
1353 new_fragments.push_tree(slice, &());
1354 } else {
1355 break;
1356 }
1357 }
1358 } else {
1359 new_fragments = fragments_cursor.slice(
1360 &FragmentIdRef::new(&start_fragment_id),
1361 SeekBias::Left,
1362 &(),
1363 );
1364 new_ropes.push_tree(new_fragments.summary().text);
1365
1366 while let Some(fragment) = fragments_cursor.item() {
1367 if fragment.id > end_fragment_id {
1368 break;
1369 } else {
1370 let mut fragment = fragment.clone();
1371 let fragment_was_visible = fragment.visible;
1372 if edit.version_in_range.observed(fragment.insertion.id)
1373 || fragment.insertion.id == undo.edit_id
1374 {
1375 fragment.visible = fragment.is_visible(&self.undo_map);
1376 fragment.max_undos.observe(undo.id);
1377 }
1378
1379 new_ropes.push_fragment(&fragment, fragment_was_visible);
1380 new_fragments.push(fragment, &());
1381 fragments_cursor.next();
1382 }
1383 }
1384 }
1385
1386 new_fragments.push_tree(fragments_cursor.suffix(&()), &());
1387 let (visible_text, deleted_text) = new_ropes.finish();
1388 drop(fragments_cursor);
1389
1390 self.fragments = new_fragments;
1391 self.visible_text = visible_text;
1392 self.deleted_text = deleted_text;
1393
1394 Ok(())
1395 }
1396
1397 fn flush_deferred_ops(&mut self) -> Result<()> {
1398 self.deferred_replicas.clear();
1399 let mut deferred_ops = Vec::new();
1400 for op in self.deferred_ops.drain().cursor().cloned() {
1401 if self.can_apply_op(&op) {
1402 self.apply_op(op)?;
1403 } else {
1404 self.deferred_replicas.insert(op.replica_id());
1405 deferred_ops.push(op);
1406 }
1407 }
1408 self.deferred_ops.insert(deferred_ops);
1409 Ok(())
1410 }
1411
1412 fn can_apply_op(&self, op: &Operation) -> bool {
1413 if self.deferred_replicas.contains(&op.replica_id()) {
1414 false
1415 } else {
1416 match op {
1417 Operation::Edit { edit, .. } => {
1418 self.version.observed(edit.start_id)
1419 && self.version.observed(edit.end_id)
1420 && edit.version_in_range <= self.version
1421 }
1422 Operation::Undo { undo, .. } => self.version.observed(undo.edit_id),
1423 Operation::UpdateSelections { selections, .. } => {
1424 if let Some(selections) = selections {
1425 selections.iter().all(|selection| {
1426 let contains_start = match selection.start {
1427 Anchor::Middle { insertion_id, .. } => {
1428 self.version.observed(insertion_id)
1429 }
1430 _ => true,
1431 };
1432 let contains_end = match selection.end {
1433 Anchor::Middle { insertion_id, .. } => {
1434 self.version.observed(insertion_id)
1435 }
1436 _ => true,
1437 };
1438 contains_start && contains_end
1439 })
1440 } else {
1441 true
1442 }
1443 }
1444 }
1445 }
1446 }
1447
1448 fn resolve_fragment_id(&self, edit_id: time::Local, offset: usize) -> Result<FragmentId> {
1449 let split_tree = self
1450 .insertion_splits
1451 .get(&edit_id)
1452 .ok_or_else(|| anyhow!("invalid operation"))?;
1453 let mut cursor = split_tree.cursor::<usize, ()>();
1454 cursor.seek(&offset, SeekBias::Left, &());
1455 Ok(cursor
1456 .item()
1457 .ok_or_else(|| anyhow!("invalid operation"))?
1458 .fragment_id
1459 .clone())
1460 }
1461
1462 fn splice_fragments<I>(&mut self, mut old_ranges: I, new_text: Option<String>) -> Vec<Operation>
1463 where
1464 I: Iterator<Item = Range<usize>>,
1465 {
1466 let mut cur_range = old_ranges.next();
1467 if cur_range.is_none() {
1468 return Vec::new();
1469 }
1470
1471 let mut ops = Vec::with_capacity(old_ranges.size_hint().0);
1472
1473 let mut old_fragments = SumTree::new();
1474 let mut old_visible_text = Rope::new();
1475 let mut old_deleted_text = Rope::new();
1476 mem::swap(&mut old_visible_text, &mut self.visible_text);
1477 mem::swap(&mut old_deleted_text, &mut self.deleted_text);
1478 mem::swap(&mut old_fragments, &mut self.fragments);
1479
1480 let mut fragments_cursor = old_fragments.cursor::<usize, usize>();
1481 let mut new_fragments =
1482 fragments_cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right, &());
1483
1484 let mut new_ropes =
1485 RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
1486 new_ropes.push_tree(new_fragments.summary().text);
1487
1488 let mut start_id = None;
1489 let mut start_offset = None;
1490 let mut end_id = None;
1491 let mut end_offset = None;
1492 let mut version_in_range = time::Global::new();
1493
1494 let mut local_timestamp = self.local_clock.tick();
1495 let mut lamport_timestamp = self.lamport_clock.tick();
1496
1497 while cur_range.is_some() && fragments_cursor.item().is_some() {
1498 let mut fragment = fragments_cursor.item().unwrap().clone();
1499 let fragment_summary = fragments_cursor.item_summary().unwrap();
1500 let mut fragment_start = *fragments_cursor.start();
1501 let mut fragment_end = fragment_start + fragment.visible_len();
1502 let fragment_was_visible = fragment.visible;
1503
1504 let old_split_tree = self
1505 .insertion_splits
1506 .remove(&fragment.insertion.id)
1507 .unwrap();
1508 let mut splits_cursor = old_split_tree.cursor::<usize, ()>();
1509 let mut new_split_tree =
1510 splits_cursor.slice(&fragment.range_in_insertion.start, SeekBias::Right, &());
1511
1512 // Find all splices that start or end within the current fragment. Then, split the
1513 // fragment and reassemble it in both trees accounting for the deleted and the newly
1514 // inserted text.
1515 while cur_range.as_ref().map_or(false, |r| r.start < fragment_end) {
1516 let range = cur_range.clone().unwrap();
1517 if range.start > fragment_start {
1518 let mut prefix = fragment.clone();
1519 prefix.range_in_insertion.end =
1520 prefix.range_in_insertion.start + (range.start - fragment_start);
1521 prefix.id =
1522 FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
1523 fragment.range_in_insertion.start = prefix.range_in_insertion.end;
1524
1525 new_ropes.push_fragment(&prefix, prefix.visible);
1526 new_fragments.push(prefix.clone(), &());
1527 new_split_tree.push(
1528 InsertionSplit {
1529 extent: prefix.range_in_insertion.end - prefix.range_in_insertion.start,
1530 fragment_id: prefix.id,
1531 },
1532 &(),
1533 );
1534 fragment_start = range.start;
1535 }
1536
1537 if range.end == fragment_start {
1538 end_id = Some(new_fragments.last().unwrap().insertion.id);
1539 end_offset = Some(new_fragments.last().unwrap().range_in_insertion.end);
1540 } else if range.end == fragment_end {
1541 end_id = Some(fragment.insertion.id);
1542 end_offset = Some(fragment.range_in_insertion.end);
1543 }
1544
1545 if range.start == fragment_start {
1546 start_id = Some(new_fragments.last().unwrap().insertion.id);
1547 start_offset = Some(new_fragments.last().unwrap().range_in_insertion.end);
1548
1549 if let Some(new_text) = new_text.clone() {
1550 let new_fragment = self.build_fragment_to_insert(
1551 &new_fragments.last().unwrap(),
1552 Some(&fragment),
1553 &new_text,
1554 local_timestamp,
1555 lamport_timestamp,
1556 );
1557
1558 new_ropes.push_str(&new_text);
1559 new_fragments.push(new_fragment, &());
1560 }
1561 }
1562
1563 if range.end < fragment_end {
1564 if range.end > fragment_start {
1565 let mut prefix = fragment.clone();
1566 prefix.range_in_insertion.end =
1567 prefix.range_in_insertion.start + (range.end - fragment_start);
1568 prefix.id =
1569 FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
1570 version_in_range.observe_all(&fragment_summary.max_version);
1571 if prefix.visible {
1572 prefix.deletions.insert(local_timestamp);
1573 prefix.visible = false;
1574 }
1575 fragment.range_in_insertion.start = prefix.range_in_insertion.end;
1576 new_ropes.push_fragment(&prefix, fragment_was_visible);
1577 new_fragments.push(prefix.clone(), &());
1578 new_split_tree.push(
1579 InsertionSplit {
1580 extent: prefix.range_in_insertion.end
1581 - prefix.range_in_insertion.start,
1582 fragment_id: prefix.id,
1583 },
1584 &(),
1585 );
1586 fragment_start = range.end;
1587 end_id = Some(fragment.insertion.id);
1588 end_offset = Some(fragment.range_in_insertion.start);
1589 }
1590 } else {
1591 version_in_range.observe_all(&fragment_summary.max_version);
1592 if fragment.visible {
1593 fragment.deletions.insert(local_timestamp);
1594 fragment.visible = false;
1595 }
1596 }
1597
1598 // If the splice ends inside this fragment, we can advance to the next splice and
1599 // check if it also intersects the current fragment. Otherwise we break out of the
1600 // loop and find the first fragment that the splice does not contain fully.
1601 if range.end <= fragment_end {
1602 ops.push(Operation::Edit {
1603 edit: EditOperation {
1604 id: local_timestamp,
1605 start_id: start_id.unwrap(),
1606 start_offset: start_offset.unwrap(),
1607 end_id: end_id.unwrap(),
1608 end_offset: end_offset.unwrap(),
1609 version_in_range,
1610 new_text: new_text.clone(),
1611 },
1612 lamport_timestamp,
1613 });
1614
1615 start_id = None;
1616 start_offset = None;
1617 end_id = None;
1618 end_offset = None;
1619 version_in_range = time::Global::new();
1620 cur_range = old_ranges.next();
1621 if cur_range.is_some() {
1622 local_timestamp = self.local_clock.tick();
1623 lamport_timestamp = self.lamport_clock.tick();
1624 }
1625 } else {
1626 break;
1627 }
1628 }
1629 new_split_tree.push(
1630 InsertionSplit {
1631 extent: fragment.range_in_insertion.end - fragment.range_in_insertion.start,
1632 fragment_id: fragment.id.clone(),
1633 },
1634 &(),
1635 );
1636 splits_cursor.next();
1637 new_split_tree.push_tree(
1638 splits_cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right, &()),
1639 &(),
1640 );
1641 self.insertion_splits
1642 .insert(fragment.insertion.id, new_split_tree);
1643
1644 new_ropes.push_fragment(&fragment, fragment_was_visible);
1645 new_fragments.push(fragment, &());
1646
1647 // Scan forward until we find a fragment that is not fully contained by the current splice.
1648 fragments_cursor.next();
1649 if let Some(range) = cur_range.clone() {
1650 while let Some(fragment) = fragments_cursor.item() {
1651 let fragment_summary = fragments_cursor.item_summary().unwrap();
1652 let fragment_was_visible = fragment.visible;
1653 fragment_start = *fragments_cursor.start();
1654 fragment_end = fragment_start + fragment.visible_len();
1655 if range.start < fragment_start && range.end >= fragment_end {
1656 let mut new_fragment = fragment.clone();
1657 version_in_range.observe_all(&fragment_summary.max_version);
1658 if new_fragment.visible {
1659 new_fragment.deletions.insert(local_timestamp);
1660 new_fragment.visible = false;
1661 }
1662
1663 new_ropes.push_fragment(&new_fragment, fragment_was_visible);
1664 new_fragments.push(new_fragment, &());
1665 fragments_cursor.next();
1666
1667 if range.end == fragment_end {
1668 end_id = Some(fragment.insertion.id);
1669 end_offset = Some(fragment.range_in_insertion.end);
1670 ops.push(Operation::Edit {
1671 edit: EditOperation {
1672 id: local_timestamp,
1673 start_id: start_id.unwrap(),
1674 start_offset: start_offset.unwrap(),
1675 end_id: end_id.unwrap(),
1676 end_offset: end_offset.unwrap(),
1677 version_in_range,
1678 new_text: new_text.clone(),
1679 },
1680 lamport_timestamp,
1681 });
1682
1683 start_id = None;
1684 start_offset = None;
1685 end_id = None;
1686 end_offset = None;
1687 version_in_range = time::Global::new();
1688
1689 cur_range = old_ranges.next();
1690 if cur_range.is_some() {
1691 local_timestamp = self.local_clock.tick();
1692 lamport_timestamp = self.lamport_clock.tick();
1693 }
1694 break;
1695 }
1696 } else {
1697 break;
1698 }
1699 }
1700
1701 // If the splice we are currently evaluating starts after the end of the fragment
1702 // that the cursor is parked at, we should seek to the next splice's start range
1703 // and push all the fragments in between into the new tree.
1704 if cur_range.as_ref().map_or(false, |r| r.start > fragment_end) {
1705 let slice = fragments_cursor.slice(
1706 &cur_range.as_ref().unwrap().start,
1707 SeekBias::Right,
1708 &(),
1709 );
1710 new_ropes.push_tree(slice.summary().text);
1711 new_fragments.push_tree(slice, &());
1712 }
1713 }
1714 }
1715
1716 // Handle range that is at the end of the buffer if it exists. There should never be
1717 // multiple because ranges must be disjoint.
1718 if cur_range.is_some() {
1719 debug_assert_eq!(old_ranges.next(), None);
1720 let last_fragment = new_fragments.last().unwrap();
1721 ops.push(Operation::Edit {
1722 edit: EditOperation {
1723 id: local_timestamp,
1724 start_id: last_fragment.insertion.id,
1725 start_offset: last_fragment.range_in_insertion.end,
1726 end_id: last_fragment.insertion.id,
1727 end_offset: last_fragment.range_in_insertion.end,
1728 version_in_range: time::Global::new(),
1729 // TODO: avoid cloning the String.
1730 new_text: new_text.clone(),
1731 },
1732 lamport_timestamp,
1733 });
1734
1735 if let Some(new_text) = new_text {
1736 let new_fragment = self.build_fragment_to_insert(
1737 &last_fragment,
1738 None,
1739 &new_text,
1740 local_timestamp,
1741 lamport_timestamp,
1742 );
1743
1744 new_ropes.push_str(&new_text);
1745 new_fragments.push(new_fragment, &());
1746 }
1747 }
1748
1749 new_fragments.push_tree(fragments_cursor.suffix(&()), &());
1750 let (visible_text, deleted_text) = new_ropes.finish();
1751
1752 self.fragments = new_fragments;
1753 self.visible_text = visible_text;
1754 self.deleted_text = deleted_text;
1755 ops
1756 }
1757
1758 fn split_fragment(
1759 &mut self,
1760 prev_fragment: &Fragment,
1761 fragment: &Fragment,
1762 range: Range<usize>,
1763 ) -> (Option<Fragment>, Option<Fragment>, Option<Fragment>) {
1764 debug_assert!(range.start >= fragment.range_in_insertion.start);
1765 debug_assert!(range.start <= fragment.range_in_insertion.end);
1766 debug_assert!(range.end <= fragment.range_in_insertion.end);
1767 debug_assert!(range.end >= fragment.range_in_insertion.start);
1768
1769 if range.end == fragment.range_in_insertion.start {
1770 (None, None, Some(fragment.clone()))
1771 } else if range.start == fragment.range_in_insertion.end {
1772 (Some(fragment.clone()), None, None)
1773 } else if range.start == fragment.range_in_insertion.start
1774 && range.end == fragment.range_in_insertion.end
1775 {
1776 (None, Some(fragment.clone()), None)
1777 } else {
1778 let mut prefix = fragment.clone();
1779
1780 let after_range = if range.end < fragment.range_in_insertion.end {
1781 let mut suffix = prefix.clone();
1782 suffix.range_in_insertion.start = range.end;
1783 prefix.range_in_insertion.end = range.end;
1784 prefix.id = FragmentId::between(&prev_fragment.id, &suffix.id);
1785 Some(suffix)
1786 } else {
1787 None
1788 };
1789
1790 let within_range = if range.start != range.end {
1791 let mut suffix = prefix.clone();
1792 suffix.range_in_insertion.start = range.start;
1793 prefix.range_in_insertion.end = range.start;
1794 prefix.id = FragmentId::between(&prev_fragment.id, &suffix.id);
1795 Some(suffix)
1796 } else {
1797 None
1798 };
1799
1800 let before_range = if range.start > fragment.range_in_insertion.start {
1801 Some(prefix)
1802 } else {
1803 None
1804 };
1805
1806 let old_split_tree = self
1807 .insertion_splits
1808 .remove(&fragment.insertion.id)
1809 .unwrap();
1810 let mut cursor = old_split_tree.cursor::<usize, ()>();
1811 let mut new_split_tree =
1812 cursor.slice(&fragment.range_in_insertion.start, SeekBias::Right, &());
1813
1814 if let Some(ref fragment) = before_range {
1815 new_split_tree.push(
1816 InsertionSplit {
1817 extent: range.start - fragment.range_in_insertion.start,
1818 fragment_id: fragment.id.clone(),
1819 },
1820 &(),
1821 );
1822 }
1823
1824 if let Some(ref fragment) = within_range {
1825 new_split_tree.push(
1826 InsertionSplit {
1827 extent: range.end - range.start,
1828 fragment_id: fragment.id.clone(),
1829 },
1830 &(),
1831 );
1832 }
1833
1834 if let Some(ref fragment) = after_range {
1835 new_split_tree.push(
1836 InsertionSplit {
1837 extent: fragment.range_in_insertion.end - range.end,
1838 fragment_id: fragment.id.clone(),
1839 },
1840 &(),
1841 );
1842 }
1843
1844 cursor.next();
1845 new_split_tree.push_tree(
1846 cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right, &()),
1847 &(),
1848 );
1849
1850 self.insertion_splits
1851 .insert(fragment.insertion.id, new_split_tree);
1852
1853 (before_range, within_range, after_range)
1854 }
1855 }
1856
1857 fn build_fragment_to_insert(
1858 &mut self,
1859 prev_fragment: &Fragment,
1860 next_fragment: Option<&Fragment>,
1861 text: &str,
1862 insertion_id: time::Local,
1863 lamport_timestamp: time::Lamport,
1864 ) -> Fragment {
1865 let new_fragment_id = FragmentId::between(
1866 &prev_fragment.id,
1867 next_fragment
1868 .map(|f| &f.id)
1869 .unwrap_or(&FragmentId::max_value()),
1870 );
1871
1872 let range_in_insertion = 0..text.len();
1873 let mut split_tree = SumTree::new();
1874 split_tree.push(
1875 InsertionSplit {
1876 extent: range_in_insertion.len(),
1877 fragment_id: new_fragment_id.clone(),
1878 },
1879 &(),
1880 );
1881 self.insertion_splits.insert(insertion_id, split_tree);
1882
1883 Fragment::new(
1884 new_fragment_id,
1885 Arc::new(Insertion {
1886 id: insertion_id,
1887 parent_id: prev_fragment.insertion.id,
1888 offset_in_parent: prev_fragment.range_in_insertion.end,
1889 lamport_timestamp,
1890 }),
1891 range_in_insertion,
1892 )
1893 }
1894
1895 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1896 self.anchor_at(position, AnchorBias::Left)
1897 }
1898
1899 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1900 self.anchor_at(position, AnchorBias::Right)
1901 }
1902
1903 pub fn anchor_at<T: ToOffset>(&self, position: T, bias: AnchorBias) -> Anchor {
1904 let offset = position.to_offset(self);
1905 let max_offset = self.len();
1906 assert!(offset <= max_offset, "offset is out of range");
1907
1908 let seek_bias;
1909 match bias {
1910 AnchorBias::Left => {
1911 if offset == 0 {
1912 return Anchor::Start;
1913 } else {
1914 seek_bias = SeekBias::Left;
1915 }
1916 }
1917 AnchorBias::Right => {
1918 if offset == max_offset {
1919 return Anchor::End;
1920 } else {
1921 seek_bias = SeekBias::Right;
1922 }
1923 }
1924 };
1925
1926 let mut cursor = self.fragments.cursor::<usize, usize>();
1927 cursor.seek(&offset, seek_bias, &());
1928 let fragment = cursor.item().unwrap();
1929 let offset_in_fragment = offset - cursor.start();
1930 let offset_in_insertion = fragment.range_in_insertion.start + offset_in_fragment;
1931 let anchor = Anchor::Middle {
1932 insertion_id: fragment.insertion.id,
1933 offset: offset_in_insertion,
1934 bias,
1935 };
1936 anchor
1937 }
1938
1939 fn fragment_id_for_anchor(&self, anchor: &Anchor) -> Result<&FragmentId> {
1940 match anchor {
1941 Anchor::Start => Ok(FragmentId::max_value()),
1942 Anchor::End => Ok(FragmentId::min_value()),
1943 Anchor::Middle {
1944 insertion_id,
1945 offset,
1946 bias,
1947 ..
1948 } => {
1949 let seek_bias = match bias {
1950 AnchorBias::Left => SeekBias::Left,
1951 AnchorBias::Right => SeekBias::Right,
1952 };
1953
1954 let splits = self
1955 .insertion_splits
1956 .get(&insertion_id)
1957 .ok_or_else(|| anyhow!("split does not exist for insertion id"))?;
1958 let mut splits_cursor = splits.cursor::<usize, ()>();
1959 splits_cursor.seek(offset, seek_bias, &());
1960 splits_cursor
1961 .item()
1962 .ok_or_else(|| anyhow!("split offset is out of range"))
1963 .map(|split| &split.fragment_id)
1964 }
1965 }
1966 }
1967
1968 fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
1969 match anchor {
1970 Anchor::Start => TextSummary::default(),
1971 Anchor::End => self.text_summary(),
1972 Anchor::Middle {
1973 insertion_id,
1974 offset,
1975 bias,
1976 } => {
1977 let seek_bias = match bias {
1978 AnchorBias::Left => SeekBias::Left,
1979 AnchorBias::Right => SeekBias::Right,
1980 };
1981
1982 let splits = self
1983 .insertion_splits
1984 .get(&insertion_id)
1985 .expect("split does not exist for insertion id");
1986 let mut splits_cursor = splits.cursor::<usize, ()>();
1987 splits_cursor.seek(offset, seek_bias, &());
1988 let split = splits_cursor.item().expect("split offset is out of range");
1989
1990 let mut fragments_cursor = self.fragments.cursor::<FragmentIdRef, usize>();
1991 fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left, &());
1992 let fragment = fragments_cursor.item().expect("fragment id does not exist");
1993
1994 let mut ix = *fragments_cursor.start();
1995 if fragment.visible {
1996 ix += offset - fragment.range_in_insertion.start;
1997 }
1998 self.text_summary_for_range(0..ix)
1999 }
2000 }
2001 }
2002
2003 pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
2004 if offset <= self.len() {
2005 Ok(self.text_summary_for_range(0..offset).lines)
2006 } else {
2007 Err(anyhow!("offset out of bounds"))
2008 }
2009 }
2010
2011 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2012 self.visible_text.clip_point(point, bias)
2013 }
2014
2015 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2016 self.visible_text.clip_offset(offset, bias)
2017 }
2018}
2019
2020impl Clone for Buffer {
2021 fn clone(&self) -> Self {
2022 Self {
2023 fragments: self.fragments.clone(),
2024 visible_text: self.visible_text.clone(),
2025 deleted_text: self.deleted_text.clone(),
2026 insertion_splits: self.insertion_splits.clone(),
2027 version: self.version.clone(),
2028 saved_version: self.saved_version.clone(),
2029 saved_mtime: self.saved_mtime,
2030 last_edit: self.last_edit.clone(),
2031 undo_map: self.undo_map.clone(),
2032 history: self.history.clone(),
2033 selections: self.selections.clone(),
2034 selections_last_update: self.selections_last_update.clone(),
2035 deferred_ops: self.deferred_ops.clone(),
2036 file: self.file.clone(),
2037 language: self.language.clone(),
2038 syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
2039 is_parsing: false,
2040 deferred_replicas: self.deferred_replicas.clone(),
2041 replica_id: self.replica_id,
2042 local_clock: self.local_clock.clone(),
2043 lamport_clock: self.lamport_clock.clone(),
2044 }
2045 }
2046}
2047
2048pub struct Snapshot {
2049 text: Rope,
2050 tree: Option<Tree>,
2051 language: Option<Arc<Language>>,
2052 query_cursor: Option<QueryCursor>,
2053}
2054
2055impl Snapshot {
2056 pub fn len(&self) -> usize {
2057 self.text.len()
2058 }
2059
2060 pub fn text(&self) -> Rope {
2061 self.text.clone()
2062 }
2063
2064 pub fn text_for_range(&self, range: Range<usize>) -> Chunks {
2065 self.text.chunks_in_range(range)
2066 }
2067
2068 pub fn highlighted_text_for_range(&mut self, range: Range<usize>) -> HighlightedChunks {
2069 let chunks = self.text.chunks_in_range(range.clone());
2070 if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
2071 let query_cursor = self.query_cursor.as_mut().unwrap();
2072 query_cursor.set_byte_range(range.start, range.end);
2073 let captures = query_cursor.captures(
2074 &language.highlight_query,
2075 tree.root_node(),
2076 TextProvider(&self.text),
2077 );
2078
2079 HighlightedChunks {
2080 range,
2081 chunks,
2082 highlights: Some(Highlights {
2083 captures,
2084 next_capture: None,
2085 stack: Default::default(),
2086 theme_mapping: language.theme_mapping(),
2087 }),
2088 }
2089 } else {
2090 HighlightedChunks {
2091 range,
2092 chunks,
2093 highlights: None,
2094 }
2095 }
2096 }
2097
2098 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2099 self.text.clip_offset(offset, bias)
2100 }
2101
2102 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2103 self.text.clip_point(point, bias)
2104 }
2105
2106 pub fn to_offset(&self, point: Point) -> usize {
2107 self.text.to_offset(point)
2108 }
2109
2110 pub fn to_point(&self, offset: usize) -> Point {
2111 self.text.to_point(offset)
2112 }
2113}
2114
2115impl Drop for Snapshot {
2116 fn drop(&mut self) {
2117 QUERY_CURSORS.lock().push(self.query_cursor.take().unwrap());
2118 }
2119}
2120
2121struct RopeBuilder<'a> {
2122 old_visible_cursor: rope::Cursor<'a>,
2123 old_deleted_cursor: rope::Cursor<'a>,
2124 new_visible: Rope,
2125 new_deleted: Rope,
2126}
2127
2128impl<'a> RopeBuilder<'a> {
2129 fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self {
2130 Self {
2131 old_visible_cursor,
2132 old_deleted_cursor,
2133 new_visible: Rope::new(),
2134 new_deleted: Rope::new(),
2135 }
2136 }
2137
2138 fn push_tree(&mut self, len: FragmentTextSummary) {
2139 self.push(len.visible, true, true);
2140 self.push(len.deleted, false, false);
2141 }
2142
2143 fn push_fragment(&mut self, fragment: &Fragment, was_visible: bool) {
2144 self.push(fragment.len(), was_visible, fragment.visible)
2145 }
2146
2147 fn push(&mut self, len: usize, was_visible: bool, is_visible: bool) {
2148 let text = if was_visible {
2149 self.old_visible_cursor
2150 .slice(self.old_visible_cursor.offset() + len)
2151 } else {
2152 self.old_deleted_cursor
2153 .slice(self.old_deleted_cursor.offset() + len)
2154 };
2155 if is_visible {
2156 self.new_visible.append(text);
2157 } else {
2158 self.new_deleted.append(text);
2159 }
2160 }
2161
2162 fn push_str(&mut self, text: &str) {
2163 self.new_visible.push(text);
2164 }
2165
2166 fn finish(mut self) -> (Rope, Rope) {
2167 self.new_visible.append(self.old_visible_cursor.suffix());
2168 self.new_deleted.append(self.old_deleted_cursor.suffix());
2169 (self.new_visible, self.new_deleted)
2170 }
2171}
2172
2173#[derive(Clone, Debug, Eq, PartialEq)]
2174pub enum Event {
2175 Edited,
2176 Dirtied,
2177 Saved,
2178 FileHandleChanged,
2179 Reloaded,
2180 Reparsed,
2181}
2182
2183impl Entity for Buffer {
2184 type Event = Event;
2185}
2186
2187impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
2188 type Item = Edit;
2189
2190 fn next(&mut self) -> Option<Self::Item> {
2191 let mut change: Option<Edit> = None;
2192
2193 while let Some(fragment) = self.cursor.item() {
2194 let new_offset = self.cursor.start().visible;
2195 let old_offset = (new_offset as isize - self.delta) as usize;
2196
2197 if !fragment.was_visible(&self.since, &self.undos) && fragment.visible {
2198 if let Some(ref mut change) = change {
2199 if change.new_range.end == new_offset {
2200 change.new_range.end += fragment.len();
2201 self.delta += fragment.len() as isize;
2202 } else {
2203 break;
2204 }
2205 } else {
2206 change = Some(Edit {
2207 old_range: old_offset..old_offset,
2208 new_range: new_offset..new_offset + fragment.len(),
2209 old_lines: Point::zero(),
2210 });
2211 self.delta += fragment.len() as isize;
2212 }
2213 } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible {
2214 let deleted_start = self.cursor.start().deleted;
2215 let old_lines = self.deleted_text.to_point(deleted_start + fragment.len())
2216 - self.deleted_text.to_point(deleted_start);
2217 if let Some(ref mut change) = change {
2218 if change.new_range.end == new_offset {
2219 change.old_range.end += fragment.len();
2220 change.old_lines += &old_lines;
2221 self.delta -= fragment.len() as isize;
2222 } else {
2223 break;
2224 }
2225 } else {
2226 change = Some(Edit {
2227 old_range: old_offset..old_offset + fragment.len(),
2228 new_range: new_offset..new_offset,
2229 old_lines,
2230 });
2231 self.delta -= fragment.len() as isize;
2232 }
2233 }
2234
2235 self.cursor.next();
2236 }
2237
2238 change
2239 }
2240}
2241
2242struct ByteChunks<'a>(rope::Chunks<'a>);
2243
2244impl<'a> Iterator for ByteChunks<'a> {
2245 type Item = &'a [u8];
2246
2247 fn next(&mut self) -> Option<Self::Item> {
2248 self.0.next().map(str::as_bytes)
2249 }
2250}
2251
2252struct TextProvider<'a>(&'a Rope);
2253
2254impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
2255 type I = ByteChunks<'a>;
2256
2257 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
2258 ByteChunks(self.0.chunks_in_range(node.byte_range()))
2259 }
2260}
2261
2262struct Highlights<'a> {
2263 captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
2264 next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
2265 stack: Vec<(usize, StyleId)>,
2266 theme_mapping: ThemeMap,
2267}
2268
2269pub struct HighlightedChunks<'a> {
2270 range: Range<usize>,
2271 chunks: Chunks<'a>,
2272 highlights: Option<Highlights<'a>>,
2273}
2274
2275impl<'a> HighlightedChunks<'a> {
2276 pub fn seek(&mut self, offset: usize) {
2277 self.range.start = offset;
2278 self.chunks.seek(self.range.start);
2279 if let Some(highlights) = self.highlights.as_mut() {
2280 highlights.stack.clear();
2281 highlights.next_capture.take();
2282 highlights.captures.advance_to_byte(self.range.start);
2283 }
2284 }
2285
2286 pub fn offset(&self) -> usize {
2287 self.range.start
2288 }
2289}
2290
2291impl<'a> Iterator for HighlightedChunks<'a> {
2292 type Item = (&'a str, StyleId);
2293
2294 fn next(&mut self) -> Option<Self::Item> {
2295 let mut next_capture_start = usize::MAX;
2296
2297 if let Some(highlights) = self.highlights.as_mut() {
2298 while let Some((parent_capture_end, _)) = highlights.stack.last() {
2299 if *parent_capture_end <= self.range.start {
2300 highlights.stack.pop();
2301 } else {
2302 break;
2303 }
2304 }
2305
2306 if highlights.next_capture.is_none() {
2307 highlights.next_capture = highlights.captures.next();
2308 }
2309
2310 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
2311 let capture = mat.captures[*capture_ix as usize];
2312 if self.range.start < capture.node.start_byte() {
2313 next_capture_start = capture.node.start_byte();
2314 break;
2315 } else {
2316 let style_id = highlights.theme_mapping.get(capture.index);
2317 highlights.stack.push((capture.node.end_byte(), style_id));
2318 highlights.next_capture = highlights.captures.next();
2319 }
2320 }
2321 }
2322
2323 if let Some(chunk) = self.chunks.peek() {
2324 let chunk_start = self.range.start;
2325 let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
2326 let mut capture_ix = StyleId::default();
2327 if let Some((parent_capture_end, parent_style_id)) =
2328 self.highlights.as_ref().and_then(|h| h.stack.last())
2329 {
2330 chunk_end = chunk_end.min(*parent_capture_end);
2331 capture_ix = *parent_style_id;
2332 }
2333
2334 let slice =
2335 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2336 self.range.start = chunk_end;
2337 if self.range.start == self.chunks.offset() + chunk.len() {
2338 self.chunks.next().unwrap();
2339 }
2340
2341 Some((slice, capture_ix))
2342 } else {
2343 None
2344 }
2345 }
2346}
2347
2348#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
2349struct FragmentId(Arc<[u16]>);
2350
2351lazy_static! {
2352 static ref FRAGMENT_ID_EMPTY: FragmentId = FragmentId(Arc::from([]));
2353 static ref FRAGMENT_ID_MIN_VALUE: FragmentId = FragmentId(Arc::from([0 as u16]));
2354 static ref FRAGMENT_ID_MAX_VALUE: FragmentId = FragmentId(Arc::from([u16::max_value()]));
2355}
2356
2357impl Default for FragmentId {
2358 fn default() -> Self {
2359 FRAGMENT_ID_EMPTY.clone()
2360 }
2361}
2362
2363impl FragmentId {
2364 fn min_value() -> &'static Self {
2365 &FRAGMENT_ID_MIN_VALUE
2366 }
2367
2368 fn max_value() -> &'static Self {
2369 &FRAGMENT_ID_MAX_VALUE
2370 }
2371
2372 fn between(left: &Self, right: &Self) -> Self {
2373 Self::between_with_max(left, right, u16::max_value())
2374 }
2375
2376 fn between_with_max(left: &Self, right: &Self, max_value: u16) -> Self {
2377 let mut new_entries = Vec::new();
2378
2379 let left_entries = left.0.iter().cloned().chain(iter::repeat(0));
2380 let right_entries = right.0.iter().cloned().chain(iter::repeat(max_value));
2381 for (l, r) in left_entries.zip(right_entries) {
2382 let interval = r - l;
2383 if interval > 1 {
2384 new_entries.push(l + cmp::max(1, cmp::min(8, interval / 2)));
2385 break;
2386 } else {
2387 new_entries.push(l);
2388 }
2389 }
2390
2391 FragmentId(Arc::from(new_entries))
2392 }
2393}
2394
2395#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug, Default)]
2396struct FragmentIdRef<'a>(Option<&'a FragmentId>);
2397
2398impl<'a> FragmentIdRef<'a> {
2399 fn new(id: &'a FragmentId) -> Self {
2400 Self(Some(id))
2401 }
2402}
2403
2404impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentIdRef<'a> {
2405 fn add_summary(&mut self, summary: &'a FragmentSummary) {
2406 self.0 = Some(&summary.max_fragment_id)
2407 }
2408}
2409
2410impl Fragment {
2411 fn new(id: FragmentId, insertion: Arc<Insertion>, range_in_insertion: Range<usize>) -> Self {
2412 Self {
2413 id,
2414 insertion,
2415 range_in_insertion,
2416 deletions: Default::default(),
2417 max_undos: Default::default(),
2418 visible: true,
2419 }
2420 }
2421
2422 fn is_visible(&self, undos: &UndoMap) -> bool {
2423 !undos.is_undone(self.insertion.id) && self.deletions.iter().all(|d| undos.is_undone(*d))
2424 }
2425
2426 fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool {
2427 (version.observed(self.insertion.id) && !undos.was_undone(self.insertion.id, version))
2428 && self
2429 .deletions
2430 .iter()
2431 .all(|d| !version.observed(*d) || undos.was_undone(*d, version))
2432 }
2433
2434 fn len(&self) -> usize {
2435 self.range_in_insertion.len()
2436 }
2437
2438 fn visible_len(&self) -> usize {
2439 if self.visible {
2440 self.range_in_insertion.len()
2441 } else {
2442 0
2443 }
2444 }
2445}
2446
2447impl sum_tree::Item for Fragment {
2448 type Summary = FragmentSummary;
2449
2450 fn summary(&self) -> Self::Summary {
2451 let mut max_version = time::Global::new();
2452 max_version.observe(self.insertion.id);
2453 for deletion in &self.deletions {
2454 max_version.observe(*deletion);
2455 }
2456 max_version.observe_all(&self.max_undos);
2457
2458 if self.visible {
2459 FragmentSummary {
2460 text: FragmentTextSummary {
2461 visible: self.len(),
2462 deleted: 0,
2463 },
2464 max_fragment_id: self.id.clone(),
2465 max_version,
2466 }
2467 } else {
2468 FragmentSummary {
2469 text: FragmentTextSummary {
2470 visible: 0,
2471 deleted: self.len(),
2472 },
2473 max_fragment_id: self.id.clone(),
2474 max_version,
2475 }
2476 }
2477 }
2478}
2479
2480impl sum_tree::Summary for FragmentSummary {
2481 type Context = ();
2482
2483 fn add_summary(&mut self, other: &Self, _: &Self::Context) {
2484 self.text.visible += &other.text.visible;
2485 self.text.deleted += &other.text.deleted;
2486 debug_assert!(self.max_fragment_id <= other.max_fragment_id);
2487 self.max_fragment_id = other.max_fragment_id.clone();
2488 self.max_version.observe_all(&other.max_version);
2489 }
2490}
2491
2492impl Default for FragmentSummary {
2493 fn default() -> Self {
2494 FragmentSummary {
2495 text: FragmentTextSummary::default(),
2496 max_fragment_id: FragmentId::min_value().clone(),
2497 max_version: time::Global::new(),
2498 }
2499 }
2500}
2501
2502impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
2503 fn add_summary(&mut self, summary: &FragmentSummary) {
2504 *self += summary.text.visible;
2505 }
2506}
2507
2508impl sum_tree::Item for InsertionSplit {
2509 type Summary = InsertionSplitSummary;
2510
2511 fn summary(&self) -> Self::Summary {
2512 InsertionSplitSummary {
2513 extent: self.extent,
2514 }
2515 }
2516}
2517
2518impl sum_tree::Summary for InsertionSplitSummary {
2519 type Context = ();
2520
2521 fn add_summary(&mut self, other: &Self, _: &()) {
2522 self.extent += other.extent;
2523 }
2524}
2525
2526impl Default for InsertionSplitSummary {
2527 fn default() -> Self {
2528 InsertionSplitSummary { extent: 0 }
2529 }
2530}
2531
2532impl<'a> sum_tree::Dimension<'a, InsertionSplitSummary> for usize {
2533 fn add_summary(&mut self, summary: &InsertionSplitSummary) {
2534 *self += summary.extent;
2535 }
2536}
2537
2538impl Operation {
2539 fn replica_id(&self) -> ReplicaId {
2540 self.lamport_timestamp().replica_id
2541 }
2542
2543 fn lamport_timestamp(&self) -> time::Lamport {
2544 match self {
2545 Operation::Edit {
2546 lamport_timestamp, ..
2547 } => *lamport_timestamp,
2548 Operation::Undo {
2549 lamport_timestamp, ..
2550 } => *lamport_timestamp,
2551 Operation::UpdateSelections {
2552 lamport_timestamp, ..
2553 } => *lamport_timestamp,
2554 }
2555 }
2556
2557 pub fn is_edit(&self) -> bool {
2558 match self {
2559 Operation::Edit { .. } => true,
2560 _ => false,
2561 }
2562 }
2563}
2564
2565impl operation_queue::Operation for Operation {
2566 fn timestamp(&self) -> time::Lamport {
2567 self.lamport_timestamp()
2568 }
2569}
2570
2571pub trait ToOffset {
2572 fn to_offset(&self, buffer: &Buffer) -> usize;
2573}
2574
2575impl ToOffset for Point {
2576 fn to_offset(&self, buffer: &Buffer) -> usize {
2577 buffer.visible_text.to_offset(*self)
2578 }
2579}
2580
2581impl ToOffset for usize {
2582 fn to_offset(&self, _: &Buffer) -> usize {
2583 *self
2584 }
2585}
2586
2587impl ToOffset for Anchor {
2588 fn to_offset(&self, buffer: &Buffer) -> usize {
2589 buffer.summary_for_anchor(self).bytes
2590 }
2591}
2592
2593impl<'a> ToOffset for &'a Anchor {
2594 fn to_offset(&self, buffer: &Buffer) -> usize {
2595 buffer.summary_for_anchor(self).bytes
2596 }
2597}
2598
2599pub trait ToPoint {
2600 fn to_point(&self, buffer: &Buffer) -> Point;
2601}
2602
2603impl ToPoint for Anchor {
2604 fn to_point(&self, buffer: &Buffer) -> Point {
2605 buffer.summary_for_anchor(self).lines
2606 }
2607}
2608
2609impl ToPoint for usize {
2610 fn to_point(&self, buffer: &Buffer) -> Point {
2611 buffer.visible_text.to_point(*self)
2612 }
2613}
2614
2615#[cfg(test)]
2616mod tests {
2617 use super::*;
2618 use crate::{
2619 test::{build_app_state, temp_tree},
2620 util::RandomCharIter,
2621 worktree::{Worktree, WorktreeHandle},
2622 };
2623 use gpui::{App, ModelHandle};
2624 use rand::prelude::*;
2625 use serde_json::json;
2626 use std::{
2627 cell::RefCell,
2628 cmp::Ordering,
2629 fs,
2630 rc::Rc,
2631 sync::atomic::{self, AtomicUsize},
2632 };
2633
2634 #[gpui::test]
2635 fn test_edit(ctx: &mut gpui::MutableAppContext) {
2636 ctx.add_model(|ctx| {
2637 let mut buffer = Buffer::new(0, "abc", ctx);
2638 assert_eq!(buffer.text(), "abc");
2639 buffer.edit(vec![3..3], "def", None).unwrap();
2640 assert_eq!(buffer.text(), "abcdef");
2641 buffer.edit(vec![0..0], "ghi", None).unwrap();
2642 assert_eq!(buffer.text(), "ghiabcdef");
2643 buffer.edit(vec![5..5], "jkl", None).unwrap();
2644 assert_eq!(buffer.text(), "ghiabjklcdef");
2645 buffer.edit(vec![6..7], "", None).unwrap();
2646 assert_eq!(buffer.text(), "ghiabjlcdef");
2647 buffer.edit(vec![4..9], "mno", None).unwrap();
2648 assert_eq!(buffer.text(), "ghiamnoef");
2649 buffer
2650 });
2651 }
2652
2653 #[gpui::test]
2654 fn test_edit_events(app: &mut gpui::MutableAppContext) {
2655 let mut now = Instant::now();
2656 let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
2657 let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
2658
2659 let buffer1 = app.add_model(|ctx| Buffer::new(0, "abcdef", ctx));
2660 let buffer2 = app.add_model(|ctx| Buffer::new(1, "abcdef", ctx));
2661 let mut buffer_ops = Vec::new();
2662 buffer1.update(app, |buffer, ctx| {
2663 let buffer_1_events = buffer_1_events.clone();
2664 ctx.subscribe(&buffer1, move |_, event, _| {
2665 buffer_1_events.borrow_mut().push(event.clone())
2666 });
2667 let buffer_2_events = buffer_2_events.clone();
2668 ctx.subscribe(&buffer2, move |_, event, _| {
2669 buffer_2_events.borrow_mut().push(event.clone())
2670 });
2671
2672 // An edit emits an edited event, followed by a dirtied event,
2673 // since the buffer was previously in a clean state.
2674 let ops = buffer.edit(Some(2..4), "XYZ", Some(ctx)).unwrap();
2675 buffer_ops.extend_from_slice(&ops);
2676
2677 // An empty transaction does not emit any events.
2678 buffer.start_transaction(None).unwrap();
2679 buffer.end_transaction(None, Some(ctx)).unwrap();
2680
2681 // A transaction containing two edits emits one edited event.
2682 now += Duration::from_secs(1);
2683 buffer.start_transaction_at(None, now).unwrap();
2684 let ops = buffer.edit(Some(5..5), "u", Some(ctx)).unwrap();
2685 buffer_ops.extend_from_slice(&ops);
2686 let ops = buffer.edit(Some(6..6), "w", Some(ctx)).unwrap();
2687 buffer_ops.extend_from_slice(&ops);
2688 buffer.end_transaction_at(None, now, Some(ctx)).unwrap();
2689
2690 // Undoing a transaction emits one edited event.
2691 let ops = buffer.undo(Some(ctx));
2692 buffer_ops.extend_from_slice(&ops);
2693 });
2694
2695 // Incorporating a set of remote ops emits a single edited event,
2696 // followed by a dirtied event.
2697 buffer2.update(app, |buffer, ctx| {
2698 buffer.apply_ops(buffer_ops, Some(ctx)).unwrap();
2699 });
2700
2701 let buffer_1_events = buffer_1_events.borrow();
2702 assert_eq!(
2703 *buffer_1_events,
2704 vec![Event::Edited, Event::Dirtied, Event::Edited, Event::Edited]
2705 );
2706
2707 let buffer_2_events = buffer_2_events.borrow();
2708 assert_eq!(*buffer_2_events, vec![Event::Edited, Event::Dirtied]);
2709 }
2710
2711 #[gpui::test]
2712 fn test_random_edits(ctx: &mut gpui::MutableAppContext) {
2713 for seed in 0..100 {
2714 println!("{:?}", seed);
2715 let mut rng = &mut StdRng::seed_from_u64(seed);
2716
2717 let reference_string_len = rng.gen_range(0..3);
2718 let mut reference_string = RandomCharIter::new(&mut rng)
2719 .take(reference_string_len)
2720 .collect::<String>();
2721 ctx.add_model(|ctx| {
2722 let mut buffer = Buffer::new(0, reference_string.as_str(), ctx);
2723 let mut buffer_versions = Vec::new();
2724 for _i in 0..10 {
2725 let (old_ranges, new_text, _) = buffer.randomly_mutate(rng, None);
2726 for old_range in old_ranges.iter().rev() {
2727 reference_string.replace_range(old_range.clone(), &new_text);
2728 }
2729 assert_eq!(buffer.text(), reference_string);
2730
2731 if rng.gen_bool(0.25) {
2732 buffer.randomly_undo_redo(rng);
2733 reference_string = buffer.text();
2734 }
2735
2736 let range = buffer.random_byte_range(0, rng);
2737 assert_eq!(
2738 buffer.text_summary_for_range(range.clone()),
2739 TextSummary::from(&reference_string[range])
2740 );
2741
2742 if rng.gen_bool(0.3) {
2743 buffer_versions.push(buffer.clone());
2744 }
2745 }
2746
2747 for mut old_buffer in buffer_versions {
2748 let mut delta = 0_isize;
2749 for Edit {
2750 old_range,
2751 new_range,
2752 ..
2753 } in buffer.edits_since(old_buffer.version.clone())
2754 {
2755 let old_len = old_range.end - old_range.start;
2756 let new_len = new_range.end - new_range.start;
2757 let old_start = (old_range.start as isize + delta) as usize;
2758 let new_text: String = buffer.text_for_range(new_range).collect();
2759 old_buffer
2760 .edit(Some(old_start..old_start + old_len), new_text, None)
2761 .unwrap();
2762
2763 delta += new_len as isize - old_len as isize;
2764 }
2765 assert_eq!(old_buffer.text(), buffer.text());
2766 }
2767
2768 buffer
2769 });
2770 }
2771 }
2772
2773 #[gpui::test]
2774 fn test_line_len(ctx: &mut gpui::MutableAppContext) {
2775 ctx.add_model(|ctx| {
2776 let mut buffer = Buffer::new(0, "", ctx);
2777 buffer.edit(vec![0..0], "abcd\nefg\nhij", None).unwrap();
2778 buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
2779 buffer.edit(vec![18..18], "\npqrs\n", None).unwrap();
2780 buffer.edit(vec![18..21], "\nPQ", None).unwrap();
2781
2782 assert_eq!(buffer.line_len(0), 4);
2783 assert_eq!(buffer.line_len(1), 3);
2784 assert_eq!(buffer.line_len(2), 5);
2785 assert_eq!(buffer.line_len(3), 3);
2786 assert_eq!(buffer.line_len(4), 4);
2787 assert_eq!(buffer.line_len(5), 0);
2788 buffer
2789 });
2790 }
2791
2792 #[gpui::test]
2793 fn test_text_summary_for_range(ctx: &mut gpui::MutableAppContext) {
2794 ctx.add_model(|ctx| {
2795 let buffer = Buffer::new(0, "ab\nefg\nhklm\nnopqrs\ntuvwxyz", ctx);
2796 assert_eq!(
2797 buffer.text_summary_for_range(1..3),
2798 TextSummary {
2799 bytes: 2,
2800 lines: Point::new(1, 0),
2801 first_line_chars: 1,
2802 last_line_chars: 0,
2803 longest_row: 0,
2804 longest_row_chars: 1,
2805 }
2806 );
2807 assert_eq!(
2808 buffer.text_summary_for_range(1..12),
2809 TextSummary {
2810 bytes: 11,
2811 lines: Point::new(3, 0),
2812 first_line_chars: 1,
2813 last_line_chars: 0,
2814 longest_row: 2,
2815 longest_row_chars: 4,
2816 }
2817 );
2818 assert_eq!(
2819 buffer.text_summary_for_range(0..20),
2820 TextSummary {
2821 bytes: 20,
2822 lines: Point::new(4, 1),
2823 first_line_chars: 2,
2824 last_line_chars: 1,
2825 longest_row: 3,
2826 longest_row_chars: 6,
2827 }
2828 );
2829 assert_eq!(
2830 buffer.text_summary_for_range(0..22),
2831 TextSummary {
2832 bytes: 22,
2833 lines: Point::new(4, 3),
2834 first_line_chars: 2,
2835 last_line_chars: 3,
2836 longest_row: 3,
2837 longest_row_chars: 6,
2838 }
2839 );
2840 assert_eq!(
2841 buffer.text_summary_for_range(7..22),
2842 TextSummary {
2843 bytes: 15,
2844 lines: Point::new(2, 3),
2845 first_line_chars: 4,
2846 last_line_chars: 3,
2847 longest_row: 1,
2848 longest_row_chars: 6,
2849 }
2850 );
2851 buffer
2852 });
2853 }
2854
2855 #[gpui::test]
2856 fn test_chars_at(ctx: &mut gpui::MutableAppContext) {
2857 ctx.add_model(|ctx| {
2858 let mut buffer = Buffer::new(0, "", ctx);
2859 buffer.edit(vec![0..0], "abcd\nefgh\nij", None).unwrap();
2860 buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
2861 buffer.edit(vec![18..18], "\npqrs", None).unwrap();
2862 buffer.edit(vec![18..21], "\nPQ", None).unwrap();
2863
2864 let chars = buffer.chars_at(Point::new(0, 0));
2865 assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
2866
2867 let chars = buffer.chars_at(Point::new(1, 0));
2868 assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
2869
2870 let chars = buffer.chars_at(Point::new(2, 0));
2871 assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
2872
2873 let chars = buffer.chars_at(Point::new(3, 0));
2874 assert_eq!(chars.collect::<String>(), "mno\nPQrs");
2875
2876 let chars = buffer.chars_at(Point::new(4, 0));
2877 assert_eq!(chars.collect::<String>(), "PQrs");
2878
2879 // Regression test:
2880 let mut buffer = Buffer::new(0, "", ctx);
2881 buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", None).unwrap();
2882 buffer.edit(vec![60..60], "\n", None).unwrap();
2883
2884 let chars = buffer.chars_at(Point::new(6, 0));
2885 assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
2886
2887 buffer
2888 });
2889 }
2890
2891 #[test]
2892 fn test_fragment_ids() {
2893 for seed in 0..10 {
2894 let rng = &mut StdRng::seed_from_u64(seed);
2895
2896 let mut ids = vec![FragmentId(Arc::from([0])), FragmentId(Arc::from([4]))];
2897 for _i in 0..100 {
2898 let index = rng.gen_range(1..ids.len());
2899
2900 let left = ids[index - 1].clone();
2901 let right = ids[index].clone();
2902 ids.insert(index, FragmentId::between_with_max(&left, &right, 4));
2903
2904 let mut sorted_ids = ids.clone();
2905 sorted_ids.sort();
2906 assert_eq!(ids, sorted_ids);
2907 }
2908 }
2909 }
2910
2911 #[gpui::test]
2912 fn test_anchors(ctx: &mut gpui::MutableAppContext) {
2913 ctx.add_model(|ctx| {
2914 let mut buffer = Buffer::new(0, "", ctx);
2915 buffer.edit(vec![0..0], "abc", None).unwrap();
2916 let left_anchor = buffer.anchor_before(2);
2917 let right_anchor = buffer.anchor_after(2);
2918
2919 buffer.edit(vec![1..1], "def\n", None).unwrap();
2920 assert_eq!(buffer.text(), "adef\nbc");
2921 assert_eq!(left_anchor.to_offset(&buffer), 6);
2922 assert_eq!(right_anchor.to_offset(&buffer), 6);
2923 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2924 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2925
2926 buffer.edit(vec![2..3], "", None).unwrap();
2927 assert_eq!(buffer.text(), "adf\nbc");
2928 assert_eq!(left_anchor.to_offset(&buffer), 5);
2929 assert_eq!(right_anchor.to_offset(&buffer), 5);
2930 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2931 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2932
2933 buffer.edit(vec![5..5], "ghi\n", None).unwrap();
2934 assert_eq!(buffer.text(), "adf\nbghi\nc");
2935 assert_eq!(left_anchor.to_offset(&buffer), 5);
2936 assert_eq!(right_anchor.to_offset(&buffer), 9);
2937 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2938 assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
2939
2940 buffer.edit(vec![7..9], "", None).unwrap();
2941 assert_eq!(buffer.text(), "adf\nbghc");
2942 assert_eq!(left_anchor.to_offset(&buffer), 5);
2943 assert_eq!(right_anchor.to_offset(&buffer), 7);
2944 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 },);
2945 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 3 });
2946
2947 // Ensure anchoring to a point is equivalent to anchoring to an offset.
2948 assert_eq!(
2949 buffer.anchor_before(Point { row: 0, column: 0 }),
2950 buffer.anchor_before(0)
2951 );
2952 assert_eq!(
2953 buffer.anchor_before(Point { row: 0, column: 1 }),
2954 buffer.anchor_before(1)
2955 );
2956 assert_eq!(
2957 buffer.anchor_before(Point { row: 0, column: 2 }),
2958 buffer.anchor_before(2)
2959 );
2960 assert_eq!(
2961 buffer.anchor_before(Point { row: 0, column: 3 }),
2962 buffer.anchor_before(3)
2963 );
2964 assert_eq!(
2965 buffer.anchor_before(Point { row: 1, column: 0 }),
2966 buffer.anchor_before(4)
2967 );
2968 assert_eq!(
2969 buffer.anchor_before(Point { row: 1, column: 1 }),
2970 buffer.anchor_before(5)
2971 );
2972 assert_eq!(
2973 buffer.anchor_before(Point { row: 1, column: 2 }),
2974 buffer.anchor_before(6)
2975 );
2976 assert_eq!(
2977 buffer.anchor_before(Point { row: 1, column: 3 }),
2978 buffer.anchor_before(7)
2979 );
2980 assert_eq!(
2981 buffer.anchor_before(Point { row: 1, column: 4 }),
2982 buffer.anchor_before(8)
2983 );
2984
2985 // Comparison between anchors.
2986 let anchor_at_offset_0 = buffer.anchor_before(0);
2987 let anchor_at_offset_1 = buffer.anchor_before(1);
2988 let anchor_at_offset_2 = buffer.anchor_before(2);
2989
2990 assert_eq!(
2991 anchor_at_offset_0
2992 .cmp(&anchor_at_offset_0, &buffer)
2993 .unwrap(),
2994 Ordering::Equal
2995 );
2996 assert_eq!(
2997 anchor_at_offset_1
2998 .cmp(&anchor_at_offset_1, &buffer)
2999 .unwrap(),
3000 Ordering::Equal
3001 );
3002 assert_eq!(
3003 anchor_at_offset_2
3004 .cmp(&anchor_at_offset_2, &buffer)
3005 .unwrap(),
3006 Ordering::Equal
3007 );
3008
3009 assert_eq!(
3010 anchor_at_offset_0
3011 .cmp(&anchor_at_offset_1, &buffer)
3012 .unwrap(),
3013 Ordering::Less
3014 );
3015 assert_eq!(
3016 anchor_at_offset_1
3017 .cmp(&anchor_at_offset_2, &buffer)
3018 .unwrap(),
3019 Ordering::Less
3020 );
3021 assert_eq!(
3022 anchor_at_offset_0
3023 .cmp(&anchor_at_offset_2, &buffer)
3024 .unwrap(),
3025 Ordering::Less
3026 );
3027
3028 assert_eq!(
3029 anchor_at_offset_1
3030 .cmp(&anchor_at_offset_0, &buffer)
3031 .unwrap(),
3032 Ordering::Greater
3033 );
3034 assert_eq!(
3035 anchor_at_offset_2
3036 .cmp(&anchor_at_offset_1, &buffer)
3037 .unwrap(),
3038 Ordering::Greater
3039 );
3040 assert_eq!(
3041 anchor_at_offset_2
3042 .cmp(&anchor_at_offset_0, &buffer)
3043 .unwrap(),
3044 Ordering::Greater
3045 );
3046 buffer
3047 });
3048 }
3049
3050 #[gpui::test]
3051 fn test_anchors_at_start_and_end(ctx: &mut gpui::MutableAppContext) {
3052 ctx.add_model(|ctx| {
3053 let mut buffer = Buffer::new(0, "", ctx);
3054 let before_start_anchor = buffer.anchor_before(0);
3055 let after_end_anchor = buffer.anchor_after(0);
3056
3057 buffer.edit(vec![0..0], "abc", None).unwrap();
3058 assert_eq!(buffer.text(), "abc");
3059 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
3060 assert_eq!(after_end_anchor.to_offset(&buffer), 3);
3061
3062 let after_start_anchor = buffer.anchor_after(0);
3063 let before_end_anchor = buffer.anchor_before(3);
3064
3065 buffer.edit(vec![3..3], "def", None).unwrap();
3066 buffer.edit(vec![0..0], "ghi", None).unwrap();
3067 assert_eq!(buffer.text(), "ghiabcdef");
3068 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
3069 assert_eq!(after_start_anchor.to_offset(&buffer), 3);
3070 assert_eq!(before_end_anchor.to_offset(&buffer), 6);
3071 assert_eq!(after_end_anchor.to_offset(&buffer), 9);
3072 buffer
3073 });
3074 }
3075
3076 #[test]
3077 fn test_is_dirty() {
3078 App::test_async((), |mut app| async move {
3079 let dir = temp_tree(json!({
3080 "file1": "",
3081 "file2": "",
3082 "file3": "",
3083 }));
3084 let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
3085 tree.flush_fs_events(&app).await;
3086 app.read(|ctx| tree.read(ctx).scan_complete()).await;
3087
3088 let file1 = app.update(|ctx| tree.file("file1", ctx)).await;
3089 let buffer1 = app.add_model(|ctx| {
3090 Buffer::from_history(0, History::new("abc".into()), Some(file1), None, ctx)
3091 });
3092 let events = Rc::new(RefCell::new(Vec::new()));
3093
3094 // initially, the buffer isn't dirty.
3095 buffer1.update(&mut app, |buffer, ctx| {
3096 ctx.subscribe(&buffer1, {
3097 let events = events.clone();
3098 move |_, event, _| events.borrow_mut().push(event.clone())
3099 });
3100
3101 assert!(!buffer.is_dirty());
3102 assert!(events.borrow().is_empty());
3103
3104 buffer.edit(vec![1..2], "", Some(ctx)).unwrap();
3105 });
3106
3107 // after the first edit, the buffer is dirty, and emits a dirtied event.
3108 buffer1.update(&mut app, |buffer, ctx| {
3109 assert!(buffer.text() == "ac");
3110 assert!(buffer.is_dirty());
3111 assert_eq!(*events.borrow(), &[Event::Edited, Event::Dirtied]);
3112 events.borrow_mut().clear();
3113
3114 buffer.did_save(buffer.version(), None, ctx);
3115 });
3116
3117 // after saving, the buffer is not dirty, and emits a saved event.
3118 buffer1.update(&mut app, |buffer, ctx| {
3119 assert!(!buffer.is_dirty());
3120 assert_eq!(*events.borrow(), &[Event::Saved]);
3121 events.borrow_mut().clear();
3122
3123 buffer.edit(vec![1..1], "B", Some(ctx)).unwrap();
3124 buffer.edit(vec![2..2], "D", Some(ctx)).unwrap();
3125 });
3126
3127 // after editing again, the buffer is dirty, and emits another dirty event.
3128 buffer1.update(&mut app, |buffer, ctx| {
3129 assert!(buffer.text() == "aBDc");
3130 assert!(buffer.is_dirty());
3131 assert_eq!(
3132 *events.borrow(),
3133 &[Event::Edited, Event::Dirtied, Event::Edited],
3134 );
3135 events.borrow_mut().clear();
3136
3137 // TODO - currently, after restoring the buffer to its
3138 // previously-saved state, the is still considered dirty.
3139 buffer.edit(vec![1..3], "", Some(ctx)).unwrap();
3140 assert!(buffer.text() == "ac");
3141 assert!(buffer.is_dirty());
3142 });
3143
3144 assert_eq!(*events.borrow(), &[Event::Edited]);
3145
3146 // When a file is deleted, the buffer is considered dirty.
3147 let events = Rc::new(RefCell::new(Vec::new()));
3148 let file2 = app.update(|ctx| tree.file("file2", ctx)).await;
3149 let buffer2 = app.add_model(|ctx: &mut ModelContext<Buffer>| {
3150 ctx.subscribe(&ctx.handle(), {
3151 let events = events.clone();
3152 move |_, event, _| events.borrow_mut().push(event.clone())
3153 });
3154
3155 Buffer::from_history(0, History::new("abc".into()), Some(file2), None, ctx)
3156 });
3157
3158 fs::remove_file(dir.path().join("file2")).unwrap();
3159 buffer2.condition(&app, |b, _| b.is_dirty()).await;
3160 assert_eq!(
3161 *events.borrow(),
3162 &[Event::Dirtied, Event::FileHandleChanged]
3163 );
3164
3165 // When a file is already dirty when deleted, we don't emit a Dirtied event.
3166 let events = Rc::new(RefCell::new(Vec::new()));
3167 let file3 = app.update(|ctx| tree.file("file3", ctx)).await;
3168 let buffer3 = app.add_model(|ctx: &mut ModelContext<Buffer>| {
3169 ctx.subscribe(&ctx.handle(), {
3170 let events = events.clone();
3171 move |_, event, _| events.borrow_mut().push(event.clone())
3172 });
3173
3174 Buffer::from_history(0, History::new("abc".into()), Some(file3), None, ctx)
3175 });
3176
3177 tree.flush_fs_events(&app).await;
3178 buffer3.update(&mut app, |buffer, ctx| {
3179 buffer.edit(Some(0..0), "x", Some(ctx)).unwrap();
3180 });
3181 events.borrow_mut().clear();
3182 fs::remove_file(dir.path().join("file3")).unwrap();
3183 buffer3
3184 .condition(&app, |_, _| !events.borrow().is_empty())
3185 .await;
3186 assert_eq!(*events.borrow(), &[Event::FileHandleChanged]);
3187 app.read(|ctx| assert!(buffer3.read(ctx).is_dirty()));
3188 });
3189 }
3190
3191 #[gpui::test]
3192 async fn test_file_changes_on_disk(mut app: gpui::TestAppContext) {
3193 let initial_contents = "aaa\nbbbbb\nc\n";
3194 let dir = temp_tree(json!({ "the-file": initial_contents }));
3195 let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
3196 app.read(|ctx| tree.read(ctx).scan_complete()).await;
3197
3198 let abs_path = dir.path().join("the-file");
3199 let file = app.update(|ctx| tree.file("the-file", ctx)).await;
3200 let buffer = app.add_model(|ctx| {
3201 Buffer::from_history(
3202 0,
3203 History::new(initial_contents.into()),
3204 Some(file),
3205 None,
3206 ctx,
3207 )
3208 });
3209
3210 // Add a cursor at the start of each row.
3211 let (selection_set_id, _) = buffer.update(&mut app, |buffer, ctx| {
3212 assert!(!buffer.is_dirty());
3213 buffer.add_selection_set(
3214 (0..3)
3215 .map(|row| {
3216 let anchor = buffer.anchor_at(Point::new(row, 0), AnchorBias::Right);
3217 Selection {
3218 id: row as usize,
3219 start: anchor.clone(),
3220 end: anchor,
3221 reversed: false,
3222 goal: SelectionGoal::None,
3223 }
3224 })
3225 .collect::<Vec<_>>(),
3226 Some(ctx),
3227 )
3228 });
3229
3230 // Change the file on disk, adding two new lines of text, and removing
3231 // one line.
3232 buffer.read_with(&app, |buffer, _| {
3233 assert!(!buffer.is_dirty());
3234 assert!(!buffer.has_conflict());
3235 });
3236 let new_contents = "AAAA\naaa\nBB\nbbbbb\n";
3237 fs::write(&abs_path, new_contents).unwrap();
3238
3239 // Because the buffer was not modified, it is reloaded from disk. Its
3240 // contents are edited according to the diff between the old and new
3241 // file contents.
3242 buffer
3243 .condition(&app, |buffer, _| buffer.text() != initial_contents)
3244 .await;
3245
3246 buffer.update(&mut app, |buffer, _| {
3247 assert_eq!(buffer.text(), new_contents);
3248 assert!(!buffer.is_dirty());
3249 assert!(!buffer.has_conflict());
3250
3251 let selections = buffer.selections(selection_set_id).unwrap();
3252 let cursor_positions = selections
3253 .iter()
3254 .map(|selection| {
3255 assert_eq!(selection.start, selection.end);
3256 selection.start.to_point(&buffer)
3257 })
3258 .collect::<Vec<_>>();
3259 assert_eq!(
3260 cursor_positions,
3261 &[Point::new(1, 0), Point::new(3, 0), Point::new(4, 0),]
3262 );
3263 });
3264
3265 // Modify the buffer
3266 buffer.update(&mut app, |buffer, ctx| {
3267 buffer.edit(vec![0..0], " ", Some(ctx)).unwrap();
3268 assert!(buffer.is_dirty());
3269 });
3270
3271 // Change the file on disk again, adding blank lines to the beginning.
3272 fs::write(&abs_path, "\n\n\nAAAA\naaa\nBB\nbbbbb\n").unwrap();
3273
3274 // Becaues the buffer is modified, it doesn't reload from disk, but is
3275 // marked as having a conflict.
3276 buffer
3277 .condition(&app, |buffer, _| buffer.has_conflict())
3278 .await;
3279 }
3280
3281 #[gpui::test]
3282 async fn test_set_text_via_diff(mut app: gpui::TestAppContext) {
3283 let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
3284 let buffer = app.add_model(|ctx| Buffer::new(0, text, ctx));
3285
3286 let text = "a\nccc\ndddd\nffffff\n";
3287 let diff = buffer
3288 .read_with(&app, |b, ctx| b.diff(text.into(), ctx))
3289 .await;
3290 buffer.update(&mut app, |b, ctx| b.set_text_via_diff(diff, ctx));
3291 app.read(|ctx| assert_eq!(buffer.read(ctx).text(), text));
3292
3293 let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
3294 let diff = buffer
3295 .read_with(&app, |b, ctx| b.diff(text.into(), ctx))
3296 .await;
3297 buffer.update(&mut app, |b, ctx| b.set_text_via_diff(diff, ctx));
3298 app.read(|ctx| assert_eq!(buffer.read(ctx).text(), text));
3299 }
3300
3301 #[gpui::test]
3302 fn test_undo_redo(app: &mut gpui::MutableAppContext) {
3303 app.add_model(|ctx| {
3304 let mut buffer = Buffer::new(0, "1234", ctx);
3305
3306 let edit1 = buffer.edit(vec![1..1], "abx", None).unwrap();
3307 let edit2 = buffer.edit(vec![3..4], "yzef", None).unwrap();
3308 let edit3 = buffer.edit(vec![3..5], "cd", None).unwrap();
3309 assert_eq!(buffer.text(), "1abcdef234");
3310
3311 buffer.undo_or_redo(edit1[0].edit_id().unwrap()).unwrap();
3312 assert_eq!(buffer.text(), "1cdef234");
3313 buffer.undo_or_redo(edit1[0].edit_id().unwrap()).unwrap();
3314 assert_eq!(buffer.text(), "1abcdef234");
3315
3316 buffer.undo_or_redo(edit2[0].edit_id().unwrap()).unwrap();
3317 assert_eq!(buffer.text(), "1abcdx234");
3318 buffer.undo_or_redo(edit3[0].edit_id().unwrap()).unwrap();
3319 assert_eq!(buffer.text(), "1abx234");
3320 buffer.undo_or_redo(edit2[0].edit_id().unwrap()).unwrap();
3321 assert_eq!(buffer.text(), "1abyzef234");
3322 buffer.undo_or_redo(edit3[0].edit_id().unwrap()).unwrap();
3323 assert_eq!(buffer.text(), "1abcdef234");
3324
3325 buffer.undo_or_redo(edit3[0].edit_id().unwrap()).unwrap();
3326 assert_eq!(buffer.text(), "1abyzef234");
3327 buffer.undo_or_redo(edit1[0].edit_id().unwrap()).unwrap();
3328 assert_eq!(buffer.text(), "1yzef234");
3329 buffer.undo_or_redo(edit2[0].edit_id().unwrap()).unwrap();
3330 assert_eq!(buffer.text(), "1234");
3331
3332 buffer
3333 });
3334 }
3335
3336 #[gpui::test]
3337 fn test_history(app: &mut gpui::MutableAppContext) {
3338 app.add_model(|ctx| {
3339 let mut now = Instant::now();
3340 let mut buffer = Buffer::new(0, "123456", ctx);
3341
3342 let (set_id, _) =
3343 buffer.add_selection_set(buffer.selections_from_ranges(vec![4..4]).unwrap(), None);
3344 buffer.start_transaction_at(Some(set_id), now).unwrap();
3345 buffer.edit(vec![2..4], "cd", None).unwrap();
3346 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
3347 assert_eq!(buffer.text(), "12cd56");
3348 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3349
3350 buffer.start_transaction_at(Some(set_id), now).unwrap();
3351 buffer
3352 .update_selection_set(
3353 set_id,
3354 buffer.selections_from_ranges(vec![1..3]).unwrap(),
3355 None,
3356 )
3357 .unwrap();
3358 buffer.edit(vec![4..5], "e", None).unwrap();
3359 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
3360 assert_eq!(buffer.text(), "12cde6");
3361 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3362
3363 now += UNDO_GROUP_INTERVAL + Duration::from_millis(1);
3364 buffer.start_transaction_at(Some(set_id), now).unwrap();
3365 buffer
3366 .update_selection_set(
3367 set_id,
3368 buffer.selections_from_ranges(vec![2..2]).unwrap(),
3369 None,
3370 )
3371 .unwrap();
3372 buffer.edit(vec![0..1], "a", None).unwrap();
3373 buffer.edit(vec![1..1], "b", None).unwrap();
3374 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
3375 assert_eq!(buffer.text(), "ab2cde6");
3376 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3377
3378 // Last transaction happened past the group interval, undo it on its
3379 // own.
3380 buffer.undo(None);
3381 assert_eq!(buffer.text(), "12cde6");
3382 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3383
3384 // First two transactions happened within the group interval, undo them
3385 // together.
3386 buffer.undo(None);
3387 assert_eq!(buffer.text(), "123456");
3388 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3389
3390 // Redo the first two transactions together.
3391 buffer.redo(None);
3392 assert_eq!(buffer.text(), "12cde6");
3393 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3394
3395 // Redo the last transaction on its own.
3396 buffer.redo(None);
3397 assert_eq!(buffer.text(), "ab2cde6");
3398 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3399
3400 buffer
3401 });
3402 }
3403
3404 #[gpui::test]
3405 fn test_random_concurrent_edits(ctx: &mut gpui::MutableAppContext) {
3406 use crate::test::Network;
3407
3408 const PEERS: usize = 5;
3409
3410 for seed in 0..100 {
3411 println!("{:?}", seed);
3412 let mut rng = &mut StdRng::seed_from_u64(seed);
3413
3414 let base_text_len = rng.gen_range(0..10);
3415 let base_text = RandomCharIter::new(&mut rng)
3416 .take(base_text_len)
3417 .collect::<String>();
3418 let mut replica_ids = Vec::new();
3419 let mut buffers = Vec::new();
3420 let mut network = Network::new();
3421 for i in 0..PEERS {
3422 let buffer =
3423 ctx.add_model(|ctx| Buffer::new(i as ReplicaId, base_text.as_str(), ctx));
3424 buffers.push(buffer);
3425 replica_ids.push(i as u16);
3426 network.add_peer(i as u16);
3427 }
3428
3429 let mut mutation_count = 10;
3430 loop {
3431 let replica_index = rng.gen_range(0..PEERS);
3432 let replica_id = replica_ids[replica_index];
3433 buffers[replica_index].update(ctx, |buffer, _| match rng.gen_range(0..=100) {
3434 0..=50 if mutation_count != 0 => {
3435 let (_, _, ops) = buffer.randomly_mutate(&mut rng, None);
3436 network.broadcast(replica_id, ops, &mut rng);
3437 mutation_count -= 1;
3438 }
3439 51..=70 if mutation_count != 0 => {
3440 let ops = buffer.randomly_undo_redo(&mut rng);
3441 network.broadcast(replica_id, ops, &mut rng);
3442 mutation_count -= 1;
3443 }
3444 71..=100 if network.has_unreceived(replica_id) => {
3445 buffer
3446 .apply_ops(network.receive(replica_id, &mut rng), None)
3447 .unwrap();
3448 }
3449 _ => {}
3450 });
3451
3452 if mutation_count == 0 && network.is_idle() {
3453 break;
3454 }
3455 }
3456
3457 let first_buffer = buffers[0].read(ctx);
3458 for buffer in &buffers[1..] {
3459 let buffer = buffer.read(ctx);
3460 assert_eq!(buffer.text(), first_buffer.text());
3461 assert_eq!(
3462 buffer.all_selections().collect::<HashMap<_, _>>(),
3463 first_buffer.all_selections().collect::<HashMap<_, _>>()
3464 );
3465 assert_eq!(
3466 buffer.all_selection_ranges().collect::<HashMap<_, _>>(),
3467 first_buffer
3468 .all_selection_ranges()
3469 .collect::<HashMap<_, _>>()
3470 );
3471 }
3472 }
3473 }
3474
3475 #[gpui::test]
3476 async fn test_reparse(mut ctx: gpui::TestAppContext) {
3477 let app_state = ctx.read(build_app_state);
3478 let rust_lang = app_state
3479 .language_registry
3480 .select_language("test.rs")
3481 .cloned();
3482 assert!(rust_lang.is_some());
3483
3484 let buffer = ctx.add_model(|ctx| {
3485 let text = "fn a() {}";
3486
3487 let buffer = Buffer::from_history(0, History::new(text.into()), None, rust_lang, ctx);
3488 assert!(buffer.is_parsing());
3489 assert!(buffer.syntax_tree().is_none());
3490 buffer
3491 });
3492
3493 // Wait for the initial text to parse
3494 buffer
3495 .condition(&ctx, |buffer, _| !buffer.is_parsing())
3496 .await;
3497 assert_eq!(
3498 get_tree_sexp(&buffer, &ctx),
3499 concat!(
3500 "(source_file (function_item name: (identifier) ",
3501 "parameters: (parameters) ",
3502 "body: (block)))"
3503 )
3504 );
3505
3506 // Perform some edits (add parameter and variable reference)
3507 // Parsing doesn't begin until the transaction is complete
3508 buffer.update(&mut ctx, |buf, ctx| {
3509 buf.start_transaction(None).unwrap();
3510
3511 let offset = buf.text().find(")").unwrap();
3512 buf.edit(vec![offset..offset], "b: C", Some(ctx)).unwrap();
3513 assert!(!buf.is_parsing());
3514
3515 let offset = buf.text().find("}").unwrap();
3516 buf.edit(vec![offset..offset], " d; ", Some(ctx)).unwrap();
3517 assert!(!buf.is_parsing());
3518
3519 buf.end_transaction(None, Some(ctx)).unwrap();
3520 assert_eq!(buf.text(), "fn a(b: C) { d; }");
3521 assert!(buf.is_parsing());
3522 });
3523 buffer
3524 .condition(&ctx, |buffer, _| !buffer.is_parsing())
3525 .await;
3526 assert_eq!(
3527 get_tree_sexp(&buffer, &ctx),
3528 concat!(
3529 "(source_file (function_item name: (identifier) ",
3530 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3531 "body: (block (identifier))))"
3532 )
3533 );
3534
3535 // Perform a series of edits without waiting for the current parse to complete:
3536 // * turn identifier into a field expression
3537 // * turn field expression into a method call
3538 // * add a turbofish to the method call
3539 buffer.update(&mut ctx, |buf, ctx| {
3540 let offset = buf.text().find(";").unwrap();
3541 buf.edit(vec![offset..offset], ".e", Some(ctx)).unwrap();
3542 assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
3543 assert!(buf.is_parsing());
3544 });
3545 buffer.update(&mut ctx, |buf, ctx| {
3546 let offset = buf.text().find(";").unwrap();
3547 buf.edit(vec![offset..offset], "(f)", Some(ctx)).unwrap();
3548 assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
3549 assert!(buf.is_parsing());
3550 });
3551 buffer.update(&mut ctx, |buf, ctx| {
3552 let offset = buf.text().find("(f)").unwrap();
3553 buf.edit(vec![offset..offset], "::<G>", Some(ctx)).unwrap();
3554 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3555 assert!(buf.is_parsing());
3556 });
3557 buffer
3558 .condition(&ctx, |buffer, _| !buffer.is_parsing())
3559 .await;
3560 assert_eq!(
3561 get_tree_sexp(&buffer, &ctx),
3562 concat!(
3563 "(source_file (function_item name: (identifier) ",
3564 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3565 "body: (block (call_expression ",
3566 "function: (generic_function ",
3567 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3568 "type_arguments: (type_arguments (type_identifier))) ",
3569 "arguments: (arguments (identifier))))))",
3570 )
3571 );
3572
3573 buffer.update(&mut ctx, |buf, ctx| {
3574 buf.undo(Some(ctx));
3575 assert_eq!(buf.text(), "fn a() {}");
3576 assert!(buf.is_parsing());
3577 });
3578 buffer
3579 .condition(&ctx, |buffer, _| !buffer.is_parsing())
3580 .await;
3581 assert_eq!(
3582 get_tree_sexp(&buffer, &ctx),
3583 concat!(
3584 "(source_file (function_item name: (identifier) ",
3585 "parameters: (parameters) ",
3586 "body: (block)))"
3587 )
3588 );
3589
3590 buffer.update(&mut ctx, |buf, ctx| {
3591 buf.redo(Some(ctx));
3592 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3593 assert!(buf.is_parsing());
3594 });
3595 buffer
3596 .condition(&ctx, |buffer, _| !buffer.is_parsing())
3597 .await;
3598 assert_eq!(
3599 get_tree_sexp(&buffer, &ctx),
3600 concat!(
3601 "(source_file (function_item name: (identifier) ",
3602 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3603 "body: (block (call_expression ",
3604 "function: (generic_function ",
3605 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3606 "type_arguments: (type_arguments (type_identifier))) ",
3607 "arguments: (arguments (identifier))))))",
3608 )
3609 );
3610
3611 fn get_tree_sexp(buffer: &ModelHandle<Buffer>, ctx: &gpui::TestAppContext) -> String {
3612 buffer.read_with(ctx, |buffer, _| {
3613 buffer.syntax_tree().unwrap().root_node().to_sexp()
3614 })
3615 }
3616 }
3617
3618 impl Buffer {
3619 fn random_byte_range(&mut self, start_offset: usize, rng: &mut impl Rng) -> Range<usize> {
3620 let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
3621 let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Left);
3622 start..end
3623 }
3624
3625 pub fn randomly_edit<T>(
3626 &mut self,
3627 rng: &mut T,
3628 old_range_count: usize,
3629 ctx: Option<&mut ModelContext<Self>>,
3630 ) -> (Vec<Range<usize>>, String, Vec<Operation>)
3631 where
3632 T: Rng,
3633 {
3634 let mut old_ranges: Vec<Range<usize>> = Vec::new();
3635 for _ in 0..old_range_count {
3636 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
3637 if last_end > self.len() {
3638 break;
3639 }
3640 old_ranges.push(self.random_byte_range(last_end, rng));
3641 }
3642 let new_text_len = rng.gen_range(0..10);
3643 let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
3644
3645 let operations = self
3646 .edit(old_ranges.iter().cloned(), new_text.as_str(), ctx)
3647 .unwrap();
3648
3649 (old_ranges, new_text, operations)
3650 }
3651
3652 pub fn randomly_mutate<T>(
3653 &mut self,
3654 rng: &mut T,
3655 mut ctx: Option<&mut ModelContext<Self>>,
3656 ) -> (Vec<Range<usize>>, String, Vec<Operation>)
3657 where
3658 T: Rng,
3659 {
3660 // Randomly edit
3661 let (old_ranges, new_text, mut operations) =
3662 self.randomly_edit(rng, 5, ctx.as_deref_mut());
3663
3664 // Randomly add, remove or mutate selection sets.
3665 let replica_selection_sets = &self
3666 .all_selections()
3667 .map(|(set_id, _)| *set_id)
3668 .filter(|set_id| self.replica_id == set_id.replica_id)
3669 .collect::<Vec<_>>();
3670 let set_id = replica_selection_sets.choose(rng);
3671 if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
3672 let op = self.remove_selection_set(*set_id.unwrap(), None).unwrap();
3673 operations.push(op);
3674 } else {
3675 let mut ranges = Vec::new();
3676 for _ in 0..5 {
3677 ranges.push(self.random_byte_range(0, rng));
3678 }
3679 let new_selections = self.selections_from_ranges(ranges).unwrap();
3680
3681 let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
3682 self.add_selection_set(new_selections, None).1
3683 } else {
3684 self.update_selection_set(*set_id.unwrap(), new_selections, None)
3685 .unwrap()
3686 };
3687 operations.push(op);
3688 }
3689
3690 (old_ranges, new_text, operations)
3691 }
3692
3693 pub fn randomly_undo_redo(&mut self, rng: &mut impl Rng) -> Vec<Operation> {
3694 let mut ops = Vec::new();
3695 for _ in 0..rng.gen_range(1..5) {
3696 if let Some(edit_id) = self.history.ops.keys().choose(rng).copied() {
3697 ops.push(self.undo_or_redo(edit_id).unwrap());
3698 }
3699 }
3700 ops
3701 }
3702
3703 fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
3704 where
3705 I: IntoIterator<Item = Range<usize>>,
3706 {
3707 static NEXT_SELECTION_ID: AtomicUsize = AtomicUsize::new(0);
3708
3709 let mut ranges = ranges.into_iter().collect::<Vec<_>>();
3710 ranges.sort_unstable_by_key(|range| range.start);
3711
3712 let mut selections = Vec::with_capacity(ranges.len());
3713 for range in ranges {
3714 if range.start > range.end {
3715 selections.push(Selection {
3716 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
3717 start: self.anchor_before(range.end),
3718 end: self.anchor_before(range.start),
3719 reversed: true,
3720 goal: SelectionGoal::None,
3721 });
3722 } else {
3723 selections.push(Selection {
3724 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
3725 start: self.anchor_after(range.start),
3726 end: self.anchor_before(range.end),
3727 reversed: false,
3728 goal: SelectionGoal::None,
3729 });
3730 }
3731 }
3732 Ok(selections)
3733 }
3734
3735 pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> {
3736 Ok(self
3737 .selections(set_id)?
3738 .iter()
3739 .map(move |selection| {
3740 let start = selection.start.to_offset(self);
3741 let end = selection.end.to_offset(self);
3742 if selection.reversed {
3743 end..start
3744 } else {
3745 start..end
3746 }
3747 })
3748 .collect())
3749 }
3750
3751 pub fn all_selections(&self) -> impl Iterator<Item = (&SelectionSetId, &[Selection])> {
3752 self.selections
3753 .iter()
3754 .map(|(set_id, selections)| (set_id, selections.as_ref()))
3755 }
3756
3757 pub fn all_selection_ranges<'a>(
3758 &'a self,
3759 ) -> impl 'a + Iterator<Item = (SelectionSetId, Vec<Range<usize>>)> {
3760 self.selections
3761 .keys()
3762 .map(move |set_id| (*set_id, self.selection_ranges(*set_id).unwrap()))
3763 }
3764 }
3765
3766 impl Operation {
3767 fn edit_id(&self) -> Option<time::Local> {
3768 match self {
3769 Operation::Edit { edit, .. } => Some(edit.id),
3770 Operation::Undo { undo, .. } => Some(undo.edit_id),
3771 Operation::UpdateSelections { .. } => None,
3772 }
3773 }
3774 }
3775}