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