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