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 Clone for Snapshot {
1934 fn clone(&self) -> Self {
1935 Self {
1936 visible_text: self.visible_text.clone(),
1937 fragments: self.fragments.clone(),
1938 version: self.version.clone(),
1939 tree: self.tree.clone(),
1940 language: self.language.clone(),
1941 query_cursor: QueryCursorHandle::new(),
1942 }
1943 }
1944}
1945
1946impl Snapshot {
1947 pub fn len(&self) -> usize {
1948 self.visible_text.len()
1949 }
1950
1951 pub fn text(&self) -> Rope {
1952 self.visible_text.clone()
1953 }
1954
1955 pub fn text_summary(&self) -> TextSummary {
1956 self.visible_text.summary()
1957 }
1958
1959 pub fn max_point(&self) -> Point {
1960 self.visible_text.max_point()
1961 }
1962
1963 pub fn text_for_range(&self, range: Range<usize>) -> Chunks {
1964 self.visible_text.chunks_in_range(range)
1965 }
1966
1967 pub fn highlighted_text_for_range(&mut self, range: Range<usize>) -> HighlightedChunks {
1968 let chunks = self.visible_text.chunks_in_range(range.clone());
1969 if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
1970 let captures = self.query_cursor.set_byte_range(range.clone()).captures(
1971 &language.highlight_query,
1972 tree.root_node(),
1973 TextProvider(&self.visible_text),
1974 );
1975
1976 HighlightedChunks {
1977 range,
1978 chunks,
1979 highlights: Some(Highlights {
1980 captures,
1981 next_capture: None,
1982 stack: Default::default(),
1983 theme_mapping: language.theme_mapping(),
1984 }),
1985 }
1986 } else {
1987 HighlightedChunks {
1988 range,
1989 chunks,
1990 highlights: None,
1991 }
1992 }
1993 }
1994
1995 pub fn text_summary_for_range<T>(&self, range: Range<T>) -> TextSummary
1996 where
1997 T: ToOffset,
1998 {
1999 let range = range.start.to_offset(self.content())..range.end.to_offset(self.content());
2000 self.content().text_summary_for_range(range)
2001 }
2002
2003 pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
2004 self.content().point_for_offset(offset)
2005 }
2006
2007 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2008 self.visible_text.clip_offset(offset, bias)
2009 }
2010
2011 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2012 self.visible_text.clip_point(point, bias)
2013 }
2014
2015 pub fn to_offset(&self, point: Point) -> usize {
2016 self.visible_text.to_offset(point)
2017 }
2018
2019 pub fn to_point(&self, offset: usize) -> Point {
2020 self.visible_text.to_point(offset)
2021 }
2022
2023 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
2024 self.content().anchor_at(position, Bias::Left)
2025 }
2026
2027 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
2028 self.content().anchor_at(position, Bias::Right)
2029 }
2030
2031 fn content(&self) -> Content {
2032 self.into()
2033 }
2034}
2035
2036pub struct Content<'a> {
2037 visible_text: &'a Rope,
2038 fragments: &'a SumTree<Fragment>,
2039 version: &'a time::Global,
2040}
2041
2042impl<'a> From<&'a Snapshot> for Content<'a> {
2043 fn from(snapshot: &'a Snapshot) -> Self {
2044 Self {
2045 visible_text: &snapshot.visible_text,
2046 fragments: &snapshot.fragments,
2047 version: &snapshot.version,
2048 }
2049 }
2050}
2051
2052impl<'a> From<&'a Buffer> for Content<'a> {
2053 fn from(buffer: &'a Buffer) -> Self {
2054 Self {
2055 visible_text: &buffer.visible_text,
2056 fragments: &buffer.fragments,
2057 version: &buffer.version,
2058 }
2059 }
2060}
2061
2062impl<'a> From<&'a mut Buffer> for Content<'a> {
2063 fn from(buffer: &'a mut Buffer) -> Self {
2064 Self {
2065 visible_text: &buffer.visible_text,
2066 fragments: &buffer.fragments,
2067 version: &buffer.version,
2068 }
2069 }
2070}
2071
2072impl<'a> From<&'a Content<'a>> for Content<'a> {
2073 fn from(content: &'a Content) -> Self {
2074 Self {
2075 visible_text: &content.visible_text,
2076 fragments: &content.fragments,
2077 version: &content.version,
2078 }
2079 }
2080}
2081
2082impl<'a> Content<'a> {
2083 fn len(&self) -> usize {
2084 self.fragments.extent::<usize>(&None)
2085 }
2086
2087 fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
2088 let cx = Some(anchor.version.clone());
2089 let mut cursor = self.fragments.cursor::<VersionedOffset, usize>();
2090 cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
2091 let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
2092 anchor.offset - cursor.seek_start().offset()
2093 } else {
2094 0
2095 };
2096 self.text_summary_for_range(0..*cursor.sum_start() + overshoot)
2097 }
2098
2099 fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
2100 self.visible_text.cursor(range.start).summary(range.end)
2101 }
2102
2103 fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
2104 let offset = position.to_offset(self);
2105 let max_offset = self.len();
2106 assert!(offset <= max_offset, "offset is out of range");
2107 let mut cursor = self.fragments.cursor::<usize, FragmentTextSummary>();
2108 cursor.seek(&offset, bias, &None);
2109 Anchor {
2110 offset: offset + cursor.sum_start().deleted,
2111 bias,
2112 version: self.version.clone(),
2113 }
2114 }
2115
2116 fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
2117 let cx = Some(anchor.version.clone());
2118 let mut cursor = self
2119 .fragments
2120 .cursor::<VersionedOffset, FragmentTextSummary>();
2121 cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
2122 let overshoot = if cursor.item().is_some() {
2123 anchor.offset - cursor.seek_start().offset()
2124 } else {
2125 0
2126 };
2127 let summary = cursor.sum_start();
2128 summary.visible + summary.deleted + overshoot
2129 }
2130
2131 fn point_for_offset(&self, offset: usize) -> Result<Point> {
2132 if offset <= self.len() {
2133 Ok(self.text_summary_for_range(0..offset).lines)
2134 } else {
2135 Err(anyhow!("offset out of bounds"))
2136 }
2137 }
2138}
2139
2140struct RopeBuilder<'a> {
2141 old_visible_cursor: rope::Cursor<'a>,
2142 old_deleted_cursor: rope::Cursor<'a>,
2143 new_visible: Rope,
2144 new_deleted: Rope,
2145}
2146
2147impl<'a> RopeBuilder<'a> {
2148 fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self {
2149 Self {
2150 old_visible_cursor,
2151 old_deleted_cursor,
2152 new_visible: Rope::new(),
2153 new_deleted: Rope::new(),
2154 }
2155 }
2156
2157 fn push_tree(&mut self, len: FragmentTextSummary) {
2158 self.push(len.visible, true, true);
2159 self.push(len.deleted, false, false);
2160 }
2161
2162 fn push_fragment(&mut self, fragment: &Fragment, was_visible: bool) {
2163 debug_assert!(fragment.len > 0);
2164 self.push(fragment.len, was_visible, fragment.visible)
2165 }
2166
2167 fn push(&mut self, len: usize, was_visible: bool, is_visible: bool) {
2168 let text = if was_visible {
2169 self.old_visible_cursor
2170 .slice(self.old_visible_cursor.offset() + len)
2171 } else {
2172 self.old_deleted_cursor
2173 .slice(self.old_deleted_cursor.offset() + len)
2174 };
2175 if is_visible {
2176 self.new_visible.append(text);
2177 } else {
2178 self.new_deleted.append(text);
2179 }
2180 }
2181
2182 fn push_str(&mut self, text: &str) {
2183 self.new_visible.push(text);
2184 }
2185
2186 fn finish(mut self) -> (Rope, Rope) {
2187 self.new_visible.append(self.old_visible_cursor.suffix());
2188 self.new_deleted.append(self.old_deleted_cursor.suffix());
2189 (self.new_visible, self.new_deleted)
2190 }
2191}
2192
2193#[derive(Clone, Debug, Eq, PartialEq)]
2194pub enum Event {
2195 Edited,
2196 Dirtied,
2197 Saved,
2198 FileHandleChanged,
2199 Reloaded,
2200 Reparsed,
2201}
2202
2203impl Entity for Buffer {
2204 type Event = Event;
2205
2206 fn release(&mut self, cx: &mut gpui::MutableAppContext) {
2207 if let Some(file) = self.file.as_ref() {
2208 file.buffer_removed(self.remote_id, cx);
2209 }
2210 }
2211}
2212
2213impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
2214 type Item = Edit;
2215
2216 fn next(&mut self) -> Option<Self::Item> {
2217 let mut change: Option<Edit> = None;
2218
2219 while let Some(fragment) = self.cursor.item() {
2220 let bytes = self.cursor.start().visible - self.new_offset;
2221 let lines = self.visible_text.to_point(self.cursor.start().visible) - self.new_point;
2222 self.old_offset += bytes;
2223 self.old_point += &lines;
2224 self.new_offset += bytes;
2225 self.new_point += &lines;
2226
2227 if !fragment.was_visible(&self.since, &self.undos) && fragment.visible {
2228 let fragment_lines =
2229 self.visible_text.to_point(self.new_offset + fragment.len) - self.new_point;
2230 if let Some(ref mut change) = change {
2231 if change.new_bytes.end == self.new_offset {
2232 change.new_bytes.end += fragment.len;
2233 } else {
2234 break;
2235 }
2236 } else {
2237 change = Some(Edit {
2238 old_bytes: self.old_offset..self.old_offset,
2239 new_bytes: self.new_offset..self.new_offset + fragment.len,
2240 old_lines: self.old_point..self.old_point,
2241 });
2242 }
2243
2244 self.new_offset += fragment.len;
2245 self.new_point += &fragment_lines;
2246 } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible {
2247 let deleted_start = self.cursor.start().deleted;
2248 let fragment_lines = self.deleted_text.to_point(deleted_start + fragment.len)
2249 - self.deleted_text.to_point(deleted_start);
2250 if let Some(ref mut change) = change {
2251 if change.new_bytes.end == self.new_offset {
2252 change.old_bytes.end += fragment.len;
2253 change.old_lines.end += &fragment_lines;
2254 } else {
2255 break;
2256 }
2257 } else {
2258 change = Some(Edit {
2259 old_bytes: self.old_offset..self.old_offset + fragment.len,
2260 new_bytes: self.new_offset..self.new_offset,
2261 old_lines: self.old_point..self.old_point + &fragment_lines,
2262 });
2263 }
2264
2265 self.old_offset += fragment.len;
2266 self.old_point += &fragment_lines;
2267 }
2268
2269 self.cursor.next(&None);
2270 }
2271
2272 change
2273 }
2274}
2275
2276struct ByteChunks<'a>(rope::Chunks<'a>);
2277
2278impl<'a> Iterator for ByteChunks<'a> {
2279 type Item = &'a [u8];
2280
2281 fn next(&mut self) -> Option<Self::Item> {
2282 self.0.next().map(str::as_bytes)
2283 }
2284}
2285
2286struct TextProvider<'a>(&'a Rope);
2287
2288impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
2289 type I = ByteChunks<'a>;
2290
2291 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
2292 ByteChunks(self.0.chunks_in_range(node.byte_range()))
2293 }
2294}
2295
2296struct Highlights<'a> {
2297 captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
2298 next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
2299 stack: Vec<(usize, StyleId)>,
2300 theme_mapping: ThemeMap,
2301}
2302
2303pub struct HighlightedChunks<'a> {
2304 range: Range<usize>,
2305 chunks: Chunks<'a>,
2306 highlights: Option<Highlights<'a>>,
2307}
2308
2309impl<'a> HighlightedChunks<'a> {
2310 pub fn seek(&mut self, offset: usize) {
2311 self.range.start = offset;
2312 self.chunks.seek(self.range.start);
2313 if let Some(highlights) = self.highlights.as_mut() {
2314 highlights
2315 .stack
2316 .retain(|(end_offset, _)| *end_offset > offset);
2317 if let Some((mat, capture_ix)) = &highlights.next_capture {
2318 let capture = mat.captures[*capture_ix as usize];
2319 if offset >= capture.node.start_byte() {
2320 let next_capture_end = capture.node.end_byte();
2321 if offset < next_capture_end {
2322 highlights.stack.push((
2323 next_capture_end,
2324 highlights.theme_mapping.get(capture.index),
2325 ));
2326 }
2327 highlights.next_capture.take();
2328 }
2329 }
2330 highlights.captures.set_byte_range(self.range.clone());
2331 }
2332 }
2333
2334 pub fn offset(&self) -> usize {
2335 self.range.start
2336 }
2337}
2338
2339impl<'a> Iterator for HighlightedChunks<'a> {
2340 type Item = (&'a str, StyleId);
2341
2342 fn next(&mut self) -> Option<Self::Item> {
2343 let mut next_capture_start = usize::MAX;
2344
2345 if let Some(highlights) = self.highlights.as_mut() {
2346 while let Some((parent_capture_end, _)) = highlights.stack.last() {
2347 if *parent_capture_end <= self.range.start {
2348 highlights.stack.pop();
2349 } else {
2350 break;
2351 }
2352 }
2353
2354 if highlights.next_capture.is_none() {
2355 highlights.next_capture = highlights.captures.next();
2356 }
2357
2358 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
2359 let capture = mat.captures[*capture_ix as usize];
2360 if self.range.start < capture.node.start_byte() {
2361 next_capture_start = capture.node.start_byte();
2362 break;
2363 } else {
2364 let style_id = highlights.theme_mapping.get(capture.index);
2365 highlights.stack.push((capture.node.end_byte(), style_id));
2366 highlights.next_capture = highlights.captures.next();
2367 }
2368 }
2369 }
2370
2371 if let Some(chunk) = self.chunks.peek() {
2372 let chunk_start = self.range.start;
2373 let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
2374 let mut style_id = StyleId::default();
2375 if let Some((parent_capture_end, parent_style_id)) =
2376 self.highlights.as_ref().and_then(|h| h.stack.last())
2377 {
2378 chunk_end = chunk_end.min(*parent_capture_end);
2379 style_id = *parent_style_id;
2380 }
2381
2382 let slice =
2383 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2384 self.range.start = chunk_end;
2385 if self.range.start == self.chunks.offset() + chunk.len() {
2386 self.chunks.next().unwrap();
2387 }
2388
2389 Some((slice, style_id))
2390 } else {
2391 None
2392 }
2393 }
2394}
2395
2396impl Fragment {
2397 fn is_visible(&self, undos: &UndoMap) -> bool {
2398 !undos.is_undone(self.timestamp.local())
2399 && self.deletions.iter().all(|d| undos.is_undone(*d))
2400 }
2401
2402 fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool {
2403 (version.observed(self.timestamp.local())
2404 && !undos.was_undone(self.timestamp.local(), version))
2405 && self
2406 .deletions
2407 .iter()
2408 .all(|d| !version.observed(*d) || undos.was_undone(*d, version))
2409 }
2410}
2411
2412impl sum_tree::Item for Fragment {
2413 type Summary = FragmentSummary;
2414
2415 fn summary(&self) -> Self::Summary {
2416 let mut max_version = time::Global::new();
2417 max_version.observe(self.timestamp.local());
2418 for deletion in &self.deletions {
2419 max_version.observe(*deletion);
2420 }
2421 max_version.join(&self.max_undos);
2422
2423 let mut min_insertion_version = time::Global::new();
2424 min_insertion_version.observe(self.timestamp.local());
2425 let max_insertion_version = min_insertion_version.clone();
2426 if self.visible {
2427 FragmentSummary {
2428 text: FragmentTextSummary {
2429 visible: self.len,
2430 deleted: 0,
2431 },
2432 max_version,
2433 min_insertion_version,
2434 max_insertion_version,
2435 }
2436 } else {
2437 FragmentSummary {
2438 text: FragmentTextSummary {
2439 visible: 0,
2440 deleted: self.len,
2441 },
2442 max_version,
2443 min_insertion_version,
2444 max_insertion_version,
2445 }
2446 }
2447 }
2448}
2449
2450impl sum_tree::Summary for FragmentSummary {
2451 type Context = Option<time::Global>;
2452
2453 fn add_summary(&mut self, other: &Self, _: &Self::Context) {
2454 self.text.visible += &other.text.visible;
2455 self.text.deleted += &other.text.deleted;
2456 self.max_version.join(&other.max_version);
2457 self.min_insertion_version
2458 .meet(&other.min_insertion_version);
2459 self.max_insertion_version
2460 .join(&other.max_insertion_version);
2461 }
2462}
2463
2464impl Default for FragmentSummary {
2465 fn default() -> Self {
2466 FragmentSummary {
2467 text: FragmentTextSummary::default(),
2468 max_version: time::Global::new(),
2469 min_insertion_version: time::Global::new(),
2470 max_insertion_version: time::Global::new(),
2471 }
2472 }
2473}
2474
2475impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
2476 fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<time::Global>) {
2477 *self += summary.text.visible;
2478 }
2479}
2480
2481#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2482enum VersionedOffset {
2483 Offset(usize),
2484 InvalidVersion,
2485}
2486
2487impl VersionedOffset {
2488 fn offset(&self) -> usize {
2489 if let Self::Offset(offset) = self {
2490 *offset
2491 } else {
2492 panic!("invalid version")
2493 }
2494 }
2495}
2496
2497impl Default for VersionedOffset {
2498 fn default() -> Self {
2499 Self::Offset(0)
2500 }
2501}
2502
2503impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
2504 fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<time::Global>) {
2505 if let Self::Offset(offset) = self {
2506 let version = cx.as_ref().unwrap();
2507 if *version >= summary.max_insertion_version {
2508 *offset += summary.text.visible + summary.text.deleted;
2509 } else if !summary
2510 .min_insertion_version
2511 .iter()
2512 .all(|t| !version.observed(*t))
2513 {
2514 *self = Self::InvalidVersion;
2515 }
2516 }
2517 }
2518}
2519
2520impl<'a> sum_tree::SeekDimension<'a, FragmentSummary> for VersionedOffset {
2521 fn cmp(&self, other: &Self, _: &Option<time::Global>) -> cmp::Ordering {
2522 match (self, other) {
2523 (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),
2524 (Self::Offset(_), Self::InvalidVersion) => cmp::Ordering::Less,
2525 (Self::InvalidVersion, _) => unreachable!(),
2526 }
2527 }
2528}
2529
2530impl Operation {
2531 fn replica_id(&self) -> ReplicaId {
2532 self.lamport_timestamp().replica_id
2533 }
2534
2535 fn lamport_timestamp(&self) -> time::Lamport {
2536 match self {
2537 Operation::Edit(edit) => edit.timestamp.lamport(),
2538 Operation::Undo {
2539 lamport_timestamp, ..
2540 } => *lamport_timestamp,
2541 Operation::UpdateSelections {
2542 lamport_timestamp, ..
2543 } => *lamport_timestamp,
2544 Operation::SetActiveSelections {
2545 lamport_timestamp, ..
2546 } => *lamport_timestamp,
2547 }
2548 }
2549
2550 pub fn is_edit(&self) -> bool {
2551 match self {
2552 Operation::Edit { .. } => true,
2553 _ => false,
2554 }
2555 }
2556}
2557
2558impl<'a> Into<proto::Operation> for &'a Operation {
2559 fn into(self) -> proto::Operation {
2560 proto::Operation {
2561 variant: Some(match self {
2562 Operation::Edit(edit) => proto::operation::Variant::Edit(edit.into()),
2563 Operation::Undo {
2564 undo,
2565 lamport_timestamp,
2566 } => proto::operation::Variant::Undo(proto::operation::Undo {
2567 replica_id: undo.id.replica_id as u32,
2568 local_timestamp: undo.id.value,
2569 lamport_timestamp: lamport_timestamp.value,
2570 ranges: undo
2571 .ranges
2572 .iter()
2573 .map(|r| proto::Range {
2574 start: r.start as u64,
2575 end: r.end as u64,
2576 })
2577 .collect(),
2578 counts: undo
2579 .counts
2580 .iter()
2581 .map(|(edit_id, count)| proto::operation::UndoCount {
2582 replica_id: edit_id.replica_id as u32,
2583 local_timestamp: edit_id.value,
2584 count: *count,
2585 })
2586 .collect(),
2587 version: From::from(&undo.version),
2588 }),
2589 Operation::UpdateSelections {
2590 set_id,
2591 selections,
2592 lamport_timestamp,
2593 } => proto::operation::Variant::UpdateSelections(
2594 proto::operation::UpdateSelections {
2595 replica_id: set_id.replica_id as u32,
2596 local_timestamp: set_id.value,
2597 lamport_timestamp: lamport_timestamp.value,
2598 set: selections.as_ref().map(|selections| proto::SelectionSet {
2599 selections: selections.iter().map(Into::into).collect(),
2600 }),
2601 },
2602 ),
2603 Operation::SetActiveSelections {
2604 set_id,
2605 lamport_timestamp,
2606 } => proto::operation::Variant::SetActiveSelections(
2607 proto::operation::SetActiveSelections {
2608 replica_id: lamport_timestamp.replica_id as u32,
2609 local_timestamp: set_id.map(|set_id| set_id.value),
2610 lamport_timestamp: lamport_timestamp.value,
2611 },
2612 ),
2613 }),
2614 }
2615 }
2616}
2617
2618impl<'a> Into<proto::operation::Edit> for &'a EditOperation {
2619 fn into(self) -> proto::operation::Edit {
2620 let ranges = self
2621 .ranges
2622 .iter()
2623 .map(|range| proto::Range {
2624 start: range.start as u64,
2625 end: range.end as u64,
2626 })
2627 .collect();
2628 proto::operation::Edit {
2629 replica_id: self.timestamp.replica_id as u32,
2630 local_timestamp: self.timestamp.local,
2631 lamport_timestamp: self.timestamp.lamport,
2632 version: From::from(&self.version),
2633 ranges,
2634 new_text: self.new_text.clone(),
2635 }
2636 }
2637}
2638
2639impl<'a> Into<proto::Anchor> for &'a Anchor {
2640 fn into(self) -> proto::Anchor {
2641 proto::Anchor {
2642 version: self
2643 .version
2644 .iter()
2645 .map(|entry| proto::VectorClockEntry {
2646 replica_id: entry.replica_id as u32,
2647 timestamp: entry.value,
2648 })
2649 .collect(),
2650 offset: self.offset as u64,
2651 bias: match self.bias {
2652 Bias::Left => proto::anchor::Bias::Left as i32,
2653 Bias::Right => proto::anchor::Bias::Right as i32,
2654 },
2655 }
2656 }
2657}
2658
2659impl<'a> Into<proto::Selection> for &'a Selection {
2660 fn into(self) -> proto::Selection {
2661 proto::Selection {
2662 id: self.id as u64,
2663 start: Some((&self.start).into()),
2664 end: Some((&self.end).into()),
2665 reversed: self.reversed,
2666 }
2667 }
2668}
2669
2670impl TryFrom<proto::Operation> for Operation {
2671 type Error = anyhow::Error;
2672
2673 fn try_from(message: proto::Operation) -> Result<Self, Self::Error> {
2674 Ok(
2675 match message
2676 .variant
2677 .ok_or_else(|| anyhow!("missing operation variant"))?
2678 {
2679 proto::operation::Variant::Edit(edit) => Operation::Edit(edit.into()),
2680 proto::operation::Variant::Undo(undo) => Operation::Undo {
2681 lamport_timestamp: time::Lamport {
2682 replica_id: undo.replica_id as ReplicaId,
2683 value: undo.lamport_timestamp,
2684 },
2685 undo: UndoOperation {
2686 id: time::Local {
2687 replica_id: undo.replica_id as ReplicaId,
2688 value: undo.local_timestamp,
2689 },
2690 counts: undo
2691 .counts
2692 .into_iter()
2693 .map(|c| {
2694 (
2695 time::Local {
2696 replica_id: c.replica_id as ReplicaId,
2697 value: c.local_timestamp,
2698 },
2699 c.count,
2700 )
2701 })
2702 .collect(),
2703 ranges: undo
2704 .ranges
2705 .into_iter()
2706 .map(|r| r.start as usize..r.end as usize)
2707 .collect(),
2708 version: undo.version.into(),
2709 },
2710 },
2711 proto::operation::Variant::UpdateSelections(message) => {
2712 let selections: Option<Vec<Selection>> = if let Some(set) = message.set {
2713 Some(
2714 set.selections
2715 .into_iter()
2716 .map(TryFrom::try_from)
2717 .collect::<Result<_, _>>()?,
2718 )
2719 } else {
2720 None
2721 };
2722 Operation::UpdateSelections {
2723 set_id: time::Lamport {
2724 replica_id: message.replica_id as ReplicaId,
2725 value: message.local_timestamp,
2726 },
2727 lamport_timestamp: time::Lamport {
2728 replica_id: message.replica_id as ReplicaId,
2729 value: message.lamport_timestamp,
2730 },
2731 selections: selections.map(Arc::from),
2732 }
2733 }
2734 proto::operation::Variant::SetActiveSelections(message) => {
2735 Operation::SetActiveSelections {
2736 set_id: message.local_timestamp.map(|value| time::Lamport {
2737 replica_id: message.replica_id as ReplicaId,
2738 value,
2739 }),
2740 lamport_timestamp: time::Lamport {
2741 replica_id: message.replica_id as ReplicaId,
2742 value: message.lamport_timestamp,
2743 },
2744 }
2745 }
2746 },
2747 )
2748 }
2749}
2750
2751impl From<proto::operation::Edit> for EditOperation {
2752 fn from(edit: proto::operation::Edit) -> Self {
2753 let ranges = edit
2754 .ranges
2755 .into_iter()
2756 .map(|range| range.start as usize..range.end as usize)
2757 .collect();
2758 EditOperation {
2759 timestamp: InsertionTimestamp {
2760 replica_id: edit.replica_id as ReplicaId,
2761 local: edit.local_timestamp,
2762 lamport: edit.lamport_timestamp,
2763 },
2764 version: edit.version.into(),
2765 ranges,
2766 new_text: edit.new_text,
2767 }
2768 }
2769}
2770
2771impl TryFrom<proto::Anchor> for Anchor {
2772 type Error = anyhow::Error;
2773
2774 fn try_from(message: proto::Anchor) -> Result<Self, Self::Error> {
2775 let mut version = time::Global::new();
2776 for entry in message.version {
2777 version.observe(time::Local {
2778 replica_id: entry.replica_id as ReplicaId,
2779 value: entry.timestamp,
2780 });
2781 }
2782
2783 Ok(Self {
2784 offset: message.offset as usize,
2785 bias: if message.bias == proto::anchor::Bias::Left as i32 {
2786 Bias::Left
2787 } else if message.bias == proto::anchor::Bias::Right as i32 {
2788 Bias::Right
2789 } else {
2790 Err(anyhow!("invalid anchor bias {}", message.bias))?
2791 },
2792 version,
2793 })
2794 }
2795}
2796
2797impl TryFrom<proto::Selection> for Selection {
2798 type Error = anyhow::Error;
2799
2800 fn try_from(selection: proto::Selection) -> Result<Self, Self::Error> {
2801 Ok(Selection {
2802 id: selection.id as usize,
2803 start: selection
2804 .start
2805 .ok_or_else(|| anyhow!("missing selection start"))?
2806 .try_into()?,
2807 end: selection
2808 .end
2809 .ok_or_else(|| anyhow!("missing selection end"))?
2810 .try_into()?,
2811 reversed: selection.reversed,
2812 goal: SelectionGoal::None,
2813 })
2814 }
2815}
2816
2817impl operation_queue::Operation for Operation {
2818 fn timestamp(&self) -> time::Lamport {
2819 self.lamport_timestamp()
2820 }
2821}
2822
2823pub trait ToOffset {
2824 fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize;
2825}
2826
2827impl ToOffset for Point {
2828 fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize {
2829 content.into().visible_text.to_offset(*self)
2830 }
2831}
2832
2833impl ToOffset for usize {
2834 fn to_offset<'a>(&self, _: impl Into<Content<'a>>) -> usize {
2835 *self
2836 }
2837}
2838
2839impl ToOffset for Anchor {
2840 fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize {
2841 content.into().summary_for_anchor(self).bytes
2842 }
2843}
2844
2845impl<'a> ToOffset for &'a Anchor {
2846 fn to_offset<'b>(&self, content: impl Into<Content<'b>>) -> usize {
2847 content.into().summary_for_anchor(self).bytes
2848 }
2849}
2850
2851pub trait ToPoint {
2852 fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point;
2853}
2854
2855impl ToPoint for Anchor {
2856 fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point {
2857 content.into().summary_for_anchor(self).lines
2858 }
2859}
2860
2861impl ToPoint for usize {
2862 fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point {
2863 content.into().visible_text.to_point(*self)
2864 }
2865}
2866
2867#[cfg(test)]
2868mod tests {
2869 use super::*;
2870 use crate::{
2871 fs::RealFs,
2872 test::{build_app_state, temp_tree},
2873 util::RandomCharIter,
2874 worktree::{Worktree, WorktreeHandle as _},
2875 };
2876 use gpui::ModelHandle;
2877 use rand::prelude::*;
2878 use serde_json::json;
2879 use std::{
2880 cell::RefCell,
2881 cmp::Ordering,
2882 env, fs, mem,
2883 path::Path,
2884 rc::Rc,
2885 sync::atomic::{self, AtomicUsize},
2886 };
2887
2888 #[gpui::test]
2889 fn test_edit(cx: &mut gpui::MutableAppContext) {
2890 cx.add_model(|cx| {
2891 let mut buffer = Buffer::new(0, "abc", cx);
2892 assert_eq!(buffer.text(), "abc");
2893 buffer.edit(vec![3..3], "def", cx);
2894 assert_eq!(buffer.text(), "abcdef");
2895 buffer.edit(vec![0..0], "ghi", cx);
2896 assert_eq!(buffer.text(), "ghiabcdef");
2897 buffer.edit(vec![5..5], "jkl", cx);
2898 assert_eq!(buffer.text(), "ghiabjklcdef");
2899 buffer.edit(vec![6..7], "", cx);
2900 assert_eq!(buffer.text(), "ghiabjlcdef");
2901 buffer.edit(vec![4..9], "mno", cx);
2902 assert_eq!(buffer.text(), "ghiamnoef");
2903 buffer
2904 });
2905 }
2906
2907 #[gpui::test]
2908 fn test_edit_events(cx: &mut gpui::MutableAppContext) {
2909 let mut now = Instant::now();
2910 let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
2911 let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
2912
2913 let buffer1 = cx.add_model(|cx| Buffer::new(0, "abcdef", cx));
2914 let buffer2 = cx.add_model(|cx| Buffer::new(1, "abcdef", cx));
2915 let buffer_ops = buffer1.update(cx, |buffer, cx| {
2916 let buffer_1_events = buffer_1_events.clone();
2917 cx.subscribe(&buffer1, move |_, event, _| {
2918 buffer_1_events.borrow_mut().push(event.clone())
2919 });
2920 let buffer_2_events = buffer_2_events.clone();
2921 cx.subscribe(&buffer2, move |_, event, _| {
2922 buffer_2_events.borrow_mut().push(event.clone())
2923 });
2924
2925 // An edit emits an edited event, followed by a dirtied event,
2926 // since the buffer was previously in a clean state.
2927 buffer.edit(Some(2..4), "XYZ", cx);
2928
2929 // An empty transaction does not emit any events.
2930 buffer.start_transaction(None).unwrap();
2931 buffer.end_transaction(None, cx).unwrap();
2932
2933 // A transaction containing two edits emits one edited event.
2934 now += Duration::from_secs(1);
2935 buffer.start_transaction_at(None, now).unwrap();
2936 buffer.edit(Some(5..5), "u", cx);
2937 buffer.edit(Some(6..6), "w", cx);
2938 buffer.end_transaction_at(None, now, cx).unwrap();
2939
2940 // Undoing a transaction emits one edited event.
2941 buffer.undo(cx);
2942
2943 buffer.operations.clone()
2944 });
2945
2946 // Incorporating a set of remote ops emits a single edited event,
2947 // followed by a dirtied event.
2948 buffer2.update(cx, |buffer, cx| {
2949 buffer.apply_ops(buffer_ops, cx).unwrap();
2950 });
2951
2952 let buffer_1_events = buffer_1_events.borrow();
2953 assert_eq!(
2954 *buffer_1_events,
2955 vec![Event::Edited, Event::Dirtied, Event::Edited, Event::Edited]
2956 );
2957
2958 let buffer_2_events = buffer_2_events.borrow();
2959 assert_eq!(*buffer_2_events, vec![Event::Edited, Event::Dirtied]);
2960 }
2961
2962 #[gpui::test]
2963 fn test_random_edits(cx: &mut gpui::MutableAppContext) {
2964 let iterations = env::var("ITERATIONS")
2965 .map(|i| i.parse().expect("invalid `ITERATIONS` variable"))
2966 .unwrap_or(100);
2967 let operations = env::var("OPERATIONS")
2968 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
2969 .unwrap_or(10);
2970 let start_seed =
2971 env::var("SEED").map_or(0, |seed| seed.parse().expect("invalid `SEED` variable"));
2972
2973 for seed in start_seed..start_seed + iterations {
2974 println!("{:?}", seed);
2975 let mut rng = &mut StdRng::seed_from_u64(seed);
2976
2977 let reference_string_len = rng.gen_range(0..3);
2978 let mut reference_string = RandomCharIter::new(&mut rng)
2979 .take(reference_string_len)
2980 .collect::<String>();
2981 cx.add_model(|cx| {
2982 let mut buffer = Buffer::new(0, reference_string.as_str(), cx);
2983 buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
2984 let mut buffer_versions = Vec::new();
2985 log::info!(
2986 "buffer text {:?}, version: {:?}",
2987 buffer.text(),
2988 buffer.version()
2989 );
2990
2991 for _i in 0..operations {
2992 let (old_ranges, new_text) = buffer.randomly_mutate(rng, cx);
2993 for old_range in old_ranges.iter().rev() {
2994 reference_string.replace_range(old_range.clone(), &new_text);
2995 }
2996 assert_eq!(buffer.text(), reference_string);
2997 log::info!(
2998 "buffer text {:?}, version: {:?}",
2999 buffer.text(),
3000 buffer.version()
3001 );
3002
3003 if rng.gen_bool(0.25) {
3004 buffer.randomly_undo_redo(rng, cx);
3005 reference_string = buffer.text();
3006 log::info!(
3007 "buffer text {:?}, version: {:?}",
3008 buffer.text(),
3009 buffer.version()
3010 );
3011 }
3012
3013 let range = buffer.random_byte_range(0, rng);
3014 assert_eq!(
3015 buffer.text_summary_for_range(range.clone()),
3016 TextSummary::from(&reference_string[range])
3017 );
3018
3019 if rng.gen_bool(0.3) {
3020 buffer_versions.push(buffer.clone());
3021 }
3022 }
3023
3024 for mut old_buffer in buffer_versions {
3025 let edits = buffer
3026 .edits_since(old_buffer.version.clone())
3027 .collect::<Vec<_>>();
3028
3029 log::info!(
3030 "mutating old buffer version {:?}, text: {:?}, edits since: {:?}",
3031 old_buffer.version(),
3032 old_buffer.text(),
3033 edits,
3034 );
3035
3036 let mut delta = 0_isize;
3037 for edit in edits {
3038 let old_start = (edit.old_bytes.start as isize + delta) as usize;
3039 let new_text: String =
3040 buffer.text_for_range(edit.new_bytes.clone()).collect();
3041 old_buffer.edit(
3042 Some(old_start..old_start + edit.deleted_bytes()),
3043 new_text,
3044 cx,
3045 );
3046 delta += edit.delta();
3047 }
3048 assert_eq!(old_buffer.text(), buffer.text());
3049 }
3050
3051 buffer
3052 });
3053 }
3054 }
3055
3056 #[gpui::test]
3057 fn test_line_len(cx: &mut gpui::MutableAppContext) {
3058 cx.add_model(|cx| {
3059 let mut buffer = Buffer::new(0, "", cx);
3060 buffer.edit(vec![0..0], "abcd\nefg\nhij", cx);
3061 buffer.edit(vec![12..12], "kl\nmno", cx);
3062 buffer.edit(vec![18..18], "\npqrs\n", cx);
3063 buffer.edit(vec![18..21], "\nPQ", cx);
3064
3065 assert_eq!(buffer.line_len(0), 4);
3066 assert_eq!(buffer.line_len(1), 3);
3067 assert_eq!(buffer.line_len(2), 5);
3068 assert_eq!(buffer.line_len(3), 3);
3069 assert_eq!(buffer.line_len(4), 4);
3070 assert_eq!(buffer.line_len(5), 0);
3071 buffer
3072 });
3073 }
3074
3075 #[gpui::test]
3076 fn test_text_summary_for_range(cx: &mut gpui::MutableAppContext) {
3077 cx.add_model(|cx| {
3078 let buffer = Buffer::new(0, "ab\nefg\nhklm\nnopqrs\ntuvwxyz", cx);
3079 assert_eq!(
3080 buffer.text_summary_for_range(1..3),
3081 TextSummary {
3082 bytes: 2,
3083 lines: Point::new(1, 0),
3084 first_line_chars: 1,
3085 last_line_chars: 0,
3086 longest_row: 0,
3087 longest_row_chars: 1,
3088 }
3089 );
3090 assert_eq!(
3091 buffer.text_summary_for_range(1..12),
3092 TextSummary {
3093 bytes: 11,
3094 lines: Point::new(3, 0),
3095 first_line_chars: 1,
3096 last_line_chars: 0,
3097 longest_row: 2,
3098 longest_row_chars: 4,
3099 }
3100 );
3101 assert_eq!(
3102 buffer.text_summary_for_range(0..20),
3103 TextSummary {
3104 bytes: 20,
3105 lines: Point::new(4, 1),
3106 first_line_chars: 2,
3107 last_line_chars: 1,
3108 longest_row: 3,
3109 longest_row_chars: 6,
3110 }
3111 );
3112 assert_eq!(
3113 buffer.text_summary_for_range(0..22),
3114 TextSummary {
3115 bytes: 22,
3116 lines: Point::new(4, 3),
3117 first_line_chars: 2,
3118 last_line_chars: 3,
3119 longest_row: 3,
3120 longest_row_chars: 6,
3121 }
3122 );
3123 assert_eq!(
3124 buffer.text_summary_for_range(7..22),
3125 TextSummary {
3126 bytes: 15,
3127 lines: Point::new(2, 3),
3128 first_line_chars: 4,
3129 last_line_chars: 3,
3130 longest_row: 1,
3131 longest_row_chars: 6,
3132 }
3133 );
3134 buffer
3135 });
3136 }
3137
3138 #[gpui::test]
3139 fn test_chars_at(cx: &mut gpui::MutableAppContext) {
3140 cx.add_model(|cx| {
3141 let mut buffer = Buffer::new(0, "", cx);
3142 buffer.edit(vec![0..0], "abcd\nefgh\nij", cx);
3143 buffer.edit(vec![12..12], "kl\nmno", cx);
3144 buffer.edit(vec![18..18], "\npqrs", cx);
3145 buffer.edit(vec![18..21], "\nPQ", cx);
3146
3147 let chars = buffer.chars_at(Point::new(0, 0));
3148 assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
3149
3150 let chars = buffer.chars_at(Point::new(1, 0));
3151 assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
3152
3153 let chars = buffer.chars_at(Point::new(2, 0));
3154 assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
3155
3156 let chars = buffer.chars_at(Point::new(3, 0));
3157 assert_eq!(chars.collect::<String>(), "mno\nPQrs");
3158
3159 let chars = buffer.chars_at(Point::new(4, 0));
3160 assert_eq!(chars.collect::<String>(), "PQrs");
3161
3162 // Regression test:
3163 let mut buffer = Buffer::new(0, "", cx);
3164 buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", cx);
3165 buffer.edit(vec![60..60], "\n", cx);
3166
3167 let chars = buffer.chars_at(Point::new(6, 0));
3168 assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
3169
3170 buffer
3171 });
3172 }
3173
3174 #[gpui::test]
3175 fn test_anchors(cx: &mut gpui::MutableAppContext) {
3176 cx.add_model(|cx| {
3177 let mut buffer = Buffer::new(0, "", cx);
3178 buffer.edit(vec![0..0], "abc", cx);
3179 let left_anchor = buffer.anchor_before(2);
3180 let right_anchor = buffer.anchor_after(2);
3181
3182 buffer.edit(vec![1..1], "def\n", cx);
3183 assert_eq!(buffer.text(), "adef\nbc");
3184 assert_eq!(left_anchor.to_offset(&buffer), 6);
3185 assert_eq!(right_anchor.to_offset(&buffer), 6);
3186 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3187 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3188
3189 buffer.edit(vec![2..3], "", cx);
3190 assert_eq!(buffer.text(), "adf\nbc");
3191 assert_eq!(left_anchor.to_offset(&buffer), 5);
3192 assert_eq!(right_anchor.to_offset(&buffer), 5);
3193 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3194 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3195
3196 buffer.edit(vec![5..5], "ghi\n", cx);
3197 assert_eq!(buffer.text(), "adf\nbghi\nc");
3198 assert_eq!(left_anchor.to_offset(&buffer), 5);
3199 assert_eq!(right_anchor.to_offset(&buffer), 9);
3200 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3201 assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
3202
3203 buffer.edit(vec![7..9], "", cx);
3204 assert_eq!(buffer.text(), "adf\nbghc");
3205 assert_eq!(left_anchor.to_offset(&buffer), 5);
3206 assert_eq!(right_anchor.to_offset(&buffer), 7);
3207 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 },);
3208 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 3 });
3209
3210 // Ensure anchoring to a point is equivalent to anchoring to an offset.
3211 assert_eq!(
3212 buffer.anchor_before(Point { row: 0, column: 0 }),
3213 buffer.anchor_before(0)
3214 );
3215 assert_eq!(
3216 buffer.anchor_before(Point { row: 0, column: 1 }),
3217 buffer.anchor_before(1)
3218 );
3219 assert_eq!(
3220 buffer.anchor_before(Point { row: 0, column: 2 }),
3221 buffer.anchor_before(2)
3222 );
3223 assert_eq!(
3224 buffer.anchor_before(Point { row: 0, column: 3 }),
3225 buffer.anchor_before(3)
3226 );
3227 assert_eq!(
3228 buffer.anchor_before(Point { row: 1, column: 0 }),
3229 buffer.anchor_before(4)
3230 );
3231 assert_eq!(
3232 buffer.anchor_before(Point { row: 1, column: 1 }),
3233 buffer.anchor_before(5)
3234 );
3235 assert_eq!(
3236 buffer.anchor_before(Point { row: 1, column: 2 }),
3237 buffer.anchor_before(6)
3238 );
3239 assert_eq!(
3240 buffer.anchor_before(Point { row: 1, column: 3 }),
3241 buffer.anchor_before(7)
3242 );
3243 assert_eq!(
3244 buffer.anchor_before(Point { row: 1, column: 4 }),
3245 buffer.anchor_before(8)
3246 );
3247
3248 // Comparison between anchors.
3249 let anchor_at_offset_0 = buffer.anchor_before(0);
3250 let anchor_at_offset_1 = buffer.anchor_before(1);
3251 let anchor_at_offset_2 = buffer.anchor_before(2);
3252
3253 assert_eq!(
3254 anchor_at_offset_0
3255 .cmp(&anchor_at_offset_0, &buffer)
3256 .unwrap(),
3257 Ordering::Equal
3258 );
3259 assert_eq!(
3260 anchor_at_offset_1
3261 .cmp(&anchor_at_offset_1, &buffer)
3262 .unwrap(),
3263 Ordering::Equal
3264 );
3265 assert_eq!(
3266 anchor_at_offset_2
3267 .cmp(&anchor_at_offset_2, &buffer)
3268 .unwrap(),
3269 Ordering::Equal
3270 );
3271
3272 assert_eq!(
3273 anchor_at_offset_0
3274 .cmp(&anchor_at_offset_1, &buffer)
3275 .unwrap(),
3276 Ordering::Less
3277 );
3278 assert_eq!(
3279 anchor_at_offset_1
3280 .cmp(&anchor_at_offset_2, &buffer)
3281 .unwrap(),
3282 Ordering::Less
3283 );
3284 assert_eq!(
3285 anchor_at_offset_0
3286 .cmp(&anchor_at_offset_2, &buffer)
3287 .unwrap(),
3288 Ordering::Less
3289 );
3290
3291 assert_eq!(
3292 anchor_at_offset_1
3293 .cmp(&anchor_at_offset_0, &buffer)
3294 .unwrap(),
3295 Ordering::Greater
3296 );
3297 assert_eq!(
3298 anchor_at_offset_2
3299 .cmp(&anchor_at_offset_1, &buffer)
3300 .unwrap(),
3301 Ordering::Greater
3302 );
3303 assert_eq!(
3304 anchor_at_offset_2
3305 .cmp(&anchor_at_offset_0, &buffer)
3306 .unwrap(),
3307 Ordering::Greater
3308 );
3309 buffer
3310 });
3311 }
3312
3313 #[gpui::test]
3314 fn test_anchors_at_start_and_end(cx: &mut gpui::MutableAppContext) {
3315 cx.add_model(|cx| {
3316 let mut buffer = Buffer::new(0, "", cx);
3317 let before_start_anchor = buffer.anchor_before(0);
3318 let after_end_anchor = buffer.anchor_after(0);
3319
3320 buffer.edit(vec![0..0], "abc", cx);
3321 assert_eq!(buffer.text(), "abc");
3322 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
3323 assert_eq!(after_end_anchor.to_offset(&buffer), 3);
3324
3325 let after_start_anchor = buffer.anchor_after(0);
3326 let before_end_anchor = buffer.anchor_before(3);
3327
3328 buffer.edit(vec![3..3], "def", cx);
3329 buffer.edit(vec![0..0], "ghi", cx);
3330 assert_eq!(buffer.text(), "ghiabcdef");
3331 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
3332 assert_eq!(after_start_anchor.to_offset(&buffer), 3);
3333 assert_eq!(before_end_anchor.to_offset(&buffer), 6);
3334 assert_eq!(after_end_anchor.to_offset(&buffer), 9);
3335 buffer
3336 });
3337 }
3338
3339 #[gpui::test]
3340 async fn test_is_dirty(mut cx: gpui::TestAppContext) {
3341 let dir = temp_tree(json!({
3342 "file1": "abc",
3343 "file2": "def",
3344 "file3": "ghi",
3345 }));
3346 let tree = Worktree::open_local(
3347 dir.path(),
3348 Default::default(),
3349 Arc::new(RealFs),
3350 &mut cx.to_async(),
3351 )
3352 .await
3353 .unwrap();
3354 tree.flush_fs_events(&cx).await;
3355 cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3356 .await;
3357
3358 let buffer1 = tree
3359 .update(&mut cx, |tree, cx| tree.open_buffer("file1", cx))
3360 .await
3361 .unwrap();
3362 let events = Rc::new(RefCell::new(Vec::new()));
3363
3364 // initially, the buffer isn't dirty.
3365 buffer1.update(&mut cx, |buffer, cx| {
3366 cx.subscribe(&buffer1, {
3367 let events = events.clone();
3368 move |_, event, _| events.borrow_mut().push(event.clone())
3369 });
3370
3371 assert!(!buffer.is_dirty());
3372 assert!(events.borrow().is_empty());
3373
3374 buffer.edit(vec![1..2], "", cx);
3375 });
3376
3377 // after the first edit, the buffer is dirty, and emits a dirtied event.
3378 buffer1.update(&mut cx, |buffer, cx| {
3379 assert!(buffer.text() == "ac");
3380 assert!(buffer.is_dirty());
3381 assert_eq!(*events.borrow(), &[Event::Edited, Event::Dirtied]);
3382 events.borrow_mut().clear();
3383 buffer.did_save(buffer.version(), buffer.file().unwrap().mtime, cx);
3384 });
3385
3386 // after saving, the buffer is not dirty, and emits a saved event.
3387 buffer1.update(&mut cx, |buffer, cx| {
3388 assert!(!buffer.is_dirty());
3389 assert_eq!(*events.borrow(), &[Event::Saved]);
3390 events.borrow_mut().clear();
3391
3392 buffer.edit(vec![1..1], "B", cx);
3393 buffer.edit(vec![2..2], "D", cx);
3394 });
3395
3396 // after editing again, the buffer is dirty, and emits another dirty event.
3397 buffer1.update(&mut cx, |buffer, cx| {
3398 assert!(buffer.text() == "aBDc");
3399 assert!(buffer.is_dirty());
3400 assert_eq!(
3401 *events.borrow(),
3402 &[Event::Edited, Event::Dirtied, Event::Edited],
3403 );
3404 events.borrow_mut().clear();
3405
3406 // TODO - currently, after restoring the buffer to its
3407 // previously-saved state, the is still considered dirty.
3408 buffer.edit(vec![1..3], "", cx);
3409 assert!(buffer.text() == "ac");
3410 assert!(buffer.is_dirty());
3411 });
3412
3413 assert_eq!(*events.borrow(), &[Event::Edited]);
3414
3415 // When a file is deleted, the buffer is considered dirty.
3416 let events = Rc::new(RefCell::new(Vec::new()));
3417 let buffer2 = tree
3418 .update(&mut cx, |tree, cx| tree.open_buffer("file2", cx))
3419 .await
3420 .unwrap();
3421 buffer2.update(&mut cx, |_, cx| {
3422 cx.subscribe(&buffer2, {
3423 let events = events.clone();
3424 move |_, event, _| events.borrow_mut().push(event.clone())
3425 });
3426 });
3427
3428 fs::remove_file(dir.path().join("file2")).unwrap();
3429 buffer2.condition(&cx, |b, _| b.is_dirty()).await;
3430 assert_eq!(
3431 *events.borrow(),
3432 &[Event::Dirtied, Event::FileHandleChanged]
3433 );
3434
3435 // When a file is already dirty when deleted, we don't emit a Dirtied event.
3436 let events = Rc::new(RefCell::new(Vec::new()));
3437 let buffer3 = tree
3438 .update(&mut cx, |tree, cx| tree.open_buffer("file3", cx))
3439 .await
3440 .unwrap();
3441 buffer3.update(&mut cx, |_, cx| {
3442 cx.subscribe(&buffer3, {
3443 let events = events.clone();
3444 move |_, event, _| events.borrow_mut().push(event.clone())
3445 });
3446 });
3447
3448 tree.flush_fs_events(&cx).await;
3449 buffer3.update(&mut cx, |buffer, cx| {
3450 buffer.edit(Some(0..0), "x", cx);
3451 });
3452 events.borrow_mut().clear();
3453 fs::remove_file(dir.path().join("file3")).unwrap();
3454 buffer3
3455 .condition(&cx, |_, _| !events.borrow().is_empty())
3456 .await;
3457 assert_eq!(*events.borrow(), &[Event::FileHandleChanged]);
3458 cx.read(|cx| assert!(buffer3.read(cx).is_dirty()));
3459 }
3460
3461 #[gpui::test]
3462 async fn test_file_changes_on_disk(mut cx: gpui::TestAppContext) {
3463 let initial_contents = "aaa\nbbbbb\nc\n";
3464 let dir = temp_tree(json!({ "the-file": initial_contents }));
3465 let tree = Worktree::open_local(
3466 dir.path(),
3467 Default::default(),
3468 Arc::new(RealFs),
3469 &mut cx.to_async(),
3470 )
3471 .await
3472 .unwrap();
3473 cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3474 .await;
3475
3476 let abs_path = dir.path().join("the-file");
3477 let buffer = tree
3478 .update(&mut cx, |tree, cx| {
3479 tree.open_buffer(Path::new("the-file"), cx)
3480 })
3481 .await
3482 .unwrap();
3483
3484 // Add a cursor at the start of each row.
3485 let selection_set_id = buffer.update(&mut cx, |buffer, cx| {
3486 assert!(!buffer.is_dirty());
3487 buffer.add_selection_set(
3488 (0..3)
3489 .map(|row| {
3490 let anchor = buffer.anchor_at(Point::new(row, 0), Bias::Right);
3491 Selection {
3492 id: row as usize,
3493 start: anchor.clone(),
3494 end: anchor,
3495 reversed: false,
3496 goal: SelectionGoal::None,
3497 }
3498 })
3499 .collect::<Vec<_>>(),
3500 cx,
3501 )
3502 });
3503
3504 // Change the file on disk, adding two new lines of text, and removing
3505 // one line.
3506 buffer.read_with(&cx, |buffer, _| {
3507 assert!(!buffer.is_dirty());
3508 assert!(!buffer.has_conflict());
3509 });
3510 let new_contents = "AAAA\naaa\nBB\nbbbbb\n";
3511 fs::write(&abs_path, new_contents).unwrap();
3512
3513 // Because the buffer was not modified, it is reloaded from disk. Its
3514 // contents are edited according to the diff between the old and new
3515 // file contents.
3516 buffer
3517 .condition(&cx, |buffer, _| buffer.text() != initial_contents)
3518 .await;
3519
3520 buffer.update(&mut cx, |buffer, _| {
3521 assert_eq!(buffer.text(), new_contents);
3522 assert!(!buffer.is_dirty());
3523 assert!(!buffer.has_conflict());
3524
3525 let set = buffer.selection_set(selection_set_id).unwrap();
3526 let cursor_positions = set
3527 .selections
3528 .iter()
3529 .map(|selection| {
3530 assert_eq!(selection.start, selection.end);
3531 selection.start.to_point(&*buffer)
3532 })
3533 .collect::<Vec<_>>();
3534 assert_eq!(
3535 cursor_positions,
3536 &[Point::new(1, 0), Point::new(3, 0), Point::new(4, 0),]
3537 );
3538 });
3539
3540 // Modify the buffer
3541 buffer.update(&mut cx, |buffer, cx| {
3542 buffer.edit(vec![0..0], " ", cx);
3543 assert!(buffer.is_dirty());
3544 });
3545
3546 // Change the file on disk again, adding blank lines to the beginning.
3547 fs::write(&abs_path, "\n\n\nAAAA\naaa\nBB\nbbbbb\n").unwrap();
3548
3549 // Becaues the buffer is modified, it doesn't reload from disk, but is
3550 // marked as having a conflict.
3551 buffer
3552 .condition(&cx, |buffer, _| buffer.has_conflict())
3553 .await;
3554 }
3555
3556 #[gpui::test]
3557 async fn test_apply_diff(mut cx: gpui::TestAppContext) {
3558 let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
3559 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
3560
3561 let text = "a\nccc\ndddd\nffffff\n";
3562 let diff = buffer.read_with(&cx, |b, cx| b.diff(text.into(), cx)).await;
3563 buffer.update(&mut cx, |b, cx| b.apply_diff(diff, cx));
3564 cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
3565
3566 let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
3567 let diff = buffer.read_with(&cx, |b, cx| b.diff(text.into(), cx)).await;
3568 buffer.update(&mut cx, |b, cx| b.apply_diff(diff, cx));
3569 cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
3570 }
3571
3572 #[gpui::test]
3573 fn test_undo_redo(cx: &mut gpui::MutableAppContext) {
3574 cx.add_model(|cx| {
3575 let mut buffer = Buffer::new(0, "1234", cx);
3576 // Set group interval to zero so as to not group edits in the undo stack.
3577 buffer.history.group_interval = Duration::from_secs(0);
3578
3579 buffer.edit(vec![1..1], "abx", cx);
3580 buffer.edit(vec![3..4], "yzef", cx);
3581 buffer.edit(vec![3..5], "cd", cx);
3582 assert_eq!(buffer.text(), "1abcdef234");
3583
3584 let transactions = buffer.history.undo_stack.clone();
3585 assert_eq!(transactions.len(), 3);
3586
3587 buffer.undo_or_redo(transactions[0].clone(), cx).unwrap();
3588 assert_eq!(buffer.text(), "1cdef234");
3589 buffer.undo_or_redo(transactions[0].clone(), cx).unwrap();
3590 assert_eq!(buffer.text(), "1abcdef234");
3591
3592 buffer.undo_or_redo(transactions[1].clone(), cx).unwrap();
3593 assert_eq!(buffer.text(), "1abcdx234");
3594 buffer.undo_or_redo(transactions[2].clone(), cx).unwrap();
3595 assert_eq!(buffer.text(), "1abx234");
3596 buffer.undo_or_redo(transactions[1].clone(), cx).unwrap();
3597 assert_eq!(buffer.text(), "1abyzef234");
3598 buffer.undo_or_redo(transactions[2].clone(), cx).unwrap();
3599 assert_eq!(buffer.text(), "1abcdef234");
3600
3601 buffer.undo_or_redo(transactions[2].clone(), cx).unwrap();
3602 assert_eq!(buffer.text(), "1abyzef234");
3603 buffer.undo_or_redo(transactions[0].clone(), cx).unwrap();
3604 assert_eq!(buffer.text(), "1yzef234");
3605 buffer.undo_or_redo(transactions[1].clone(), cx).unwrap();
3606 assert_eq!(buffer.text(), "1234");
3607
3608 buffer
3609 });
3610 }
3611
3612 #[gpui::test]
3613 fn test_history(cx: &mut gpui::MutableAppContext) {
3614 cx.add_model(|cx| {
3615 let mut now = Instant::now();
3616 let mut buffer = Buffer::new(0, "123456", cx);
3617
3618 let set_id =
3619 buffer.add_selection_set(buffer.selections_from_ranges(vec![4..4]).unwrap(), cx);
3620 buffer.start_transaction_at(Some(set_id), now).unwrap();
3621 buffer.edit(vec![2..4], "cd", cx);
3622 buffer.end_transaction_at(Some(set_id), now, cx).unwrap();
3623 assert_eq!(buffer.text(), "12cd56");
3624 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3625
3626 buffer.start_transaction_at(Some(set_id), now).unwrap();
3627 buffer
3628 .update_selection_set(
3629 set_id,
3630 buffer.selections_from_ranges(vec![1..3]).unwrap(),
3631 cx,
3632 )
3633 .unwrap();
3634 buffer.edit(vec![4..5], "e", cx);
3635 buffer.end_transaction_at(Some(set_id), now, cx).unwrap();
3636 assert_eq!(buffer.text(), "12cde6");
3637 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3638
3639 now += buffer.history.group_interval + Duration::from_millis(1);
3640 buffer.start_transaction_at(Some(set_id), now).unwrap();
3641 buffer
3642 .update_selection_set(
3643 set_id,
3644 buffer.selections_from_ranges(vec![2..2]).unwrap(),
3645 cx,
3646 )
3647 .unwrap();
3648 buffer.edit(vec![0..1], "a", cx);
3649 buffer.edit(vec![1..1], "b", cx);
3650 buffer.end_transaction_at(Some(set_id), now, cx).unwrap();
3651 assert_eq!(buffer.text(), "ab2cde6");
3652 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3653
3654 // Last transaction happened past the group interval, undo it on its
3655 // own.
3656 buffer.undo(cx);
3657 assert_eq!(buffer.text(), "12cde6");
3658 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3659
3660 // First two transactions happened within the group interval, undo them
3661 // together.
3662 buffer.undo(cx);
3663 assert_eq!(buffer.text(), "123456");
3664 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3665
3666 // Redo the first two transactions together.
3667 buffer.redo(cx);
3668 assert_eq!(buffer.text(), "12cde6");
3669 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3670
3671 // Redo the last transaction on its own.
3672 buffer.redo(cx);
3673 assert_eq!(buffer.text(), "ab2cde6");
3674 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3675
3676 buffer
3677 });
3678 }
3679
3680 #[gpui::test]
3681 fn test_concurrent_edits(cx: &mut gpui::MutableAppContext) {
3682 let text = "abcdef";
3683
3684 let buffer1 = cx.add_model(|cx| Buffer::new(1, text, cx));
3685 let buffer2 = cx.add_model(|cx| Buffer::new(2, text, cx));
3686 let buffer3 = cx.add_model(|cx| Buffer::new(3, text, cx));
3687
3688 let buf1_op = buffer1.update(cx, |buffer, cx| {
3689 buffer.edit(vec![1..2], "12", cx);
3690 assert_eq!(buffer.text(), "a12cdef");
3691 buffer.operations.last().unwrap().clone()
3692 });
3693 let buf2_op = buffer2.update(cx, |buffer, cx| {
3694 buffer.edit(vec![3..4], "34", cx);
3695 assert_eq!(buffer.text(), "abc34ef");
3696 buffer.operations.last().unwrap().clone()
3697 });
3698 let buf3_op = buffer3.update(cx, |buffer, cx| {
3699 buffer.edit(vec![5..6], "56", cx);
3700 assert_eq!(buffer.text(), "abcde56");
3701 buffer.operations.last().unwrap().clone()
3702 });
3703
3704 buffer1.update(cx, |buffer, _| {
3705 buffer.apply_op(buf2_op.clone()).unwrap();
3706 buffer.apply_op(buf3_op.clone()).unwrap();
3707 });
3708 buffer2.update(cx, |buffer, _| {
3709 buffer.apply_op(buf1_op.clone()).unwrap();
3710 buffer.apply_op(buf3_op.clone()).unwrap();
3711 });
3712 buffer3.update(cx, |buffer, _| {
3713 buffer.apply_op(buf1_op.clone()).unwrap();
3714 buffer.apply_op(buf2_op.clone()).unwrap();
3715 });
3716
3717 assert_eq!(buffer1.read(cx).text(), "a12c34e56");
3718 assert_eq!(buffer2.read(cx).text(), "a12c34e56");
3719 assert_eq!(buffer3.read(cx).text(), "a12c34e56");
3720 }
3721
3722 #[gpui::test]
3723 fn test_random_concurrent_edits(cx: &mut gpui::MutableAppContext) {
3724 use crate::test::Network;
3725
3726 let peers = env::var("PEERS")
3727 .map(|i| i.parse().expect("invalid `PEERS` variable"))
3728 .unwrap_or(5);
3729 let iterations = env::var("ITERATIONS")
3730 .map(|i| i.parse().expect("invalid `ITERATIONS` variable"))
3731 .unwrap_or(100);
3732 let operations = env::var("OPERATIONS")
3733 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3734 .unwrap_or(10);
3735 let start_seed =
3736 env::var("SEED").map_or(0, |seed| seed.parse().expect("invalid `SEED` variable"));
3737
3738 for seed in start_seed..start_seed + iterations {
3739 dbg!(seed);
3740 let mut rng = StdRng::seed_from_u64(seed);
3741
3742 let base_text_len = rng.gen_range(0..10);
3743 let base_text = RandomCharIter::new(&mut rng)
3744 .take(base_text_len)
3745 .collect::<String>();
3746 let mut replica_ids = Vec::new();
3747 let mut buffers = Vec::new();
3748 let mut network = Network::new(StdRng::seed_from_u64(seed));
3749
3750 for i in 0..peers {
3751 let buffer = cx.add_model(|cx| {
3752 let mut buf = Buffer::new(i as ReplicaId, base_text.as_str(), cx);
3753 buf.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
3754 buf
3755 });
3756 buffers.push(buffer);
3757 replica_ids.push(i as u16);
3758 network.add_peer(i as u16);
3759 }
3760
3761 log::info!("initial text: {:?}", base_text);
3762
3763 let mut mutation_count = operations;
3764 loop {
3765 let replica_index = rng.gen_range(0..peers);
3766 let replica_id = replica_ids[replica_index];
3767 buffers[replica_index].update(cx, |buffer, cx| match rng.gen_range(0..=100) {
3768 0..=50 if mutation_count != 0 => {
3769 buffer.randomly_mutate(&mut rng, cx);
3770 network.broadcast(buffer.replica_id, mem::take(&mut buffer.operations));
3771 log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
3772 mutation_count -= 1;
3773 }
3774 51..=70 if mutation_count != 0 => {
3775 buffer.randomly_undo_redo(&mut rng, cx);
3776 network.broadcast(buffer.replica_id, mem::take(&mut buffer.operations));
3777 mutation_count -= 1;
3778 }
3779 71..=100 if network.has_unreceived(replica_id) => {
3780 let ops = network.receive(replica_id);
3781 if !ops.is_empty() {
3782 log::info!(
3783 "peer {} applying {} ops from the network.",
3784 replica_id,
3785 ops.len()
3786 );
3787 buffer.apply_ops(ops, cx).unwrap();
3788 }
3789 }
3790 _ => {}
3791 });
3792
3793 if mutation_count == 0 && network.is_idle() {
3794 break;
3795 }
3796 }
3797
3798 let first_buffer = buffers[0].read(cx);
3799 for buffer in &buffers[1..] {
3800 let buffer = buffer.read(cx);
3801 assert_eq!(
3802 buffer.text(),
3803 first_buffer.text(),
3804 "Replica {} text != Replica 0 text",
3805 buffer.replica_id
3806 );
3807 assert_eq!(
3808 buffer.selection_sets().collect::<HashMap<_, _>>(),
3809 first_buffer.selection_sets().collect::<HashMap<_, _>>()
3810 );
3811 assert_eq!(
3812 buffer.all_selection_ranges().collect::<HashMap<_, _>>(),
3813 first_buffer
3814 .all_selection_ranges()
3815 .collect::<HashMap<_, _>>()
3816 );
3817 }
3818 }
3819 }
3820
3821 #[gpui::test]
3822 async fn test_reparse(mut cx: gpui::TestAppContext) {
3823 let app_state = cx.read(build_app_state);
3824 let rust_lang = app_state.languages.select_language("test.rs");
3825 assert!(rust_lang.is_some());
3826
3827 let buffer = cx.add_model(|cx| {
3828 let text = "fn a() {}".into();
3829 let buffer = Buffer::from_history(0, History::new(text), None, rust_lang.cloned(), cx);
3830 assert!(buffer.is_parsing());
3831 assert!(buffer.syntax_tree().is_none());
3832 buffer
3833 });
3834
3835 // Wait for the initial text to parse
3836 buffer
3837 .condition(&cx, |buffer, _| !buffer.is_parsing())
3838 .await;
3839 assert_eq!(
3840 get_tree_sexp(&buffer, &cx),
3841 concat!(
3842 "(source_file (function_item name: (identifier) ",
3843 "parameters: (parameters) ",
3844 "body: (block)))"
3845 )
3846 );
3847
3848 // Perform some edits (add parameter and variable reference)
3849 // Parsing doesn't begin until the transaction is complete
3850 buffer.update(&mut cx, |buf, cx| {
3851 buf.start_transaction(None).unwrap();
3852
3853 let offset = buf.text().find(")").unwrap();
3854 buf.edit(vec![offset..offset], "b: C", cx);
3855 assert!(!buf.is_parsing());
3856
3857 let offset = buf.text().find("}").unwrap();
3858 buf.edit(vec![offset..offset], " d; ", cx);
3859 assert!(!buf.is_parsing());
3860
3861 buf.end_transaction(None, cx).unwrap();
3862 assert_eq!(buf.text(), "fn a(b: C) { d; }");
3863 assert!(buf.is_parsing());
3864 });
3865 buffer
3866 .condition(&cx, |buffer, _| !buffer.is_parsing())
3867 .await;
3868 assert_eq!(
3869 get_tree_sexp(&buffer, &cx),
3870 concat!(
3871 "(source_file (function_item name: (identifier) ",
3872 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3873 "body: (block (identifier))))"
3874 )
3875 );
3876
3877 // Perform a series of edits without waiting for the current parse to complete:
3878 // * turn identifier into a field expression
3879 // * turn field expression into a method call
3880 // * add a turbofish to the method call
3881 buffer.update(&mut cx, |buf, cx| {
3882 let offset = buf.text().find(";").unwrap();
3883 buf.edit(vec![offset..offset], ".e", cx);
3884 assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
3885 assert!(buf.is_parsing());
3886 });
3887 buffer.update(&mut cx, |buf, cx| {
3888 let offset = buf.text().find(";").unwrap();
3889 buf.edit(vec![offset..offset], "(f)", cx);
3890 assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
3891 assert!(buf.is_parsing());
3892 });
3893 buffer.update(&mut cx, |buf, cx| {
3894 let offset = buf.text().find("(f)").unwrap();
3895 buf.edit(vec![offset..offset], "::<G>", cx);
3896 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3897 assert!(buf.is_parsing());
3898 });
3899 buffer
3900 .condition(&cx, |buffer, _| !buffer.is_parsing())
3901 .await;
3902 assert_eq!(
3903 get_tree_sexp(&buffer, &cx),
3904 concat!(
3905 "(source_file (function_item name: (identifier) ",
3906 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3907 "body: (block (call_expression ",
3908 "function: (generic_function ",
3909 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3910 "type_arguments: (type_arguments (type_identifier))) ",
3911 "arguments: (arguments (identifier))))))",
3912 )
3913 );
3914
3915 buffer.update(&mut cx, |buf, cx| {
3916 buf.undo(cx);
3917 assert_eq!(buf.text(), "fn a() {}");
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) ",
3928 "body: (block)))"
3929 )
3930 );
3931
3932 buffer.update(&mut cx, |buf, cx| {
3933 buf.redo(cx);
3934 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3935 assert!(buf.is_parsing());
3936 });
3937 buffer
3938 .condition(&cx, |buffer, _| !buffer.is_parsing())
3939 .await;
3940 assert_eq!(
3941 get_tree_sexp(&buffer, &cx),
3942 concat!(
3943 "(source_file (function_item name: (identifier) ",
3944 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3945 "body: (block (call_expression ",
3946 "function: (generic_function ",
3947 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3948 "type_arguments: (type_arguments (type_identifier))) ",
3949 "arguments: (arguments (identifier))))))",
3950 )
3951 );
3952
3953 fn get_tree_sexp(buffer: &ModelHandle<Buffer>, cx: &gpui::TestAppContext) -> String {
3954 buffer.read_with(cx, |buffer, _| {
3955 buffer.syntax_tree().unwrap().root_node().to_sexp()
3956 })
3957 }
3958 }
3959
3960 #[gpui::test]
3961 async fn test_enclosing_bracket_ranges(mut cx: gpui::TestAppContext) {
3962 use unindent::Unindent as _;
3963
3964 let app_state = cx.read(build_app_state);
3965 let rust_lang = app_state.languages.select_language("test.rs");
3966 assert!(rust_lang.is_some());
3967
3968 let buffer = cx.add_model(|cx| {
3969 let text = "
3970 mod x {
3971 mod y {
3972
3973 }
3974 }
3975 "
3976 .unindent()
3977 .into();
3978 Buffer::from_history(0, History::new(text), None, rust_lang.cloned(), cx)
3979 });
3980 buffer
3981 .condition(&cx, |buffer, _| !buffer.is_parsing())
3982 .await;
3983 buffer.read_with(&cx, |buf, _| {
3984 assert_eq!(
3985 buf.enclosing_bracket_point_ranges(Point::new(1, 6)..Point::new(1, 6)),
3986 Some((
3987 Point::new(0, 6)..Point::new(0, 7),
3988 Point::new(4, 0)..Point::new(4, 1)
3989 ))
3990 );
3991 assert_eq!(
3992 buf.enclosing_bracket_point_ranges(Point::new(1, 10)..Point::new(1, 10)),
3993 Some((
3994 Point::new(1, 10)..Point::new(1, 11),
3995 Point::new(3, 4)..Point::new(3, 5)
3996 ))
3997 );
3998 assert_eq!(
3999 buf.enclosing_bracket_point_ranges(Point::new(3, 5)..Point::new(3, 5)),
4000 Some((
4001 Point::new(1, 10)..Point::new(1, 11),
4002 Point::new(3, 4)..Point::new(3, 5)
4003 ))
4004 );
4005 });
4006 }
4007
4008 impl Buffer {
4009 fn random_byte_range(&mut self, start_offset: usize, rng: &mut impl Rng) -> Range<usize> {
4010 let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
4011 let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
4012 start..end
4013 }
4014
4015 pub fn randomly_edit<T>(
4016 &mut self,
4017 rng: &mut T,
4018 old_range_count: usize,
4019 cx: &mut ModelContext<Self>,
4020 ) -> (Vec<Range<usize>>, String)
4021 where
4022 T: Rng,
4023 {
4024 let mut old_ranges: Vec<Range<usize>> = Vec::new();
4025 for _ in 0..old_range_count {
4026 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
4027 if last_end > self.len() {
4028 break;
4029 }
4030 old_ranges.push(self.random_byte_range(last_end, rng));
4031 }
4032 let new_text_len = rng.gen_range(0..10);
4033 let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
4034 log::info!(
4035 "mutating buffer {} at {:?}: {:?}",
4036 self.replica_id,
4037 old_ranges,
4038 new_text
4039 );
4040 self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
4041 (old_ranges, new_text)
4042 }
4043
4044 pub fn randomly_mutate<T>(
4045 &mut self,
4046 rng: &mut T,
4047 cx: &mut ModelContext<Self>,
4048 ) -> (Vec<Range<usize>>, String)
4049 where
4050 T: Rng,
4051 {
4052 let (old_ranges, new_text) = self.randomly_edit(rng, 5, cx);
4053
4054 // Randomly add, remove or mutate selection sets.
4055 let replica_selection_sets = &self
4056 .selection_sets()
4057 .map(|(set_id, _)| *set_id)
4058 .filter(|set_id| self.replica_id == set_id.replica_id)
4059 .collect::<Vec<_>>();
4060 let set_id = replica_selection_sets.choose(rng);
4061 if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
4062 self.remove_selection_set(*set_id.unwrap(), cx).unwrap();
4063 } else {
4064 let mut ranges = Vec::new();
4065 for _ in 0..5 {
4066 ranges.push(self.random_byte_range(0, rng));
4067 }
4068 let new_selections = self.selections_from_ranges(ranges).unwrap();
4069
4070 if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
4071 self.add_selection_set(new_selections, cx);
4072 } else {
4073 self.update_selection_set(*set_id.unwrap(), new_selections, cx)
4074 .unwrap();
4075 }
4076 }
4077
4078 (old_ranges, new_text)
4079 }
4080
4081 pub fn randomly_undo_redo(&mut self, rng: &mut impl Rng, cx: &mut ModelContext<Self>) {
4082 for _ in 0..rng.gen_range(1..=5) {
4083 if let Some(transaction) = self.history.undo_stack.choose(rng).cloned() {
4084 log::info!(
4085 "undoing buffer {} transaction {:?}",
4086 self.replica_id,
4087 transaction
4088 );
4089 self.undo_or_redo(transaction, cx).unwrap();
4090 }
4091 }
4092 }
4093
4094 fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
4095 where
4096 I: IntoIterator<Item = Range<usize>>,
4097 {
4098 static NEXT_SELECTION_ID: AtomicUsize = AtomicUsize::new(0);
4099
4100 let mut ranges = ranges.into_iter().collect::<Vec<_>>();
4101 ranges.sort_unstable_by_key(|range| range.start);
4102
4103 let mut selections = Vec::with_capacity(ranges.len());
4104 for range in ranges {
4105 if range.start > range.end {
4106 selections.push(Selection {
4107 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
4108 start: self.anchor_before(range.end),
4109 end: self.anchor_before(range.start),
4110 reversed: true,
4111 goal: SelectionGoal::None,
4112 });
4113 } else {
4114 selections.push(Selection {
4115 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
4116 start: self.anchor_after(range.start),
4117 end: self.anchor_before(range.end),
4118 reversed: false,
4119 goal: SelectionGoal::None,
4120 });
4121 }
4122 }
4123 Ok(selections)
4124 }
4125
4126 pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> {
4127 Ok(self
4128 .selection_set(set_id)?
4129 .selections
4130 .iter()
4131 .map(move |selection| {
4132 let start = selection.start.to_offset(self);
4133 let end = selection.end.to_offset(self);
4134 if selection.reversed {
4135 end..start
4136 } else {
4137 start..end
4138 }
4139 })
4140 .collect())
4141 }
4142
4143 pub fn all_selection_ranges<'a>(
4144 &'a self,
4145 ) -> impl 'a + Iterator<Item = (SelectionSetId, Vec<Range<usize>>)> {
4146 self.selections
4147 .keys()
4148 .map(move |set_id| (*set_id, self.selection_ranges(*set_id).unwrap()))
4149 }
4150
4151 pub fn enclosing_bracket_point_ranges<T: ToOffset>(
4152 &self,
4153 range: Range<T>,
4154 ) -> Option<(Range<Point>, Range<Point>)> {
4155 self.enclosing_bracket_ranges(range).map(|(start, end)| {
4156 let point_start = start.start.to_point(self)..start.end.to_point(self);
4157 let point_end = end.start.to_point(self)..end.end.to_point(self);
4158 (point_start, point_end)
4159 })
4160 }
4161 }
4162}