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