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