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