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