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