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