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>(&'a self, range: Range<T>) -> BufferChunks<'a> {
2096 let range = range.start.to_offset(self)..range.end.to_offset(self);
2097
2098 let mut diagnostic_endpoints = Vec::<DiagnosticEndpoint>::new();
2099 for entry in self.diagnostics_in_range::<_, usize>(range.clone()) {
2100 diagnostic_endpoints.push(DiagnosticEndpoint {
2101 offset: entry.range.start,
2102 is_start: true,
2103 severity: entry.diagnostic.severity,
2104 });
2105 diagnostic_endpoints.push(DiagnosticEndpoint {
2106 offset: entry.range.end,
2107 is_start: false,
2108 severity: entry.diagnostic.severity,
2109 });
2110 }
2111 diagnostic_endpoints.sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
2112
2113 BufferChunks::new(
2114 self.text.as_rope(),
2115 range,
2116 self.tree.as_ref(),
2117 self.grammar(),
2118 diagnostic_endpoints,
2119 )
2120 }
2121
2122 pub fn language(&self) -> Option<&Arc<Language>> {
2123 self.language.as_ref()
2124 }
2125
2126 fn grammar(&self) -> Option<&Arc<Grammar>> {
2127 self.language
2128 .as_ref()
2129 .and_then(|language| language.grammar.as_ref())
2130 }
2131
2132 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2133 if let Some(tree) = self.tree.as_ref() {
2134 let root = tree.root_node();
2135 let range = range.start.to_offset(self)..range.end.to_offset(self);
2136 let mut node = root.descendant_for_byte_range(range.start, range.end);
2137 while node.map_or(false, |n| n.byte_range() == range) {
2138 node = node.unwrap().parent();
2139 }
2140 node.map(|n| n.byte_range())
2141 } else {
2142 None
2143 }
2144 }
2145
2146 pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2147 let tree = self.tree.as_ref()?;
2148 let grammar = self
2149 .language
2150 .as_ref()
2151 .and_then(|language| language.grammar.as_ref())?;
2152
2153 let mut cursor = QueryCursorHandle::new();
2154 let matches = cursor.matches(
2155 &grammar.outline_query,
2156 tree.root_node(),
2157 TextProvider(self.as_rope()),
2158 );
2159
2160 let mut chunks = self.chunks(0..self.len());
2161
2162 let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?;
2163 let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?;
2164 let context_capture_ix = grammar
2165 .outline_query
2166 .capture_index_for_name("context")
2167 .unwrap_or(u32::MAX);
2168
2169 let mut stack = Vec::<Range<usize>>::new();
2170 let items = matches
2171 .filter_map(|mat| {
2172 let item_node = mat.nodes_for_capture_index(item_capture_ix).next()?;
2173 let range = item_node.start_byte()..item_node.end_byte();
2174 let mut text = String::new();
2175 let mut name_ranges = Vec::new();
2176 let mut highlight_ranges = Vec::new();
2177
2178 for capture in mat.captures {
2179 let node_is_name;
2180 if capture.index == name_capture_ix {
2181 node_is_name = true;
2182 } else if capture.index == context_capture_ix {
2183 node_is_name = false;
2184 } else {
2185 continue;
2186 }
2187
2188 let range = capture.node.start_byte()..capture.node.end_byte();
2189 if !text.is_empty() {
2190 text.push(' ');
2191 }
2192 if node_is_name {
2193 let mut start = text.len();
2194 let end = start + range.len();
2195
2196 // When multiple names are captured, then the matcheable text
2197 // includes the whitespace in between the names.
2198 if !name_ranges.is_empty() {
2199 start -= 1;
2200 }
2201
2202 name_ranges.push(start..end);
2203 }
2204
2205 let mut offset = range.start;
2206 chunks.seek(offset);
2207 while let Some(mut chunk) = chunks.next() {
2208 if chunk.text.len() > range.end - offset {
2209 chunk.text = &chunk.text[0..(range.end - offset)];
2210 offset = range.end;
2211 } else {
2212 offset += chunk.text.len();
2213 }
2214 let style = chunk
2215 .highlight_id
2216 .zip(theme)
2217 .and_then(|(highlight, theme)| highlight.style(theme));
2218 if let Some(style) = style {
2219 let start = text.len();
2220 let end = start + chunk.text.len();
2221 highlight_ranges.push((start..end, style));
2222 }
2223 text.push_str(chunk.text);
2224 if offset >= range.end {
2225 break;
2226 }
2227 }
2228 }
2229
2230 while stack.last().map_or(false, |prev_range| {
2231 !prev_range.contains(&range.start) || !prev_range.contains(&range.end)
2232 }) {
2233 stack.pop();
2234 }
2235 stack.push(range.clone());
2236
2237 Some(OutlineItem {
2238 depth: stack.len() - 1,
2239 range: self.anchor_after(range.start)..self.anchor_before(range.end),
2240 text,
2241 highlight_ranges,
2242 name_ranges,
2243 })
2244 })
2245 .collect::<Vec<_>>();
2246
2247 if items.is_empty() {
2248 None
2249 } else {
2250 Some(Outline::new(items))
2251 }
2252 }
2253
2254 pub fn enclosing_bracket_ranges<T: ToOffset>(
2255 &self,
2256 range: Range<T>,
2257 ) -> Option<(Range<usize>, Range<usize>)> {
2258 let (grammar, tree) = self.grammar().zip(self.tree.as_ref())?;
2259 let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?;
2260 let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?;
2261
2262 // Find bracket pairs that *inclusively* contain the given range.
2263 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
2264 let mut cursor = QueryCursorHandle::new();
2265 let matches = cursor.set_byte_range(range).matches(
2266 &grammar.brackets_query,
2267 tree.root_node(),
2268 TextProvider(self.as_rope()),
2269 );
2270
2271 // Get the ranges of the innermost pair of brackets.
2272 matches
2273 .filter_map(|mat| {
2274 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
2275 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
2276 Some((open.byte_range(), close.byte_range()))
2277 })
2278 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
2279 }
2280
2281 /*
2282 impl BufferSnapshot
2283 pub fn remote_selections_in_range(&self, Range<Anchor>) -> impl Iterator<Item = (ReplicaId, impl Iterator<Item = &Selection<Anchor>>)>
2284 pub fn remote_selections_in_range(&self, Range<Anchor>) -> impl Iterator<Item = (ReplicaId, i
2285 */
2286
2287 pub fn remote_selections_in_range<'a>(
2288 &'a self,
2289 range: Range<Anchor>,
2290 ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = &'a Selection<Anchor>>)>
2291 {
2292 self.remote_selections
2293 .iter()
2294 .filter(|(replica_id, set)| {
2295 **replica_id != self.text.replica_id() && !set.selections.is_empty()
2296 })
2297 .map(move |(replica_id, set)| {
2298 let start_ix = match set.selections.binary_search_by(|probe| {
2299 probe
2300 .end
2301 .cmp(&range.start, self)
2302 .unwrap()
2303 .then(Ordering::Greater)
2304 }) {
2305 Ok(ix) | Err(ix) => ix,
2306 };
2307 let end_ix = match set.selections.binary_search_by(|probe| {
2308 probe
2309 .start
2310 .cmp(&range.end, self)
2311 .unwrap()
2312 .then(Ordering::Less)
2313 }) {
2314 Ok(ix) | Err(ix) => ix,
2315 };
2316
2317 (*replica_id, set.selections[start_ix..end_ix].iter())
2318 })
2319 }
2320
2321 pub fn diagnostics_in_range<'a, T, O>(
2322 &'a self,
2323 search_range: Range<T>,
2324 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2325 where
2326 T: 'a + Clone + ToOffset,
2327 O: 'a + FromAnchor,
2328 {
2329 self.diagnostics.range(search_range.clone(), self, true)
2330 }
2331
2332 pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
2333 let mut groups = Vec::new();
2334 self.diagnostics.groups(&mut groups, self);
2335 groups
2336 }
2337
2338 pub fn diagnostic_group<'a, O>(
2339 &'a self,
2340 group_id: usize,
2341 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2342 where
2343 O: 'a + FromAnchor,
2344 {
2345 self.diagnostics.group(group_id, self)
2346 }
2347
2348 pub fn diagnostics_update_count(&self) -> usize {
2349 self.diagnostics_update_count
2350 }
2351
2352 pub fn parse_count(&self) -> usize {
2353 self.parse_count
2354 }
2355
2356 pub fn selections_update_count(&self) -> usize {
2357 self.selections_update_count
2358 }
2359}
2360
2361impl Clone for BufferSnapshot {
2362 fn clone(&self) -> Self {
2363 Self {
2364 text: self.text.clone(),
2365 tree: self.tree.clone(),
2366 remote_selections: self.remote_selections.clone(),
2367 diagnostics: self.diagnostics.clone(),
2368 selections_update_count: self.selections_update_count,
2369 diagnostics_update_count: self.diagnostics_update_count,
2370 is_parsing: self.is_parsing,
2371 language: self.language.clone(),
2372 parse_count: self.parse_count,
2373 }
2374 }
2375}
2376
2377impl Deref for BufferSnapshot {
2378 type Target = text::BufferSnapshot;
2379
2380 fn deref(&self) -> &Self::Target {
2381 &self.text
2382 }
2383}
2384
2385impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
2386 type I = ByteChunks<'a>;
2387
2388 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
2389 ByteChunks(self.0.chunks_in_range(node.byte_range()))
2390 }
2391}
2392
2393pub(crate) struct ByteChunks<'a>(rope::Chunks<'a>);
2394
2395impl<'a> Iterator for ByteChunks<'a> {
2396 type Item = &'a [u8];
2397
2398 fn next(&mut self) -> Option<Self::Item> {
2399 self.0.next().map(str::as_bytes)
2400 }
2401}
2402
2403unsafe impl<'a> Send for BufferChunks<'a> {}
2404
2405impl<'a> BufferChunks<'a> {
2406 pub(crate) fn new(
2407 text: &'a Rope,
2408 range: Range<usize>,
2409 tree: Option<&'a Tree>,
2410 grammar: Option<&'a Arc<Grammar>>,
2411 diagnostic_endpoints: Vec<DiagnosticEndpoint>,
2412 ) -> Self {
2413 let mut highlights = None;
2414 if let Some((grammar, tree)) = grammar.zip(tree) {
2415 let mut query_cursor = QueryCursorHandle::new();
2416
2417 // TODO - add a Tree-sitter API to remove the need for this.
2418 let cursor = unsafe {
2419 std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
2420 };
2421 let captures = cursor.set_byte_range(range.clone()).captures(
2422 &grammar.highlights_query,
2423 tree.root_node(),
2424 TextProvider(text),
2425 );
2426 highlights = Some(BufferChunkHighlights {
2427 captures,
2428 next_capture: None,
2429 stack: Default::default(),
2430 highlight_map: grammar.highlight_map(),
2431 _query_cursor: query_cursor,
2432 })
2433 }
2434
2435 let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
2436 let chunks = text.chunks_in_range(range.clone());
2437
2438 BufferChunks {
2439 range,
2440 chunks,
2441 diagnostic_endpoints,
2442 error_depth: 0,
2443 warning_depth: 0,
2444 information_depth: 0,
2445 hint_depth: 0,
2446 highlights,
2447 }
2448 }
2449
2450 pub fn seek(&mut self, offset: usize) {
2451 self.range.start = offset;
2452 self.chunks.seek(self.range.start);
2453 if let Some(highlights) = self.highlights.as_mut() {
2454 highlights
2455 .stack
2456 .retain(|(end_offset, _)| *end_offset > offset);
2457 if let Some((mat, capture_ix)) = &highlights.next_capture {
2458 let capture = mat.captures[*capture_ix as usize];
2459 if offset >= capture.node.start_byte() {
2460 let next_capture_end = capture.node.end_byte();
2461 if offset < next_capture_end {
2462 highlights.stack.push((
2463 next_capture_end,
2464 highlights.highlight_map.get(capture.index),
2465 ));
2466 }
2467 highlights.next_capture.take();
2468 }
2469 }
2470 highlights.captures.set_byte_range(self.range.clone());
2471 }
2472 }
2473
2474 pub fn offset(&self) -> usize {
2475 self.range.start
2476 }
2477
2478 fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
2479 let depth = match endpoint.severity {
2480 DiagnosticSeverity::ERROR => &mut self.error_depth,
2481 DiagnosticSeverity::WARNING => &mut self.warning_depth,
2482 DiagnosticSeverity::INFORMATION => &mut self.information_depth,
2483 DiagnosticSeverity::HINT => &mut self.hint_depth,
2484 _ => return,
2485 };
2486 if endpoint.is_start {
2487 *depth += 1;
2488 } else {
2489 *depth -= 1;
2490 }
2491 }
2492
2493 fn current_diagnostic_severity(&mut self) -> Option<DiagnosticSeverity> {
2494 if self.error_depth > 0 {
2495 Some(DiagnosticSeverity::ERROR)
2496 } else if self.warning_depth > 0 {
2497 Some(DiagnosticSeverity::WARNING)
2498 } else if self.information_depth > 0 {
2499 Some(DiagnosticSeverity::INFORMATION)
2500 } else if self.hint_depth > 0 {
2501 Some(DiagnosticSeverity::HINT)
2502 } else {
2503 None
2504 }
2505 }
2506}
2507
2508impl<'a> Iterator for BufferChunks<'a> {
2509 type Item = Chunk<'a>;
2510
2511 fn next(&mut self) -> Option<Self::Item> {
2512 let mut next_capture_start = usize::MAX;
2513 let mut next_diagnostic_endpoint = usize::MAX;
2514
2515 if let Some(highlights) = self.highlights.as_mut() {
2516 while let Some((parent_capture_end, _)) = highlights.stack.last() {
2517 if *parent_capture_end <= self.range.start {
2518 highlights.stack.pop();
2519 } else {
2520 break;
2521 }
2522 }
2523
2524 if highlights.next_capture.is_none() {
2525 highlights.next_capture = highlights.captures.next();
2526 }
2527
2528 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
2529 let capture = mat.captures[*capture_ix as usize];
2530 if self.range.start < capture.node.start_byte() {
2531 next_capture_start = capture.node.start_byte();
2532 break;
2533 } else {
2534 let highlight_id = highlights.highlight_map.get(capture.index);
2535 highlights
2536 .stack
2537 .push((capture.node.end_byte(), highlight_id));
2538 highlights.next_capture = highlights.captures.next();
2539 }
2540 }
2541 }
2542
2543 while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
2544 if endpoint.offset <= self.range.start {
2545 self.update_diagnostic_depths(endpoint);
2546 self.diagnostic_endpoints.next();
2547 } else {
2548 next_diagnostic_endpoint = endpoint.offset;
2549 break;
2550 }
2551 }
2552
2553 if let Some(chunk) = self.chunks.peek() {
2554 let chunk_start = self.range.start;
2555 let mut chunk_end = (self.chunks.offset() + chunk.len())
2556 .min(next_capture_start)
2557 .min(next_diagnostic_endpoint);
2558 let mut highlight_id = None;
2559 if let Some(highlights) = self.highlights.as_ref() {
2560 if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
2561 chunk_end = chunk_end.min(*parent_capture_end);
2562 highlight_id = Some(*parent_highlight_id);
2563 }
2564 }
2565
2566 let slice =
2567 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2568 self.range.start = chunk_end;
2569 if self.range.start == self.chunks.offset() + chunk.len() {
2570 self.chunks.next().unwrap();
2571 }
2572
2573 Some(Chunk {
2574 text: slice,
2575 highlight_id,
2576 diagnostic: self.current_diagnostic_severity(),
2577 })
2578 } else {
2579 None
2580 }
2581 }
2582}
2583
2584impl QueryCursorHandle {
2585 pub(crate) fn new() -> Self {
2586 QueryCursorHandle(Some(
2587 QUERY_CURSORS
2588 .lock()
2589 .pop()
2590 .unwrap_or_else(|| QueryCursor::new()),
2591 ))
2592 }
2593}
2594
2595impl Deref for QueryCursorHandle {
2596 type Target = QueryCursor;
2597
2598 fn deref(&self) -> &Self::Target {
2599 self.0.as_ref().unwrap()
2600 }
2601}
2602
2603impl DerefMut for QueryCursorHandle {
2604 fn deref_mut(&mut self) -> &mut Self::Target {
2605 self.0.as_mut().unwrap()
2606 }
2607}
2608
2609impl Drop for QueryCursorHandle {
2610 fn drop(&mut self) {
2611 let mut cursor = self.0.take().unwrap();
2612 cursor.set_byte_range(0..usize::MAX);
2613 cursor.set_point_range(Point::zero().to_ts_point()..Point::MAX.to_ts_point());
2614 QUERY_CURSORS.lock().push(cursor)
2615 }
2616}
2617
2618trait ToTreeSitterPoint {
2619 fn to_ts_point(self) -> tree_sitter::Point;
2620 fn from_ts_point(point: tree_sitter::Point) -> Self;
2621}
2622
2623impl ToTreeSitterPoint for Point {
2624 fn to_ts_point(self) -> tree_sitter::Point {
2625 tree_sitter::Point::new(self.row as usize, self.column as usize)
2626 }
2627
2628 fn from_ts_point(point: tree_sitter::Point) -> Self {
2629 Point::new(point.row as u32, point.column as u32)
2630 }
2631}
2632
2633impl operation_queue::Operation for Operation {
2634 fn lamport_timestamp(&self) -> clock::Lamport {
2635 match self {
2636 Operation::Buffer(_) => {
2637 unreachable!("buffer operations should never be deferred at this layer")
2638 }
2639 Operation::UpdateDiagnostics {
2640 lamport_timestamp, ..
2641 }
2642 | Operation::UpdateSelections {
2643 lamport_timestamp, ..
2644 } => *lamport_timestamp,
2645 Operation::UpdateCompletionTriggers { .. } => {
2646 unreachable!("updating completion triggers should never be deferred")
2647 }
2648 }
2649 }
2650}
2651
2652impl Default for Diagnostic {
2653 fn default() -> Self {
2654 Self {
2655 code: Default::default(),
2656 severity: DiagnosticSeverity::ERROR,
2657 message: Default::default(),
2658 group_id: Default::default(),
2659 is_primary: Default::default(),
2660 is_valid: true,
2661 is_disk_based: false,
2662 }
2663 }
2664}
2665
2666impl<T> Completion<T> {
2667 pub fn sort_key(&self) -> (usize, &str) {
2668 let kind_key = match self.lsp_completion.kind {
2669 Some(lsp::CompletionItemKind::VARIABLE) => 0,
2670 _ => 1,
2671 };
2672 (kind_key, &self.label.text[self.label.filter_range.clone()])
2673 }
2674
2675 pub fn is_snippet(&self) -> bool {
2676 self.lsp_completion.insert_text_format == Some(lsp::InsertTextFormat::SNIPPET)
2677 }
2678}
2679
2680pub fn contiguous_ranges(
2681 values: impl Iterator<Item = u32>,
2682 max_len: usize,
2683) -> impl Iterator<Item = Range<u32>> {
2684 let mut values = values.into_iter();
2685 let mut current_range: Option<Range<u32>> = None;
2686 std::iter::from_fn(move || loop {
2687 if let Some(value) = values.next() {
2688 if let Some(range) = &mut current_range {
2689 if value == range.end && range.len() < max_len {
2690 range.end += 1;
2691 continue;
2692 }
2693 }
2694
2695 let prev_range = current_range.clone();
2696 current_range = Some(value..(value + 1));
2697 if prev_range.is_some() {
2698 return prev_range;
2699 }
2700 } else {
2701 return current_range.take();
2702 }
2703 })
2704}