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