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