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