1use crate::diagnostic_set::{DiagnosticEntry, DiagnosticGroup};
2pub use crate::{
3 diagnostic_set::DiagnosticSet,
4 highlight_map::{HighlightId, HighlightMap},
5 proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, LanguageServerConfig,
6 PLAIN_TEXT,
7};
8use anyhow::{anyhow, Result};
9use clock::ReplicaId;
10use futures::FutureExt as _;
11use gpui::{fonts::HighlightStyle, AppContext, Entity, ModelContext, MutableAppContext, Task};
12use lazy_static::lazy_static;
13use lsp::LanguageServer;
14use parking_lot::Mutex;
15use postage::{prelude::Stream, sink::Sink, watch};
16use similar::{ChangeTag, TextDiff};
17use smol::future::yield_now;
18use std::{
19 any::Any,
20 cell::RefCell,
21 cmp::{self, Ordering},
22 collections::{BTreeMap, HashMap},
23 ffi::OsString,
24 future::Future,
25 iter::{Iterator, Peekable},
26 ops::{Deref, DerefMut, Range, Sub},
27 path::{Path, PathBuf},
28 str,
29 sync::Arc,
30 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
31 vec,
32};
33use sum_tree::TreeMap;
34use text::{operation_queue::OperationQueue, rope::TextDimension};
35pub use text::{Buffer as TextBuffer, Operation as _, *};
36use theme::SyntaxTheme;
37use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
38use util::{post_inc, TryFutureExt as _};
39
40#[cfg(any(test, feature = "test-support"))]
41pub use tree_sitter_rust;
42
43pub use lsp::DiagnosticSeverity;
44
45thread_local! {
46 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
47}
48
49lazy_static! {
50 static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
51}
52
53// TODO - Make this configurable
54const INDENT_SIZE: u32 = 4;
55
56pub struct Buffer {
57 text: TextBuffer,
58 file: Option<Box<dyn File>>,
59 saved_version: clock::Global,
60 saved_mtime: SystemTime,
61 language: Option<Arc<Language>>,
62 autoindent_requests: Vec<Arc<AutoindentRequest>>,
63 pending_autoindent: Option<Task<()>>,
64 sync_parse_timeout: Duration,
65 syntax_tree: Mutex<Option<SyntaxTree>>,
66 parsing_in_background: bool,
67 parse_count: usize,
68 diagnostics: DiagnosticSet,
69 remote_selections: TreeMap<ReplicaId, SelectionSet>,
70 selections_update_count: usize,
71 diagnostics_update_count: usize,
72 language_server: Option<LanguageServerState>,
73 deferred_ops: OperationQueue<Operation>,
74 #[cfg(test)]
75 pub(crate) operations: Vec<Operation>,
76}
77
78pub struct BufferSnapshot {
79 text: text::BufferSnapshot,
80 tree: Option<Tree>,
81 diagnostics: DiagnosticSet,
82 diagnostics_update_count: usize,
83 remote_selections: TreeMap<ReplicaId, SelectionSet>,
84 selections_update_count: usize,
85 is_parsing: bool,
86 language: Option<Arc<Language>>,
87 parse_count: usize,
88}
89
90#[derive(Clone, Debug)]
91struct SelectionSet {
92 selections: Arc<[Selection<Anchor>]>,
93 lamport_timestamp: clock::Lamport,
94}
95
96#[derive(Clone, Debug, PartialEq, Eq)]
97pub struct GroupId {
98 source: Arc<str>,
99 id: usize,
100}
101
102#[derive(Clone, Debug, PartialEq, Eq)]
103pub struct Diagnostic {
104 pub code: Option<String>,
105 pub severity: DiagnosticSeverity,
106 pub message: String,
107 pub group_id: usize,
108 pub is_valid: bool,
109 pub is_primary: bool,
110 pub is_disk_based: bool,
111}
112
113struct LanguageServerState {
114 server: Arc<LanguageServer>,
115 latest_snapshot: watch::Sender<Option<LanguageServerSnapshot>>,
116 pending_snapshots: BTreeMap<usize, LanguageServerSnapshot>,
117 next_version: usize,
118 _maintain_server: Task<Option<()>>,
119}
120
121#[derive(Clone)]
122struct LanguageServerSnapshot {
123 buffer_snapshot: text::BufferSnapshot,
124 version: usize,
125 path: Arc<Path>,
126}
127
128#[derive(Clone, Debug)]
129pub enum Operation {
130 Buffer(text::Operation),
131 UpdateDiagnostics {
132 diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
133 lamport_timestamp: clock::Lamport,
134 },
135 UpdateSelections {
136 replica_id: ReplicaId,
137 selections: Arc<[Selection<Anchor>]>,
138 lamport_timestamp: clock::Lamport,
139 },
140}
141
142#[derive(Clone, Debug, Eq, PartialEq)]
143pub enum Event {
144 Edited,
145 Dirtied,
146 Saved,
147 FileHandleChanged,
148 Reloaded,
149 Reparsed,
150 DiagnosticsUpdated,
151 Closed,
152}
153
154pub trait File {
155 fn mtime(&self) -> SystemTime;
156
157 /// Returns the path of this file relative to the worktree's root directory.
158 fn path(&self) -> &Arc<Path>;
159
160 /// Returns the absolute path of this file.
161 fn abs_path(&self) -> Option<PathBuf>;
162
163 /// Returns the path of this file relative to the worktree's parent directory (this means it
164 /// includes the name of the worktree's root folder).
165 fn full_path(&self) -> PathBuf;
166
167 /// Returns the last component of this handle's absolute path. If this handle refers to the root
168 /// of its worktree, then this method will return the name of the worktree itself.
169 fn file_name(&self) -> Option<OsString>;
170
171 fn is_deleted(&self) -> bool;
172
173 fn save(
174 &self,
175 buffer_id: u64,
176 text: Rope,
177 version: clock::Global,
178 cx: &mut MutableAppContext,
179 ) -> Task<Result<(clock::Global, SystemTime)>>;
180
181 fn load_local(&self, cx: &AppContext) -> Option<Task<Result<String>>>;
182
183 fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
184
185 fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
186
187 fn as_any(&self) -> &dyn Any;
188}
189
190struct QueryCursorHandle(Option<QueryCursor>);
191
192#[derive(Clone)]
193struct SyntaxTree {
194 tree: Tree,
195 version: clock::Global,
196}
197
198#[derive(Clone)]
199struct AutoindentRequest {
200 before_edit: BufferSnapshot,
201 edited: Vec<Anchor>,
202 inserted: Option<Vec<Range<Anchor>>>,
203}
204
205#[derive(Debug)]
206struct IndentSuggestion {
207 basis_row: u32,
208 indent: bool,
209}
210
211struct TextProvider<'a>(&'a Rope);
212
213struct BufferChunkHighlights<'a> {
214 captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
215 next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
216 stack: Vec<(usize, HighlightId)>,
217 highlight_map: HighlightMap,
218 theme: &'a SyntaxTheme,
219 _query_cursor: QueryCursorHandle,
220}
221
222pub struct BufferChunks<'a> {
223 range: Range<usize>,
224 chunks: rope::Chunks<'a>,
225 diagnostic_endpoints: Peekable<vec::IntoIter<DiagnosticEndpoint>>,
226 error_depth: usize,
227 warning_depth: usize,
228 information_depth: usize,
229 hint_depth: usize,
230 highlights: Option<BufferChunkHighlights<'a>>,
231}
232
233#[derive(Clone, Copy, Debug, Default)]
234pub struct Chunk<'a> {
235 pub text: &'a str,
236 pub highlight_style: Option<HighlightStyle>,
237 pub diagnostic: Option<DiagnosticSeverity>,
238}
239
240pub(crate) struct Diff {
241 base_version: clock::Global,
242 new_text: Arc<str>,
243 changes: Vec<(ChangeTag, usize)>,
244}
245
246#[derive(Clone, Copy)]
247struct DiagnosticEndpoint {
248 offset: usize,
249 is_start: bool,
250 severity: DiagnosticSeverity,
251}
252
253impl Buffer {
254 pub fn new<T: Into<Arc<str>>>(
255 replica_id: ReplicaId,
256 base_text: T,
257 cx: &mut ModelContext<Self>,
258 ) -> Self {
259 Self::build(
260 TextBuffer::new(
261 replica_id,
262 cx.model_id() as u64,
263 History::new(base_text.into()),
264 ),
265 None,
266 )
267 }
268
269 pub fn from_file<T: Into<Arc<str>>>(
270 replica_id: ReplicaId,
271 base_text: T,
272 file: Box<dyn File>,
273 cx: &mut ModelContext<Self>,
274 ) -> Self {
275 Self::build(
276 TextBuffer::new(
277 replica_id,
278 cx.model_id() as u64,
279 History::new(base_text.into()),
280 ),
281 Some(file),
282 )
283 }
284
285 pub fn from_proto(
286 replica_id: ReplicaId,
287 message: proto::Buffer,
288 file: Option<Box<dyn File>>,
289 cx: &mut ModelContext<Self>,
290 ) -> Result<Self> {
291 let fragments_len = message.fragments.len();
292 let buffer = TextBuffer::from_parts(
293 replica_id,
294 message.id,
295 &message.visible_text,
296 &message.deleted_text,
297 message
298 .undo_map
299 .into_iter()
300 .map(proto::deserialize_undo_map_entry),
301 message
302 .fragments
303 .into_iter()
304 .enumerate()
305 .map(|(i, fragment)| {
306 proto::deserialize_buffer_fragment(fragment, i, fragments_len)
307 }),
308 message.lamport_timestamp,
309 From::from(message.version),
310 );
311 let mut this = Self::build(buffer, file);
312 for selection_set in message.selections {
313 this.remote_selections.insert(
314 selection_set.replica_id as ReplicaId,
315 SelectionSet {
316 selections: proto::deserialize_selections(selection_set.selections),
317 lamport_timestamp: clock::Lamport {
318 replica_id: selection_set.replica_id as ReplicaId,
319 value: selection_set.lamport_timestamp,
320 },
321 },
322 );
323 }
324 let snapshot = this.snapshot();
325 let entries = proto::deserialize_diagnostics(message.diagnostics);
326 this.apply_diagnostic_update(
327 DiagnosticSet::from_sorted_entries(entries.into_iter().cloned(), &snapshot),
328 cx,
329 );
330
331 let deferred_ops = message
332 .deferred_operations
333 .into_iter()
334 .map(proto::deserialize_operation)
335 .collect::<Result<Vec<_>>>()?;
336 this.apply_ops(deferred_ops, cx)?;
337
338 Ok(this)
339 }
340
341 pub fn to_proto(&self) -> proto::Buffer {
342 proto::Buffer {
343 id: self.remote_id(),
344 visible_text: self.text.text(),
345 deleted_text: self.text.deleted_text(),
346 undo_map: self
347 .text
348 .undo_history()
349 .map(proto::serialize_undo_map_entry)
350 .collect(),
351 version: From::from(&self.version),
352 lamport_timestamp: self.lamport_clock.value,
353 fragments: self
354 .text
355 .fragments()
356 .map(proto::serialize_buffer_fragment)
357 .collect(),
358 selections: self
359 .remote_selections
360 .iter()
361 .map(|(replica_id, set)| proto::SelectionSet {
362 replica_id: *replica_id as u32,
363 selections: proto::serialize_selections(&set.selections),
364 lamport_timestamp: set.lamport_timestamp.value,
365 })
366 .collect(),
367 diagnostics: proto::serialize_diagnostics(self.diagnostics.iter()),
368 deferred_operations: self
369 .deferred_ops
370 .iter()
371 .map(proto::serialize_operation)
372 .chain(
373 self.text
374 .deferred_ops()
375 .map(|op| proto::serialize_operation(&Operation::Buffer(op.clone()))),
376 )
377 .collect(),
378 }
379 }
380
381 pub fn with_language(
382 mut self,
383 language: Option<Arc<Language>>,
384 language_server: Option<Arc<LanguageServer>>,
385 cx: &mut ModelContext<Self>,
386 ) -> Self {
387 self.set_language(language, language_server, cx);
388 self
389 }
390
391 fn build(buffer: TextBuffer, file: Option<Box<dyn File>>) -> Self {
392 let saved_mtime;
393 if let Some(file) = file.as_ref() {
394 saved_mtime = file.mtime();
395 } else {
396 saved_mtime = UNIX_EPOCH;
397 }
398
399 Self {
400 saved_mtime,
401 saved_version: buffer.version(),
402 text: buffer,
403 file,
404 syntax_tree: Mutex::new(None),
405 parsing_in_background: false,
406 parse_count: 0,
407 sync_parse_timeout: Duration::from_millis(1),
408 autoindent_requests: Default::default(),
409 pending_autoindent: Default::default(),
410 language: None,
411 remote_selections: Default::default(),
412 selections_update_count: 0,
413 diagnostics: Default::default(),
414 diagnostics_update_count: 0,
415 language_server: None,
416 deferred_ops: OperationQueue::new(),
417 #[cfg(test)]
418 operations: Default::default(),
419 }
420 }
421
422 pub fn snapshot(&self) -> BufferSnapshot {
423 BufferSnapshot {
424 text: self.text.snapshot(),
425 tree: self.syntax_tree(),
426 remote_selections: self.remote_selections.clone(),
427 diagnostics: self.diagnostics.clone(),
428 diagnostics_update_count: self.diagnostics_update_count,
429 is_parsing: self.parsing_in_background,
430 language: self.language.clone(),
431 parse_count: self.parse_count,
432 selections_update_count: self.selections_update_count,
433 }
434 }
435
436 pub fn file(&self) -> Option<&dyn File> {
437 self.file.as_deref()
438 }
439
440 pub fn save(
441 &mut self,
442 cx: &mut ModelContext<Self>,
443 ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
444 let file = self
445 .file
446 .as_ref()
447 .ok_or_else(|| anyhow!("buffer has no file"))?;
448 let text = self.as_rope().clone();
449 let version = self.version();
450 let save = file.save(self.remote_id(), text, version, cx.as_mut());
451 Ok(cx.spawn(|this, mut cx| async move {
452 let (version, mtime) = save.await?;
453 this.update(&mut cx, |this, cx| {
454 this.did_save(version.clone(), mtime, None, cx);
455 });
456 Ok((version, mtime))
457 }))
458 }
459
460 pub fn set_language(
461 &mut self,
462 language: Option<Arc<Language>>,
463 language_server: Option<Arc<lsp::LanguageServer>>,
464 cx: &mut ModelContext<Self>,
465 ) {
466 self.language = language;
467 self.language_server = if let Some(server) = language_server {
468 let (latest_snapshot_tx, mut latest_snapshot_rx) = watch::channel();
469 Some(LanguageServerState {
470 latest_snapshot: latest_snapshot_tx,
471 pending_snapshots: Default::default(),
472 next_version: 0,
473 server: server.clone(),
474 _maintain_server: cx.background().spawn(
475 async move {
476 let mut prev_snapshot: Option<LanguageServerSnapshot> = None;
477 while let Some(snapshot) = latest_snapshot_rx.recv().await {
478 if let Some(snapshot) = snapshot {
479 let uri = lsp::Url::from_file_path(&snapshot.path).unwrap();
480 if let Some(prev_snapshot) = prev_snapshot {
481 let changes = lsp::DidChangeTextDocumentParams {
482 text_document: lsp::VersionedTextDocumentIdentifier::new(
483 uri,
484 snapshot.version as i32,
485 ),
486 content_changes: snapshot
487 .buffer_snapshot
488 .edits_since::<(PointUtf16, usize)>(
489 prev_snapshot.buffer_snapshot.version(),
490 )
491 .map(|edit| {
492 let edit_start = edit.new.start.0;
493 let edit_end = edit_start
494 + (edit.old.end.0 - edit.old.start.0);
495 let new_text = snapshot
496 .buffer_snapshot
497 .text_for_range(
498 edit.new.start.1..edit.new.end.1,
499 )
500 .collect();
501 lsp::TextDocumentContentChangeEvent {
502 range: Some(lsp::Range::new(
503 lsp::Position::new(
504 edit_start.row,
505 edit_start.column,
506 ),
507 lsp::Position::new(
508 edit_end.row,
509 edit_end.column,
510 ),
511 )),
512 range_length: None,
513 text: new_text,
514 }
515 })
516 .collect(),
517 };
518 server
519 .notify::<lsp::notification::DidChangeTextDocument>(changes)
520 .await?;
521 } else {
522 server
523 .notify::<lsp::notification::DidOpenTextDocument>(
524 lsp::DidOpenTextDocumentParams {
525 text_document: lsp::TextDocumentItem::new(
526 uri,
527 Default::default(),
528 snapshot.version as i32,
529 snapshot.buffer_snapshot.text().to_string(),
530 ),
531 },
532 )
533 .await?;
534 }
535
536 prev_snapshot = Some(snapshot);
537 }
538 }
539 Ok(())
540 }
541 .log_err(),
542 ),
543 })
544 } else {
545 None
546 };
547
548 self.reparse(cx);
549 self.update_language_server();
550 }
551
552 pub fn did_save(
553 &mut self,
554 version: clock::Global,
555 mtime: SystemTime,
556 new_file: Option<Box<dyn File>>,
557 cx: &mut ModelContext<Self>,
558 ) {
559 self.saved_mtime = mtime;
560 self.saved_version = version;
561 if let Some(new_file) = new_file {
562 self.file = Some(new_file);
563 }
564 if let Some(state) = &self.language_server {
565 cx.background()
566 .spawn(
567 state
568 .server
569 .notify::<lsp::notification::DidSaveTextDocument>(
570 lsp::DidSaveTextDocumentParams {
571 text_document: lsp::TextDocumentIdentifier {
572 uri: lsp::Url::from_file_path(
573 self.file.as_ref().unwrap().abs_path().unwrap(),
574 )
575 .unwrap(),
576 },
577 text: None,
578 },
579 ),
580 )
581 .detach()
582 }
583 cx.emit(Event::Saved);
584 }
585
586 pub fn file_updated(
587 &mut self,
588 new_file: Box<dyn File>,
589 cx: &mut ModelContext<Self>,
590 ) -> Option<Task<()>> {
591 let old_file = self.file.as_ref()?;
592 let mut file_changed = false;
593 let mut task = None;
594
595 if new_file.path() != old_file.path() {
596 file_changed = true;
597 }
598
599 if new_file.is_deleted() {
600 if !old_file.is_deleted() {
601 file_changed = true;
602 if !self.is_dirty() {
603 cx.emit(Event::Dirtied);
604 }
605 }
606 } else {
607 let new_mtime = new_file.mtime();
608 if new_mtime != old_file.mtime() {
609 file_changed = true;
610
611 if !self.is_dirty() {
612 task = Some(cx.spawn(|this, mut cx| {
613 async move {
614 let new_text = this.read_with(&cx, |this, cx| {
615 this.file.as_ref().and_then(|file| file.load_local(cx))
616 });
617 if let Some(new_text) = new_text {
618 let new_text = new_text.await?;
619 let diff = this
620 .read_with(&cx, |this, cx| this.diff(new_text.into(), cx))
621 .await;
622 this.update(&mut cx, |this, cx| {
623 if this.apply_diff(diff, cx) {
624 this.saved_version = this.version();
625 this.saved_mtime = new_mtime;
626 cx.emit(Event::Reloaded);
627 }
628 });
629 }
630 Ok(())
631 }
632 .log_err()
633 .map(drop)
634 }));
635 }
636 }
637 }
638
639 if file_changed {
640 cx.emit(Event::FileHandleChanged);
641 }
642 self.file = Some(new_file);
643 task
644 }
645
646 pub fn close(&mut self, cx: &mut ModelContext<Self>) {
647 cx.emit(Event::Closed);
648 }
649
650 pub fn language(&self) -> Option<&Arc<Language>> {
651 self.language.as_ref()
652 }
653
654 pub fn parse_count(&self) -> usize {
655 self.parse_count
656 }
657
658 pub fn selections_update_count(&self) -> usize {
659 self.selections_update_count
660 }
661
662 pub fn diagnostics_update_count(&self) -> usize {
663 self.diagnostics_update_count
664 }
665
666 pub(crate) fn syntax_tree(&self) -> Option<Tree> {
667 if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
668 self.interpolate_tree(syntax_tree);
669 Some(syntax_tree.tree.clone())
670 } else {
671 None
672 }
673 }
674
675 #[cfg(any(test, feature = "test-support"))]
676 pub fn is_parsing(&self) -> bool {
677 self.parsing_in_background
678 }
679
680 #[cfg(test)]
681 pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
682 self.sync_parse_timeout = timeout;
683 }
684
685 fn reparse(&mut self, cx: &mut ModelContext<Self>) -> bool {
686 if self.parsing_in_background {
687 return false;
688 }
689
690 if let Some(grammar) = self.grammar().cloned() {
691 let old_tree = self.syntax_tree();
692 let text = self.as_rope().clone();
693 let parsed_version = self.version();
694 let parse_task = cx.background().spawn({
695 let grammar = grammar.clone();
696 async move { Self::parse_text(&text, old_tree, &grammar) }
697 });
698
699 match cx
700 .background()
701 .block_with_timeout(self.sync_parse_timeout, parse_task)
702 {
703 Ok(new_tree) => {
704 self.did_finish_parsing(new_tree, parsed_version, cx);
705 return true;
706 }
707 Err(parse_task) => {
708 self.parsing_in_background = true;
709 cx.spawn(move |this, mut cx| async move {
710 let new_tree = parse_task.await;
711 this.update(&mut cx, move |this, cx| {
712 let grammar_changed = this
713 .grammar()
714 .map_or(true, |curr_grammar| !Arc::ptr_eq(&grammar, curr_grammar));
715 let parse_again =
716 this.version.changed_since(&parsed_version) || grammar_changed;
717 this.parsing_in_background = false;
718 this.did_finish_parsing(new_tree, parsed_version, cx);
719
720 if parse_again && this.reparse(cx) {
721 return;
722 }
723 });
724 })
725 .detach();
726 }
727 }
728 }
729 false
730 }
731
732 fn parse_text(text: &Rope, old_tree: Option<Tree>, grammar: &Grammar) -> Tree {
733 PARSER.with(|parser| {
734 let mut parser = parser.borrow_mut();
735 parser
736 .set_language(grammar.ts_language)
737 .expect("incompatible grammar");
738 let mut chunks = text.chunks_in_range(0..text.len());
739 let tree = parser
740 .parse_with(
741 &mut move |offset, _| {
742 chunks.seek(offset);
743 chunks.next().unwrap_or("").as_bytes()
744 },
745 old_tree.as_ref(),
746 )
747 .unwrap();
748 tree
749 })
750 }
751
752 fn interpolate_tree(&self, tree: &mut SyntaxTree) {
753 for edit in self.edits_since::<(usize, Point)>(&tree.version) {
754 let (bytes, lines) = edit.flatten();
755 tree.tree.edit(&InputEdit {
756 start_byte: bytes.new.start,
757 old_end_byte: bytes.new.start + bytes.old.len(),
758 new_end_byte: bytes.new.end,
759 start_position: lines.new.start.to_ts_point(),
760 old_end_position: (lines.new.start + (lines.old.end - lines.old.start))
761 .to_ts_point(),
762 new_end_position: lines.new.end.to_ts_point(),
763 });
764 }
765 tree.version = self.version();
766 }
767
768 fn did_finish_parsing(
769 &mut self,
770 tree: Tree,
771 version: clock::Global,
772 cx: &mut ModelContext<Self>,
773 ) {
774 self.parse_count += 1;
775 *self.syntax_tree.lock() = Some(SyntaxTree { tree, version });
776 self.request_autoindent(cx);
777 cx.emit(Event::Reparsed);
778 cx.notify();
779 }
780
781 pub fn update_diagnostics<T>(
782 &mut self,
783 version: Option<i32>,
784 mut diagnostics: Vec<DiagnosticEntry<T>>,
785 cx: &mut ModelContext<Self>,
786 ) -> Result<Operation>
787 where
788 T: Copy + Ord + TextDimension + Sub<Output = T> + Clip + ToPoint,
789 {
790 fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
791 Ordering::Equal
792 .then_with(|| b.is_primary.cmp(&a.is_primary))
793 .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
794 .then_with(|| a.severity.cmp(&b.severity))
795 .then_with(|| a.message.cmp(&b.message))
796 }
797
798 let version = version.map(|version| version as usize);
799 let content = if let Some(version) = version {
800 let language_server = self.language_server.as_mut().unwrap();
801 language_server
802 .pending_snapshots
803 .retain(|&v, _| v >= version);
804 let snapshot = language_server
805 .pending_snapshots
806 .get(&version)
807 .ok_or_else(|| anyhow!("missing snapshot"))?;
808 &snapshot.buffer_snapshot
809 } else {
810 self.deref()
811 };
812
813 diagnostics.sort_unstable_by(|a, b| {
814 Ordering::Equal
815 .then_with(|| a.range.start.cmp(&b.range.start))
816 .then_with(|| b.range.end.cmp(&a.range.end))
817 .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
818 });
819
820 let mut sanitized_diagnostics = Vec::new();
821 let mut edits_since_save = content.edits_since::<T>(&self.saved_version).peekable();
822 let mut last_edit_old_end = T::default();
823 let mut last_edit_new_end = T::default();
824 'outer: for entry in diagnostics {
825 let mut start = entry.range.start;
826 let mut end = entry.range.end;
827
828 // Some diagnostics are based on files on disk instead of buffers'
829 // current contents. Adjust these diagnostics' ranges to reflect
830 // any unsaved edits.
831 if entry.diagnostic.is_disk_based {
832 while let Some(edit) = edits_since_save.peek() {
833 if edit.old.end <= start {
834 last_edit_old_end = edit.old.end;
835 last_edit_new_end = edit.new.end;
836 edits_since_save.next();
837 } else if edit.old.start <= end && edit.old.end >= start {
838 continue 'outer;
839 } else {
840 break;
841 }
842 }
843
844 let start_overshoot = start - last_edit_old_end;
845 start = last_edit_new_end;
846 start.add_assign(&start_overshoot);
847
848 let end_overshoot = end - last_edit_old_end;
849 end = last_edit_new_end;
850 end.add_assign(&end_overshoot);
851 }
852
853 let range = start.clip(Bias::Left, content)..end.clip(Bias::Right, content);
854 let mut range = range.start.to_point(content)..range.end.to_point(content);
855 // Expand empty ranges by one character
856 if range.start == range.end {
857 range.end.column += 1;
858 range.end = content.clip_point(range.end, Bias::Right);
859 if range.start == range.end && range.end.column > 0 {
860 range.start.column -= 1;
861 range.start = content.clip_point(range.start, Bias::Left);
862 }
863 }
864
865 sanitized_diagnostics.push(DiagnosticEntry {
866 range,
867 diagnostic: entry.diagnostic,
868 });
869 }
870 drop(edits_since_save);
871
872 let set = DiagnosticSet::new(sanitized_diagnostics, content);
873 self.apply_diagnostic_update(set.clone(), cx);
874 Ok(Operation::UpdateDiagnostics {
875 diagnostics: set.iter().cloned().collect(),
876 lamport_timestamp: self.text.lamport_clock.tick(),
877 })
878 }
879
880 fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
881 if let Some(indent_columns) = self.compute_autoindents() {
882 let indent_columns = cx.background().spawn(indent_columns);
883 match cx
884 .background()
885 .block_with_timeout(Duration::from_micros(500), indent_columns)
886 {
887 Ok(indent_columns) => self.apply_autoindents(indent_columns, cx),
888 Err(indent_columns) => {
889 self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
890 let indent_columns = indent_columns.await;
891 this.update(&mut cx, |this, cx| {
892 this.apply_autoindents(indent_columns, cx);
893 });
894 }));
895 }
896 }
897 }
898 }
899
900 fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, u32>>> {
901 let max_rows_between_yields = 100;
902 let snapshot = self.snapshot();
903 if snapshot.language.is_none()
904 || snapshot.tree.is_none()
905 || self.autoindent_requests.is_empty()
906 {
907 return None;
908 }
909
910 let autoindent_requests = self.autoindent_requests.clone();
911 Some(async move {
912 let mut indent_columns = BTreeMap::new();
913 for request in autoindent_requests {
914 let old_to_new_rows = request
915 .edited
916 .iter()
917 .map(|anchor| anchor.summary::<Point>(&request.before_edit).row)
918 .zip(
919 request
920 .edited
921 .iter()
922 .map(|anchor| anchor.summary::<Point>(&snapshot).row),
923 )
924 .collect::<BTreeMap<u32, u32>>();
925
926 let mut old_suggestions = HashMap::<u32, u32>::default();
927 let old_edited_ranges =
928 contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
929 for old_edited_range in old_edited_ranges {
930 let suggestions = request
931 .before_edit
932 .suggest_autoindents(old_edited_range.clone())
933 .into_iter()
934 .flatten();
935 for (old_row, suggestion) in old_edited_range.zip(suggestions) {
936 let indentation_basis = old_to_new_rows
937 .get(&suggestion.basis_row)
938 .and_then(|from_row| old_suggestions.get(from_row).copied())
939 .unwrap_or_else(|| {
940 request
941 .before_edit
942 .indent_column_for_line(suggestion.basis_row)
943 });
944 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
945 old_suggestions.insert(
946 *old_to_new_rows.get(&old_row).unwrap(),
947 indentation_basis + delta,
948 );
949 }
950 yield_now().await;
951 }
952
953 // At this point, old_suggestions contains the suggested indentation for all edited lines with respect to the state of the
954 // buffer before the edit, but keyed by the row for these lines after the edits were applied.
955 let new_edited_row_ranges =
956 contiguous_ranges(old_to_new_rows.values().copied(), max_rows_between_yields);
957 for new_edited_row_range in new_edited_row_ranges {
958 let suggestions = snapshot
959 .suggest_autoindents(new_edited_row_range.clone())
960 .into_iter()
961 .flatten();
962 for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
963 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
964 let new_indentation = indent_columns
965 .get(&suggestion.basis_row)
966 .copied()
967 .unwrap_or_else(|| {
968 snapshot.indent_column_for_line(suggestion.basis_row)
969 })
970 + delta;
971 if old_suggestions
972 .get(&new_row)
973 .map_or(true, |old_indentation| new_indentation != *old_indentation)
974 {
975 indent_columns.insert(new_row, new_indentation);
976 }
977 }
978 yield_now().await;
979 }
980
981 if let Some(inserted) = request.inserted.as_ref() {
982 let inserted_row_ranges = contiguous_ranges(
983 inserted
984 .iter()
985 .map(|range| range.to_point(&snapshot))
986 .flat_map(|range| range.start.row..range.end.row + 1),
987 max_rows_between_yields,
988 );
989 for inserted_row_range in inserted_row_ranges {
990 let suggestions = snapshot
991 .suggest_autoindents(inserted_row_range.clone())
992 .into_iter()
993 .flatten();
994 for (row, suggestion) in inserted_row_range.zip(suggestions) {
995 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
996 let new_indentation = indent_columns
997 .get(&suggestion.basis_row)
998 .copied()
999 .unwrap_or_else(|| {
1000 snapshot.indent_column_for_line(suggestion.basis_row)
1001 })
1002 + delta;
1003 indent_columns.insert(row, new_indentation);
1004 }
1005 yield_now().await;
1006 }
1007 }
1008 }
1009 indent_columns
1010 })
1011 }
1012
1013 fn apply_autoindents(
1014 &mut self,
1015 indent_columns: BTreeMap<u32, u32>,
1016 cx: &mut ModelContext<Self>,
1017 ) {
1018 self.autoindent_requests.clear();
1019 self.start_transaction();
1020 for (row, indent_column) in &indent_columns {
1021 self.set_indent_column_for_line(*row, *indent_column, cx);
1022 }
1023 self.end_transaction(cx);
1024 }
1025
1026 fn set_indent_column_for_line(&mut self, row: u32, column: u32, cx: &mut ModelContext<Self>) {
1027 let current_column = self.indent_column_for_line(row);
1028 if column > current_column {
1029 let offset = Point::new(row, 0).to_offset(&*self);
1030 self.edit(
1031 [offset..offset],
1032 " ".repeat((column - current_column) as usize),
1033 cx,
1034 );
1035 } else if column < current_column {
1036 self.edit(
1037 [Point::new(row, 0)..Point::new(row, current_column - column)],
1038 "",
1039 cx,
1040 );
1041 }
1042 }
1043
1044 pub(crate) fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
1045 // TODO: it would be nice to not allocate here.
1046 let old_text = self.text();
1047 let base_version = self.version();
1048 cx.background().spawn(async move {
1049 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
1050 .iter_all_changes()
1051 .map(|c| (c.tag(), c.value().len()))
1052 .collect::<Vec<_>>();
1053 Diff {
1054 base_version,
1055 new_text,
1056 changes,
1057 }
1058 })
1059 }
1060
1061 pub(crate) fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> bool {
1062 if self.version == diff.base_version {
1063 self.start_transaction();
1064 let mut offset = 0;
1065 for (tag, len) in diff.changes {
1066 let range = offset..(offset + len);
1067 match tag {
1068 ChangeTag::Equal => offset += len,
1069 ChangeTag::Delete => self.edit(Some(range), "", cx),
1070 ChangeTag::Insert => {
1071 self.edit(Some(offset..offset), &diff.new_text[range], cx);
1072 offset += len;
1073 }
1074 }
1075 }
1076 self.end_transaction(cx);
1077 true
1078 } else {
1079 false
1080 }
1081 }
1082
1083 pub fn is_dirty(&self) -> bool {
1084 !self.saved_version.observed_all(&self.version)
1085 || self.file.as_ref().map_or(false, |file| file.is_deleted())
1086 }
1087
1088 pub fn has_conflict(&self) -> bool {
1089 !self.saved_version.observed_all(&self.version)
1090 && self
1091 .file
1092 .as_ref()
1093 .map_or(false, |file| file.mtime() > self.saved_mtime)
1094 }
1095
1096 pub fn subscribe(&mut self) -> Subscription {
1097 self.text.subscribe()
1098 }
1099
1100 pub fn start_transaction(&mut self) -> Option<TransactionId> {
1101 self.start_transaction_at(Instant::now())
1102 }
1103
1104 pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
1105 self.text.start_transaction_at(now)
1106 }
1107
1108 pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1109 self.end_transaction_at(Instant::now(), cx)
1110 }
1111
1112 pub fn end_transaction_at(
1113 &mut self,
1114 now: Instant,
1115 cx: &mut ModelContext<Self>,
1116 ) -> Option<TransactionId> {
1117 if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
1118 let was_dirty = start_version != self.saved_version;
1119 self.did_edit(&start_version, was_dirty, cx);
1120 Some(transaction_id)
1121 } else {
1122 None
1123 }
1124 }
1125
1126 pub fn set_active_selections(
1127 &mut self,
1128 selections: Arc<[Selection<Anchor>]>,
1129 cx: &mut ModelContext<Self>,
1130 ) {
1131 let lamport_timestamp = self.text.lamport_clock.tick();
1132 self.remote_selections.insert(
1133 self.text.replica_id(),
1134 SelectionSet {
1135 selections: selections.clone(),
1136 lamport_timestamp,
1137 },
1138 );
1139 self.send_operation(
1140 Operation::UpdateSelections {
1141 replica_id: self.text.replica_id(),
1142 selections,
1143 lamport_timestamp,
1144 },
1145 cx,
1146 );
1147 }
1148
1149 pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
1150 self.set_active_selections(Arc::from([]), cx);
1151 }
1152
1153 fn update_language_server(&mut self) {
1154 let language_server = if let Some(language_server) = self.language_server.as_mut() {
1155 language_server
1156 } else {
1157 return;
1158 };
1159 let abs_path = self
1160 .file
1161 .as_ref()
1162 .map_or(Path::new("/").to_path_buf(), |file| {
1163 file.abs_path().unwrap()
1164 });
1165
1166 let version = post_inc(&mut language_server.next_version);
1167 let snapshot = LanguageServerSnapshot {
1168 buffer_snapshot: self.text.snapshot(),
1169 version,
1170 path: Arc::from(abs_path),
1171 };
1172 language_server
1173 .pending_snapshots
1174 .insert(version, snapshot.clone());
1175 let _ = language_server
1176 .latest_snapshot
1177 .blocking_send(Some(snapshot));
1178 }
1179
1180 pub fn edit<I, S, T>(&mut self, ranges_iter: I, new_text: T, cx: &mut ModelContext<Self>)
1181 where
1182 I: IntoIterator<Item = Range<S>>,
1183 S: ToOffset,
1184 T: Into<String>,
1185 {
1186 self.edit_internal(ranges_iter, new_text, false, cx)
1187 }
1188
1189 pub fn edit_with_autoindent<I, S, T>(
1190 &mut self,
1191 ranges_iter: I,
1192 new_text: T,
1193 cx: &mut ModelContext<Self>,
1194 ) where
1195 I: IntoIterator<Item = Range<S>>,
1196 S: ToOffset,
1197 T: Into<String>,
1198 {
1199 self.edit_internal(ranges_iter, new_text, true, cx)
1200 }
1201
1202 pub fn edit_internal<I, S, T>(
1203 &mut self,
1204 ranges_iter: I,
1205 new_text: T,
1206 autoindent: bool,
1207 cx: &mut ModelContext<Self>,
1208 ) where
1209 I: IntoIterator<Item = Range<S>>,
1210 S: ToOffset,
1211 T: Into<String>,
1212 {
1213 let new_text = new_text.into();
1214
1215 // Skip invalid ranges and coalesce contiguous ones.
1216 let mut ranges: Vec<Range<usize>> = Vec::new();
1217 for range in ranges_iter {
1218 let range = range.start.to_offset(self)..range.end.to_offset(self);
1219 if !new_text.is_empty() || !range.is_empty() {
1220 if let Some(prev_range) = ranges.last_mut() {
1221 if prev_range.end >= range.start {
1222 prev_range.end = cmp::max(prev_range.end, range.end);
1223 } else {
1224 ranges.push(range);
1225 }
1226 } else {
1227 ranges.push(range);
1228 }
1229 }
1230 }
1231 if ranges.is_empty() {
1232 return;
1233 }
1234
1235 self.start_transaction();
1236 self.pending_autoindent.take();
1237 let autoindent_request = if autoindent && self.language.is_some() {
1238 let before_edit = self.snapshot();
1239 let edited = ranges
1240 .iter()
1241 .filter_map(|range| {
1242 let start = range.start.to_point(self);
1243 if new_text.starts_with('\n') && start.column == self.line_len(start.row) {
1244 None
1245 } else {
1246 Some(self.anchor_before(range.start))
1247 }
1248 })
1249 .collect();
1250 Some((before_edit, edited))
1251 } else {
1252 None
1253 };
1254
1255 let first_newline_ix = new_text.find('\n');
1256 let new_text_len = new_text.len();
1257
1258 let edit = self.text.edit(ranges.iter().cloned(), new_text);
1259
1260 if let Some((before_edit, edited)) = autoindent_request {
1261 let mut inserted = None;
1262 if let Some(first_newline_ix) = first_newline_ix {
1263 let mut delta = 0isize;
1264 inserted = Some(
1265 ranges
1266 .iter()
1267 .map(|range| {
1268 let start =
1269 (delta + range.start as isize) as usize + first_newline_ix + 1;
1270 let end = (delta + range.start as isize) as usize + new_text_len;
1271 delta +=
1272 (range.end as isize - range.start as isize) + new_text_len as isize;
1273 self.anchor_before(start)..self.anchor_after(end)
1274 })
1275 .collect(),
1276 );
1277 }
1278
1279 self.autoindent_requests.push(Arc::new(AutoindentRequest {
1280 before_edit,
1281 edited,
1282 inserted,
1283 }));
1284 }
1285
1286 self.end_transaction(cx);
1287 self.send_operation(Operation::Buffer(text::Operation::Edit(edit)), cx);
1288 }
1289
1290 fn did_edit(
1291 &mut self,
1292 old_version: &clock::Global,
1293 was_dirty: bool,
1294 cx: &mut ModelContext<Self>,
1295 ) {
1296 if self.edits_since::<usize>(old_version).next().is_none() {
1297 return;
1298 }
1299
1300 self.reparse(cx);
1301 self.update_language_server();
1302
1303 cx.emit(Event::Edited);
1304 if !was_dirty {
1305 cx.emit(Event::Dirtied);
1306 }
1307 cx.notify();
1308 }
1309
1310 fn grammar(&self) -> Option<&Arc<Grammar>> {
1311 self.language.as_ref().and_then(|l| l.grammar.as_ref())
1312 }
1313
1314 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1315 &mut self,
1316 ops: I,
1317 cx: &mut ModelContext<Self>,
1318 ) -> Result<()> {
1319 self.pending_autoindent.take();
1320 let was_dirty = self.is_dirty();
1321 let old_version = self.version.clone();
1322 let mut deferred_ops = Vec::new();
1323 let buffer_ops = ops
1324 .into_iter()
1325 .filter_map(|op| match op {
1326 Operation::Buffer(op) => Some(op),
1327 _ => {
1328 if self.can_apply_op(&op) {
1329 self.apply_op(op, cx);
1330 } else {
1331 deferred_ops.push(op);
1332 }
1333 None
1334 }
1335 })
1336 .collect::<Vec<_>>();
1337 self.text.apply_ops(buffer_ops)?;
1338 self.deferred_ops.insert(deferred_ops);
1339 self.flush_deferred_ops(cx);
1340 self.did_edit(&old_version, was_dirty, cx);
1341 // Notify independently of whether the buffer was edited as the operations could include a
1342 // selection update.
1343 cx.notify();
1344 Ok(())
1345 }
1346
1347 fn flush_deferred_ops(&mut self, cx: &mut ModelContext<Self>) {
1348 let mut deferred_ops = Vec::new();
1349 for op in self.deferred_ops.drain().iter().cloned() {
1350 if self.can_apply_op(&op) {
1351 self.apply_op(op, cx);
1352 } else {
1353 deferred_ops.push(op);
1354 }
1355 }
1356 self.deferred_ops.insert(deferred_ops);
1357 }
1358
1359 fn can_apply_op(&self, operation: &Operation) -> bool {
1360 match operation {
1361 Operation::Buffer(_) => {
1362 unreachable!("buffer operations should never be applied at this layer")
1363 }
1364 Operation::UpdateDiagnostics {
1365 diagnostics: diagnostic_set,
1366 ..
1367 } => diagnostic_set.iter().all(|diagnostic| {
1368 self.text.can_resolve(&diagnostic.range.start)
1369 && self.text.can_resolve(&diagnostic.range.end)
1370 }),
1371 Operation::UpdateSelections { selections, .. } => selections
1372 .iter()
1373 .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
1374 }
1375 }
1376
1377 fn apply_op(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1378 match operation {
1379 Operation::Buffer(_) => {
1380 unreachable!("buffer operations should never be applied at this layer")
1381 }
1382 Operation::UpdateDiagnostics {
1383 diagnostics: diagnostic_set,
1384 ..
1385 } => {
1386 let snapshot = self.snapshot();
1387 self.apply_diagnostic_update(
1388 DiagnosticSet::from_sorted_entries(diagnostic_set.iter().cloned(), &snapshot),
1389 cx,
1390 );
1391 }
1392 Operation::UpdateSelections {
1393 replica_id,
1394 selections,
1395 lamport_timestamp,
1396 } => {
1397 if let Some(set) = self.remote_selections.get(&replica_id) {
1398 if set.lamport_timestamp > lamport_timestamp {
1399 return;
1400 }
1401 }
1402
1403 self.remote_selections.insert(
1404 replica_id,
1405 SelectionSet {
1406 selections,
1407 lamport_timestamp,
1408 },
1409 );
1410 self.text.lamport_clock.observe(lamport_timestamp);
1411 self.selections_update_count += 1;
1412 }
1413 }
1414 }
1415
1416 fn apply_diagnostic_update(&mut self, diagnostics: DiagnosticSet, cx: &mut ModelContext<Self>) {
1417 self.diagnostics = diagnostics;
1418 self.diagnostics_update_count += 1;
1419 cx.notify();
1420 cx.emit(Event::DiagnosticsUpdated);
1421 }
1422
1423 #[cfg(not(test))]
1424 pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1425 if let Some(file) = &self.file {
1426 file.buffer_updated(self.remote_id(), operation, cx.as_mut());
1427 }
1428 }
1429
1430 #[cfg(test)]
1431 pub fn send_operation(&mut self, operation: Operation, _: &mut ModelContext<Self>) {
1432 self.operations.push(operation);
1433 }
1434
1435 pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1436 self.remote_selections.remove(&replica_id);
1437 cx.notify();
1438 }
1439
1440 pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1441 let was_dirty = self.is_dirty();
1442 let old_version = self.version.clone();
1443
1444 if let Some((transaction_id, operation)) = self.text.undo() {
1445 self.send_operation(Operation::Buffer(operation), cx);
1446 self.did_edit(&old_version, was_dirty, cx);
1447 Some(transaction_id)
1448 } else {
1449 None
1450 }
1451 }
1452
1453 pub fn undo_transaction(
1454 &mut self,
1455 transaction_id: TransactionId,
1456 cx: &mut ModelContext<Self>,
1457 ) -> bool {
1458 let was_dirty = self.is_dirty();
1459 let old_version = self.version.clone();
1460
1461 if let Some(operation) = self.text.undo_transaction(transaction_id) {
1462 self.send_operation(Operation::Buffer(operation), cx);
1463 self.did_edit(&old_version, was_dirty, cx);
1464 true
1465 } else {
1466 false
1467 }
1468 }
1469
1470 pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1471 let was_dirty = self.is_dirty();
1472 let old_version = self.version.clone();
1473
1474 if let Some((transaction_id, operation)) = self.text.redo() {
1475 self.send_operation(Operation::Buffer(operation), cx);
1476 self.did_edit(&old_version, was_dirty, cx);
1477 Some(transaction_id)
1478 } else {
1479 None
1480 }
1481 }
1482
1483 pub fn redo_transaction(
1484 &mut self,
1485 transaction_id: TransactionId,
1486 cx: &mut ModelContext<Self>,
1487 ) -> bool {
1488 let was_dirty = self.is_dirty();
1489 let old_version = self.version.clone();
1490
1491 if let Some(operation) = self.text.redo_transaction(transaction_id) {
1492 self.send_operation(Operation::Buffer(operation), cx);
1493 self.did_edit(&old_version, was_dirty, cx);
1494 true
1495 } else {
1496 false
1497 }
1498 }
1499}
1500
1501#[cfg(any(test, feature = "test-support"))]
1502impl Buffer {
1503 pub fn set_group_interval(&mut self, group_interval: Duration) {
1504 self.text.set_group_interval(group_interval);
1505 }
1506
1507 pub fn randomly_edit<T>(
1508 &mut self,
1509 rng: &mut T,
1510 old_range_count: usize,
1511 cx: &mut ModelContext<Self>,
1512 ) where
1513 T: rand::Rng,
1514 {
1515 let mut old_ranges: Vec<Range<usize>> = Vec::new();
1516 for _ in 0..old_range_count {
1517 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
1518 if last_end > self.len() {
1519 break;
1520 }
1521 old_ranges.push(self.text.random_byte_range(last_end, rng));
1522 }
1523 let new_text_len = rng.gen_range(0..10);
1524 let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng)
1525 .take(new_text_len)
1526 .collect();
1527 log::info!(
1528 "mutating buffer {} at {:?}: {:?}",
1529 self.replica_id(),
1530 old_ranges,
1531 new_text
1532 );
1533 self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
1534 }
1535
1536 pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
1537 let was_dirty = self.is_dirty();
1538 let old_version = self.version.clone();
1539
1540 let ops = self.text.randomly_undo_redo(rng);
1541 if !ops.is_empty() {
1542 for op in ops {
1543 self.send_operation(Operation::Buffer(op), cx);
1544 self.did_edit(&old_version, was_dirty, cx);
1545 }
1546 }
1547 }
1548}
1549
1550impl Entity for Buffer {
1551 type Event = Event;
1552
1553 fn release(&mut self, cx: &mut gpui::MutableAppContext) {
1554 if let Some(file) = self.file.as_ref() {
1555 file.buffer_removed(self.remote_id(), cx);
1556 }
1557 }
1558}
1559
1560impl Deref for Buffer {
1561 type Target = TextBuffer;
1562
1563 fn deref(&self) -> &Self::Target {
1564 &self.text
1565 }
1566}
1567
1568impl BufferSnapshot {
1569 fn suggest_autoindents<'a>(
1570 &'a self,
1571 row_range: Range<u32>,
1572 ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
1573 let mut query_cursor = QueryCursorHandle::new();
1574 if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) {
1575 let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
1576
1577 // Get the "indentation ranges" that intersect this row range.
1578 let indent_capture_ix = grammar.indents_query.capture_index_for_name("indent");
1579 let end_capture_ix = grammar.indents_query.capture_index_for_name("end");
1580 query_cursor.set_point_range(
1581 Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point()
1582 ..Point::new(row_range.end, 0).to_ts_point(),
1583 );
1584 let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
1585 for mat in query_cursor.matches(
1586 &grammar.indents_query,
1587 tree.root_node(),
1588 TextProvider(self.as_rope()),
1589 ) {
1590 let mut node_kind = "";
1591 let mut start: Option<Point> = None;
1592 let mut end: Option<Point> = None;
1593 for capture in mat.captures {
1594 if Some(capture.index) == indent_capture_ix {
1595 node_kind = capture.node.kind();
1596 start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
1597 end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
1598 } else if Some(capture.index) == end_capture_ix {
1599 end = Some(Point::from_ts_point(capture.node.start_position().into()));
1600 }
1601 }
1602
1603 if let Some((start, end)) = start.zip(end) {
1604 if start.row == end.row {
1605 continue;
1606 }
1607
1608 let range = start..end;
1609 match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
1610 Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
1611 Ok(ix) => {
1612 let prev_range = &mut indentation_ranges[ix];
1613 prev_range.0.end = prev_range.0.end.max(range.end);
1614 }
1615 }
1616 }
1617 }
1618
1619 let mut prev_row = prev_non_blank_row.unwrap_or(0);
1620 Some(row_range.map(move |row| {
1621 let row_start = Point::new(row, self.indent_column_for_line(row));
1622
1623 let mut indent_from_prev_row = false;
1624 let mut outdent_to_row = u32::MAX;
1625 for (range, _node_kind) in &indentation_ranges {
1626 if range.start.row >= row {
1627 break;
1628 }
1629
1630 if range.start.row == prev_row && range.end > row_start {
1631 indent_from_prev_row = true;
1632 }
1633 if range.end.row >= prev_row && range.end <= row_start {
1634 outdent_to_row = outdent_to_row.min(range.start.row);
1635 }
1636 }
1637
1638 let suggestion = if outdent_to_row == prev_row {
1639 IndentSuggestion {
1640 basis_row: prev_row,
1641 indent: false,
1642 }
1643 } else if indent_from_prev_row {
1644 IndentSuggestion {
1645 basis_row: prev_row,
1646 indent: true,
1647 }
1648 } else if outdent_to_row < prev_row {
1649 IndentSuggestion {
1650 basis_row: outdent_to_row,
1651 indent: false,
1652 }
1653 } else {
1654 IndentSuggestion {
1655 basis_row: prev_row,
1656 indent: false,
1657 }
1658 };
1659
1660 prev_row = row;
1661 suggestion
1662 }))
1663 } else {
1664 None
1665 }
1666 }
1667
1668 fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
1669 while row > 0 {
1670 row -= 1;
1671 if !self.is_line_blank(row) {
1672 return Some(row);
1673 }
1674 }
1675 None
1676 }
1677
1678 pub fn chunks<'a, T: ToOffset>(
1679 &'a self,
1680 range: Range<T>,
1681 theme: Option<&'a SyntaxTheme>,
1682 ) -> BufferChunks<'a> {
1683 let range = range.start.to_offset(self)..range.end.to_offset(self);
1684
1685 let mut highlights = None;
1686 let mut diagnostic_endpoints = Vec::<DiagnosticEndpoint>::new();
1687 if let Some(theme) = theme {
1688 for entry in self.diagnostics_in_range::<_, usize>(range.clone()) {
1689 diagnostic_endpoints.push(DiagnosticEndpoint {
1690 offset: entry.range.start,
1691 is_start: true,
1692 severity: entry.diagnostic.severity,
1693 });
1694 diagnostic_endpoints.push(DiagnosticEndpoint {
1695 offset: entry.range.end,
1696 is_start: false,
1697 severity: entry.diagnostic.severity,
1698 });
1699 }
1700 diagnostic_endpoints
1701 .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
1702
1703 if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) {
1704 let mut query_cursor = QueryCursorHandle::new();
1705
1706 // TODO - add a Tree-sitter API to remove the need for this.
1707 let cursor = unsafe {
1708 std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
1709 };
1710 let captures = cursor.set_byte_range(range.clone()).captures(
1711 &grammar.highlights_query,
1712 tree.root_node(),
1713 TextProvider(self.text.as_rope()),
1714 );
1715 highlights = Some(BufferChunkHighlights {
1716 captures,
1717 next_capture: None,
1718 stack: Default::default(),
1719 highlight_map: grammar.highlight_map(),
1720 _query_cursor: query_cursor,
1721 theme,
1722 })
1723 }
1724 }
1725
1726 let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
1727 let chunks = self.text.as_rope().chunks_in_range(range.clone());
1728
1729 BufferChunks {
1730 range,
1731 chunks,
1732 diagnostic_endpoints,
1733 error_depth: 0,
1734 warning_depth: 0,
1735 information_depth: 0,
1736 hint_depth: 0,
1737 highlights,
1738 }
1739 }
1740
1741 pub fn language(&self) -> Option<&Arc<Language>> {
1742 self.language.as_ref()
1743 }
1744
1745 fn grammar(&self) -> Option<&Arc<Grammar>> {
1746 self.language
1747 .as_ref()
1748 .and_then(|language| language.grammar.as_ref())
1749 }
1750
1751 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1752 if let Some(tree) = self.tree.as_ref() {
1753 let root = tree.root_node();
1754 let range = range.start.to_offset(self)..range.end.to_offset(self);
1755 let mut node = root.descendant_for_byte_range(range.start, range.end);
1756 while node.map_or(false, |n| n.byte_range() == range) {
1757 node = node.unwrap().parent();
1758 }
1759 node.map(|n| n.byte_range())
1760 } else {
1761 None
1762 }
1763 }
1764
1765 pub fn enclosing_bracket_ranges<T: ToOffset>(
1766 &self,
1767 range: Range<T>,
1768 ) -> Option<(Range<usize>, Range<usize>)> {
1769 let (grammar, tree) = self.grammar().zip(self.tree.as_ref())?;
1770 let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?;
1771 let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?;
1772
1773 // Find bracket pairs that *inclusively* contain the given range.
1774 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
1775 let mut cursor = QueryCursorHandle::new();
1776 let matches = cursor.set_byte_range(range).matches(
1777 &grammar.brackets_query,
1778 tree.root_node(),
1779 TextProvider(self.as_rope()),
1780 );
1781
1782 // Get the ranges of the innermost pair of brackets.
1783 matches
1784 .filter_map(|mat| {
1785 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
1786 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
1787 Some((open.byte_range(), close.byte_range()))
1788 })
1789 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
1790 }
1791
1792 pub fn remote_selections_in_range<'a>(
1793 &'a self,
1794 range: Range<Anchor>,
1795 ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = &'a Selection<Anchor>>)>
1796 {
1797 self.remote_selections
1798 .iter()
1799 .filter(|(replica_id, set)| {
1800 **replica_id != self.text.replica_id() && !set.selections.is_empty()
1801 })
1802 .map(move |(replica_id, set)| {
1803 let start_ix = match set.selections.binary_search_by(|probe| {
1804 probe
1805 .end
1806 .cmp(&range.start, self)
1807 .unwrap()
1808 .then(Ordering::Greater)
1809 }) {
1810 Ok(ix) | Err(ix) => ix,
1811 };
1812 let end_ix = match set.selections.binary_search_by(|probe| {
1813 probe
1814 .start
1815 .cmp(&range.end, self)
1816 .unwrap()
1817 .then(Ordering::Less)
1818 }) {
1819 Ok(ix) | Err(ix) => ix,
1820 };
1821
1822 (*replica_id, set.selections[start_ix..end_ix].iter())
1823 })
1824 }
1825
1826 pub fn diagnostics_in_range<'a, T, O>(
1827 &'a self,
1828 search_range: Range<T>,
1829 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
1830 where
1831 T: 'a + Clone + ToOffset,
1832 O: 'a + FromAnchor,
1833 {
1834 self.diagnostics.range(search_range.clone(), self, true)
1835 }
1836
1837 pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
1838 let mut groups = Vec::new();
1839 self.diagnostics.groups(&mut groups, self);
1840 groups
1841 }
1842
1843 pub fn diagnostic_group<'a, O>(
1844 &'a self,
1845 group_id: usize,
1846 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
1847 where
1848 O: 'a + FromAnchor,
1849 {
1850 self.diagnostics.group(group_id, self)
1851 }
1852
1853 pub fn diagnostics_update_count(&self) -> usize {
1854 self.diagnostics_update_count
1855 }
1856
1857 pub fn parse_count(&self) -> usize {
1858 self.parse_count
1859 }
1860
1861 pub fn selections_update_count(&self) -> usize {
1862 self.selections_update_count
1863 }
1864}
1865
1866impl Clone for BufferSnapshot {
1867 fn clone(&self) -> Self {
1868 Self {
1869 text: self.text.clone(),
1870 tree: self.tree.clone(),
1871 remote_selections: self.remote_selections.clone(),
1872 diagnostics: self.diagnostics.clone(),
1873 selections_update_count: self.selections_update_count,
1874 diagnostics_update_count: self.diagnostics_update_count,
1875 is_parsing: self.is_parsing,
1876 language: self.language.clone(),
1877 parse_count: self.parse_count,
1878 }
1879 }
1880}
1881
1882impl Deref for BufferSnapshot {
1883 type Target = text::BufferSnapshot;
1884
1885 fn deref(&self) -> &Self::Target {
1886 &self.text
1887 }
1888}
1889
1890impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
1891 type I = ByteChunks<'a>;
1892
1893 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
1894 ByteChunks(self.0.chunks_in_range(node.byte_range()))
1895 }
1896}
1897
1898struct ByteChunks<'a>(rope::Chunks<'a>);
1899
1900impl<'a> Iterator for ByteChunks<'a> {
1901 type Item = &'a [u8];
1902
1903 fn next(&mut self) -> Option<Self::Item> {
1904 self.0.next().map(str::as_bytes)
1905 }
1906}
1907
1908unsafe impl<'a> Send for BufferChunks<'a> {}
1909
1910impl<'a> BufferChunks<'a> {
1911 pub fn seek(&mut self, offset: usize) {
1912 self.range.start = offset;
1913 self.chunks.seek(self.range.start);
1914 if let Some(highlights) = self.highlights.as_mut() {
1915 highlights
1916 .stack
1917 .retain(|(end_offset, _)| *end_offset > offset);
1918 if let Some((mat, capture_ix)) = &highlights.next_capture {
1919 let capture = mat.captures[*capture_ix as usize];
1920 if offset >= capture.node.start_byte() {
1921 let next_capture_end = capture.node.end_byte();
1922 if offset < next_capture_end {
1923 highlights.stack.push((
1924 next_capture_end,
1925 highlights.highlight_map.get(capture.index),
1926 ));
1927 }
1928 highlights.next_capture.take();
1929 }
1930 }
1931 highlights.captures.set_byte_range(self.range.clone());
1932 }
1933 }
1934
1935 pub fn offset(&self) -> usize {
1936 self.range.start
1937 }
1938
1939 fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
1940 let depth = match endpoint.severity {
1941 DiagnosticSeverity::ERROR => &mut self.error_depth,
1942 DiagnosticSeverity::WARNING => &mut self.warning_depth,
1943 DiagnosticSeverity::INFORMATION => &mut self.information_depth,
1944 DiagnosticSeverity::HINT => &mut self.hint_depth,
1945 _ => return,
1946 };
1947 if endpoint.is_start {
1948 *depth += 1;
1949 } else {
1950 *depth -= 1;
1951 }
1952 }
1953
1954 fn current_diagnostic_severity(&mut self) -> Option<DiagnosticSeverity> {
1955 if self.error_depth > 0 {
1956 Some(DiagnosticSeverity::ERROR)
1957 } else if self.warning_depth > 0 {
1958 Some(DiagnosticSeverity::WARNING)
1959 } else if self.information_depth > 0 {
1960 Some(DiagnosticSeverity::INFORMATION)
1961 } else if self.hint_depth > 0 {
1962 Some(DiagnosticSeverity::HINT)
1963 } else {
1964 None
1965 }
1966 }
1967}
1968
1969impl<'a> Iterator for BufferChunks<'a> {
1970 type Item = Chunk<'a>;
1971
1972 fn next(&mut self) -> Option<Self::Item> {
1973 let mut next_capture_start = usize::MAX;
1974 let mut next_diagnostic_endpoint = usize::MAX;
1975
1976 if let Some(highlights) = self.highlights.as_mut() {
1977 while let Some((parent_capture_end, _)) = highlights.stack.last() {
1978 if *parent_capture_end <= self.range.start {
1979 highlights.stack.pop();
1980 } else {
1981 break;
1982 }
1983 }
1984
1985 if highlights.next_capture.is_none() {
1986 highlights.next_capture = highlights.captures.next();
1987 }
1988
1989 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
1990 let capture = mat.captures[*capture_ix as usize];
1991 if self.range.start < capture.node.start_byte() {
1992 next_capture_start = capture.node.start_byte();
1993 break;
1994 } else {
1995 let highlight_id = highlights.highlight_map.get(capture.index);
1996 highlights
1997 .stack
1998 .push((capture.node.end_byte(), highlight_id));
1999 highlights.next_capture = highlights.captures.next();
2000 }
2001 }
2002 }
2003
2004 while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
2005 if endpoint.offset <= self.range.start {
2006 self.update_diagnostic_depths(endpoint);
2007 self.diagnostic_endpoints.next();
2008 } else {
2009 next_diagnostic_endpoint = endpoint.offset;
2010 break;
2011 }
2012 }
2013
2014 if let Some(chunk) = self.chunks.peek() {
2015 let chunk_start = self.range.start;
2016 let mut chunk_end = (self.chunks.offset() + chunk.len())
2017 .min(next_capture_start)
2018 .min(next_diagnostic_endpoint);
2019 let mut highlight_style = None;
2020 if let Some(highlights) = self.highlights.as_ref() {
2021 if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
2022 chunk_end = chunk_end.min(*parent_capture_end);
2023 highlight_style = parent_highlight_id.style(highlights.theme);
2024 }
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(Chunk {
2035 text: slice,
2036 highlight_style,
2037 diagnostic: self.current_diagnostic_severity(),
2038 })
2039 } else {
2040 None
2041 }
2042 }
2043}
2044
2045impl QueryCursorHandle {
2046 fn new() -> Self {
2047 QueryCursorHandle(Some(
2048 QUERY_CURSORS
2049 .lock()
2050 .pop()
2051 .unwrap_or_else(|| QueryCursor::new()),
2052 ))
2053 }
2054}
2055
2056impl Deref for QueryCursorHandle {
2057 type Target = QueryCursor;
2058
2059 fn deref(&self) -> &Self::Target {
2060 self.0.as_ref().unwrap()
2061 }
2062}
2063
2064impl DerefMut for QueryCursorHandle {
2065 fn deref_mut(&mut self) -> &mut Self::Target {
2066 self.0.as_mut().unwrap()
2067 }
2068}
2069
2070impl Drop for QueryCursorHandle {
2071 fn drop(&mut self) {
2072 let mut cursor = self.0.take().unwrap();
2073 cursor.set_byte_range(0..usize::MAX);
2074 cursor.set_point_range(Point::zero().to_ts_point()..Point::MAX.to_ts_point());
2075 QUERY_CURSORS.lock().push(cursor)
2076 }
2077}
2078
2079trait ToTreeSitterPoint {
2080 fn to_ts_point(self) -> tree_sitter::Point;
2081 fn from_ts_point(point: tree_sitter::Point) -> Self;
2082}
2083
2084impl ToTreeSitterPoint for Point {
2085 fn to_ts_point(self) -> tree_sitter::Point {
2086 tree_sitter::Point::new(self.row as usize, self.column as usize)
2087 }
2088
2089 fn from_ts_point(point: tree_sitter::Point) -> Self {
2090 Point::new(point.row as u32, point.column as u32)
2091 }
2092}
2093
2094impl operation_queue::Operation for Operation {
2095 fn lamport_timestamp(&self) -> clock::Lamport {
2096 match self {
2097 Operation::Buffer(_) => {
2098 unreachable!("buffer operations should never be deferred at this layer")
2099 }
2100 Operation::UpdateDiagnostics {
2101 lamport_timestamp, ..
2102 }
2103 | Operation::UpdateSelections {
2104 lamport_timestamp, ..
2105 } => *lamport_timestamp,
2106 }
2107 }
2108}
2109
2110impl Default for Diagnostic {
2111 fn default() -> Self {
2112 Self {
2113 code: Default::default(),
2114 severity: DiagnosticSeverity::ERROR,
2115 message: Default::default(),
2116 group_id: Default::default(),
2117 is_primary: Default::default(),
2118 is_valid: true,
2119 is_disk_based: false,
2120 }
2121 }
2122}
2123
2124pub fn contiguous_ranges(
2125 values: impl Iterator<Item = u32>,
2126 max_len: usize,
2127) -> impl Iterator<Item = Range<u32>> {
2128 let mut values = values.into_iter();
2129 let mut current_range: Option<Range<u32>> = None;
2130 std::iter::from_fn(move || loop {
2131 if let Some(value) = values.next() {
2132 if let Some(range) = &mut current_range {
2133 if value == range.end && range.len() < max_len {
2134 range.end += 1;
2135 continue;
2136 }
2137 }
2138
2139 let prev_range = current_range.clone();
2140 current_range = Some(value..(value + 1));
2141 if prev_range.is_some() {
2142 return prev_range;
2143 }
2144 } else {
2145 return current_range.take();
2146 }
2147 })
2148}