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::{CodeActionKind, 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 code_actions<T>(
1852 &self,
1853 position: T,
1854 cx: &mut ModelContext<Self>,
1855 ) -> Task<Result<Vec<lsp::CodeAction>>>
1856 where
1857 T: ToPointUtf16,
1858 {
1859 let file = if let Some(file) = self.file.as_ref() {
1860 file
1861 } else {
1862 return Task::ready(Ok(Default::default()));
1863 };
1864
1865 if let Some(file) = file.as_local() {
1866 let server = if let Some(language_server) = self.language_server.as_ref() {
1867 language_server.server.clone()
1868 } else {
1869 return Task::ready(Ok(Default::default()));
1870 };
1871 let abs_path = file.abs_path(cx);
1872 let position = position.to_point_utf16(self);
1873
1874 cx.spawn(|this, mut cx| async move {
1875 let actions = server
1876 .request::<lsp::request::CodeActionRequest>(lsp::CodeActionParams {
1877 text_document: lsp::TextDocumentIdentifier::new(
1878 lsp::Url::from_file_path(abs_path).unwrap(),
1879 ),
1880 range: lsp::Range::new(
1881 position.to_lsp_position(),
1882 position.to_lsp_position(),
1883 ),
1884 work_done_progress_params: Default::default(),
1885 partial_result_params: Default::default(),
1886 context: lsp::CodeActionContext {
1887 diagnostics: Default::default(),
1888 only: Some(vec![
1889 lsp::CodeActionKind::QUICKFIX,
1890 lsp::CodeActionKind::REFACTOR,
1891 lsp::CodeActionKind::REFACTOR_EXTRACT,
1892 ]),
1893 },
1894 })
1895 .await?
1896 .unwrap_or_default()
1897 .into_iter()
1898 .filter_map(|entry| {
1899 if let lsp::CodeActionOrCommand::CodeAction(action) = entry {
1900 Some(action)
1901 } else {
1902 None
1903 }
1904 })
1905 .collect();
1906 Ok(actions)
1907 })
1908 } else {
1909 log::info!("code actions are not implemented for guests");
1910 Task::ready(Ok(Default::default()))
1911 }
1912 }
1913
1914 pub fn apply_additional_edits_for_completion(
1915 &mut self,
1916 completion: Completion<Anchor>,
1917 push_to_history: bool,
1918 cx: &mut ModelContext<Self>,
1919 ) -> Task<Result<Vec<clock::Local>>> {
1920 let file = if let Some(file) = self.file.as_ref() {
1921 file
1922 } else {
1923 return Task::ready(Ok(Default::default()));
1924 };
1925
1926 if file.is_local() {
1927 let server = if let Some(lang) = self.language_server.as_ref() {
1928 lang.server.clone()
1929 } else {
1930 return Task::ready(Ok(Default::default()));
1931 };
1932
1933 cx.spawn(|this, mut cx| async move {
1934 let resolved_completion = server
1935 .request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
1936 .await?;
1937 if let Some(additional_edits) = resolved_completion.additional_text_edits {
1938 this.update(&mut cx, |this, cx| {
1939 if !push_to_history {
1940 this.avoid_grouping_next_transaction();
1941 }
1942 this.start_transaction();
1943 let edit_ids = this.apply_lsp_edits(additional_edits, cx);
1944 if let Some(transaction_id) = this.end_transaction(cx) {
1945 if !push_to_history {
1946 this.text.forget_transaction(transaction_id);
1947 }
1948 }
1949 edit_ids
1950 })
1951 } else {
1952 Ok(Default::default())
1953 }
1954 })
1955 } else {
1956 let apply_edits = file.apply_additional_edits_for_completion(
1957 self.remote_id(),
1958 completion,
1959 cx.as_mut(),
1960 );
1961 cx.spawn(|this, mut cx| async move {
1962 let edit_ids = apply_edits.await?;
1963 this.update(&mut cx, |this, _| this.text.wait_for_edits(&edit_ids))
1964 .await;
1965 if push_to_history {
1966 this.update(&mut cx, |this, _| {
1967 this.text
1968 .push_transaction(edit_ids.iter().copied(), Instant::now());
1969 });
1970 }
1971 Ok(edit_ids)
1972 })
1973 }
1974 }
1975
1976 pub fn completion_triggers(&self) -> &[String] {
1977 &self.completion_triggers
1978 }
1979}
1980
1981#[cfg(any(test, feature = "test-support"))]
1982impl Buffer {
1983 pub fn set_group_interval(&mut self, group_interval: Duration) {
1984 self.text.set_group_interval(group_interval);
1985 }
1986
1987 pub fn randomly_edit<T>(
1988 &mut self,
1989 rng: &mut T,
1990 old_range_count: usize,
1991 cx: &mut ModelContext<Self>,
1992 ) where
1993 T: rand::Rng,
1994 {
1995 let mut old_ranges: Vec<Range<usize>> = Vec::new();
1996 for _ in 0..old_range_count {
1997 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
1998 if last_end > self.len() {
1999 break;
2000 }
2001 old_ranges.push(self.text.random_byte_range(last_end, rng));
2002 }
2003 let new_text_len = rng.gen_range(0..10);
2004 let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng)
2005 .take(new_text_len)
2006 .collect();
2007 log::info!(
2008 "mutating buffer {} at {:?}: {:?}",
2009 self.replica_id(),
2010 old_ranges,
2011 new_text
2012 );
2013 self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
2014 }
2015
2016 pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
2017 let was_dirty = self.is_dirty();
2018 let old_version = self.version.clone();
2019
2020 let ops = self.text.randomly_undo_redo(rng);
2021 if !ops.is_empty() {
2022 for op in ops {
2023 self.send_operation(Operation::Buffer(op), cx);
2024 self.did_edit(&old_version, was_dirty, cx);
2025 }
2026 }
2027 }
2028}
2029
2030impl Entity for Buffer {
2031 type Event = Event;
2032
2033 fn release(&mut self, cx: &mut gpui::MutableAppContext) {
2034 if let Some(file) = self.file.as_ref() {
2035 file.buffer_removed(self.remote_id(), cx);
2036 }
2037 }
2038}
2039
2040impl Deref for Buffer {
2041 type Target = TextBuffer;
2042
2043 fn deref(&self) -> &Self::Target {
2044 &self.text
2045 }
2046}
2047
2048impl BufferSnapshot {
2049 fn suggest_autoindents<'a>(
2050 &'a self,
2051 row_range: Range<u32>,
2052 ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
2053 let mut query_cursor = QueryCursorHandle::new();
2054 if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) {
2055 let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
2056
2057 // Get the "indentation ranges" that intersect this row range.
2058 let indent_capture_ix = grammar.indents_query.capture_index_for_name("indent");
2059 let end_capture_ix = grammar.indents_query.capture_index_for_name("end");
2060 query_cursor.set_point_range(
2061 Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point()
2062 ..Point::new(row_range.end, 0).to_ts_point(),
2063 );
2064 let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
2065 for mat in query_cursor.matches(
2066 &grammar.indents_query,
2067 tree.root_node(),
2068 TextProvider(self.as_rope()),
2069 ) {
2070 let mut node_kind = "";
2071 let mut start: Option<Point> = None;
2072 let mut end: Option<Point> = None;
2073 for capture in mat.captures {
2074 if Some(capture.index) == indent_capture_ix {
2075 node_kind = capture.node.kind();
2076 start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
2077 end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
2078 } else if Some(capture.index) == end_capture_ix {
2079 end = Some(Point::from_ts_point(capture.node.start_position().into()));
2080 }
2081 }
2082
2083 if let Some((start, end)) = start.zip(end) {
2084 if start.row == end.row {
2085 continue;
2086 }
2087
2088 let range = start..end;
2089 match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
2090 Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
2091 Ok(ix) => {
2092 let prev_range = &mut indentation_ranges[ix];
2093 prev_range.0.end = prev_range.0.end.max(range.end);
2094 }
2095 }
2096 }
2097 }
2098
2099 let mut prev_row = prev_non_blank_row.unwrap_or(0);
2100 Some(row_range.map(move |row| {
2101 let row_start = Point::new(row, self.indent_column_for_line(row));
2102
2103 let mut indent_from_prev_row = false;
2104 let mut outdent_to_row = u32::MAX;
2105 for (range, _node_kind) in &indentation_ranges {
2106 if range.start.row >= row {
2107 break;
2108 }
2109
2110 if range.start.row == prev_row && range.end > row_start {
2111 indent_from_prev_row = true;
2112 }
2113 if range.end.row >= prev_row && range.end <= row_start {
2114 outdent_to_row = outdent_to_row.min(range.start.row);
2115 }
2116 }
2117
2118 let suggestion = if outdent_to_row == prev_row {
2119 IndentSuggestion {
2120 basis_row: prev_row,
2121 indent: false,
2122 }
2123 } else if indent_from_prev_row {
2124 IndentSuggestion {
2125 basis_row: prev_row,
2126 indent: true,
2127 }
2128 } else if outdent_to_row < prev_row {
2129 IndentSuggestion {
2130 basis_row: outdent_to_row,
2131 indent: false,
2132 }
2133 } else {
2134 IndentSuggestion {
2135 basis_row: prev_row,
2136 indent: false,
2137 }
2138 };
2139
2140 prev_row = row;
2141 suggestion
2142 }))
2143 } else {
2144 None
2145 }
2146 }
2147
2148 fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
2149 while row > 0 {
2150 row -= 1;
2151 if !self.is_line_blank(row) {
2152 return Some(row);
2153 }
2154 }
2155 None
2156 }
2157
2158 pub fn chunks<'a, T: ToOffset>(
2159 &'a self,
2160 range: Range<T>,
2161 language_aware: bool,
2162 ) -> BufferChunks<'a> {
2163 let range = range.start.to_offset(self)..range.end.to_offset(self);
2164
2165 let mut tree = None;
2166 let mut diagnostic_endpoints = Vec::new();
2167 if language_aware {
2168 tree = self.tree.as_ref();
2169 for entry in self.diagnostics_in_range::<_, usize>(range.clone()) {
2170 diagnostic_endpoints.push(DiagnosticEndpoint {
2171 offset: entry.range.start,
2172 is_start: true,
2173 severity: entry.diagnostic.severity,
2174 });
2175 diagnostic_endpoints.push(DiagnosticEndpoint {
2176 offset: entry.range.end,
2177 is_start: false,
2178 severity: entry.diagnostic.severity,
2179 });
2180 }
2181 diagnostic_endpoints
2182 .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
2183 }
2184
2185 BufferChunks::new(
2186 self.text.as_rope(),
2187 range,
2188 tree,
2189 self.grammar(),
2190 diagnostic_endpoints,
2191 )
2192 }
2193
2194 pub fn language(&self) -> Option<&Arc<Language>> {
2195 self.language.as_ref()
2196 }
2197
2198 fn grammar(&self) -> Option<&Arc<Grammar>> {
2199 self.language
2200 .as_ref()
2201 .and_then(|language| language.grammar.as_ref())
2202 }
2203
2204 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2205 let tree = self.tree.as_ref()?;
2206 let range = range.start.to_offset(self)..range.end.to_offset(self);
2207 let mut cursor = tree.root_node().walk();
2208
2209 // Descend to smallest leaf that touches or exceeds the start of the range.
2210 while cursor.goto_first_child_for_byte(range.start).is_some() {}
2211
2212 // Ascend to the smallest ancestor that strictly contains the range.
2213 loop {
2214 let node_range = cursor.node().byte_range();
2215 if node_range.start <= range.start
2216 && node_range.end >= range.end
2217 && node_range.len() > range.len()
2218 {
2219 break;
2220 }
2221 if !cursor.goto_parent() {
2222 break;
2223 }
2224 }
2225
2226 let left_node = cursor.node();
2227
2228 // For an empty range, try to find another node immediately to the right of the range.
2229 if left_node.end_byte() == range.start {
2230 let mut right_node = None;
2231 while !cursor.goto_next_sibling() {
2232 if !cursor.goto_parent() {
2233 break;
2234 }
2235 }
2236
2237 while cursor.node().start_byte() == range.start {
2238 right_node = Some(cursor.node());
2239 if !cursor.goto_first_child() {
2240 break;
2241 }
2242 }
2243
2244 if let Some(right_node) = right_node {
2245 if right_node.is_named() || !left_node.is_named() {
2246 return Some(right_node.byte_range());
2247 }
2248 }
2249 }
2250
2251 Some(left_node.byte_range())
2252 }
2253
2254 pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2255 let tree = self.tree.as_ref()?;
2256 let grammar = self
2257 .language
2258 .as_ref()
2259 .and_then(|language| language.grammar.as_ref())?;
2260
2261 let mut cursor = QueryCursorHandle::new();
2262 let matches = cursor.matches(
2263 &grammar.outline_query,
2264 tree.root_node(),
2265 TextProvider(self.as_rope()),
2266 );
2267
2268 let mut chunks = self.chunks(0..self.len(), true);
2269
2270 let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?;
2271 let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?;
2272 let context_capture_ix = grammar
2273 .outline_query
2274 .capture_index_for_name("context")
2275 .unwrap_or(u32::MAX);
2276
2277 let mut stack = Vec::<Range<usize>>::new();
2278 let items = matches
2279 .filter_map(|mat| {
2280 let item_node = mat.nodes_for_capture_index(item_capture_ix).next()?;
2281 let range = item_node.start_byte()..item_node.end_byte();
2282 let mut text = String::new();
2283 let mut name_ranges = Vec::new();
2284 let mut highlight_ranges = Vec::new();
2285
2286 for capture in mat.captures {
2287 let node_is_name;
2288 if capture.index == name_capture_ix {
2289 node_is_name = true;
2290 } else if capture.index == context_capture_ix {
2291 node_is_name = false;
2292 } else {
2293 continue;
2294 }
2295
2296 let range = capture.node.start_byte()..capture.node.end_byte();
2297 if !text.is_empty() {
2298 text.push(' ');
2299 }
2300 if node_is_name {
2301 let mut start = text.len();
2302 let end = start + range.len();
2303
2304 // When multiple names are captured, then the matcheable text
2305 // includes the whitespace in between the names.
2306 if !name_ranges.is_empty() {
2307 start -= 1;
2308 }
2309
2310 name_ranges.push(start..end);
2311 }
2312
2313 let mut offset = range.start;
2314 chunks.seek(offset);
2315 while let Some(mut chunk) = chunks.next() {
2316 if chunk.text.len() > range.end - offset {
2317 chunk.text = &chunk.text[0..(range.end - offset)];
2318 offset = range.end;
2319 } else {
2320 offset += chunk.text.len();
2321 }
2322 let style = chunk
2323 .highlight_id
2324 .zip(theme)
2325 .and_then(|(highlight, theme)| highlight.style(theme));
2326 if let Some(style) = style {
2327 let start = text.len();
2328 let end = start + chunk.text.len();
2329 highlight_ranges.push((start..end, style));
2330 }
2331 text.push_str(chunk.text);
2332 if offset >= range.end {
2333 break;
2334 }
2335 }
2336 }
2337
2338 while stack.last().map_or(false, |prev_range| {
2339 !prev_range.contains(&range.start) || !prev_range.contains(&range.end)
2340 }) {
2341 stack.pop();
2342 }
2343 stack.push(range.clone());
2344
2345 Some(OutlineItem {
2346 depth: stack.len() - 1,
2347 range: self.anchor_after(range.start)..self.anchor_before(range.end),
2348 text,
2349 highlight_ranges,
2350 name_ranges,
2351 })
2352 })
2353 .collect::<Vec<_>>();
2354
2355 if items.is_empty() {
2356 None
2357 } else {
2358 Some(Outline::new(items))
2359 }
2360 }
2361
2362 pub fn enclosing_bracket_ranges<T: ToOffset>(
2363 &self,
2364 range: Range<T>,
2365 ) -> Option<(Range<usize>, Range<usize>)> {
2366 let (grammar, tree) = self.grammar().zip(self.tree.as_ref())?;
2367 let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?;
2368 let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?;
2369
2370 // Find bracket pairs that *inclusively* contain the given range.
2371 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
2372 let mut cursor = QueryCursorHandle::new();
2373 let matches = cursor.set_byte_range(range).matches(
2374 &grammar.brackets_query,
2375 tree.root_node(),
2376 TextProvider(self.as_rope()),
2377 );
2378
2379 // Get the ranges of the innermost pair of brackets.
2380 matches
2381 .filter_map(|mat| {
2382 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
2383 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
2384 Some((open.byte_range(), close.byte_range()))
2385 })
2386 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
2387 }
2388
2389 /*
2390 impl BufferSnapshot
2391 pub fn remote_selections_in_range(&self, Range<Anchor>) -> impl Iterator<Item = (ReplicaId, impl Iterator<Item = &Selection<Anchor>>)>
2392 pub fn remote_selections_in_range(&self, Range<Anchor>) -> impl Iterator<Item = (ReplicaId, i
2393 */
2394
2395 pub fn remote_selections_in_range<'a>(
2396 &'a self,
2397 range: Range<Anchor>,
2398 ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = &'a Selection<Anchor>>)>
2399 {
2400 self.remote_selections
2401 .iter()
2402 .filter(|(replica_id, set)| {
2403 **replica_id != self.text.replica_id() && !set.selections.is_empty()
2404 })
2405 .map(move |(replica_id, set)| {
2406 let start_ix = match set.selections.binary_search_by(|probe| {
2407 probe
2408 .end
2409 .cmp(&range.start, self)
2410 .unwrap()
2411 .then(Ordering::Greater)
2412 }) {
2413 Ok(ix) | Err(ix) => ix,
2414 };
2415 let end_ix = match set.selections.binary_search_by(|probe| {
2416 probe
2417 .start
2418 .cmp(&range.end, self)
2419 .unwrap()
2420 .then(Ordering::Less)
2421 }) {
2422 Ok(ix) | Err(ix) => ix,
2423 };
2424
2425 (*replica_id, set.selections[start_ix..end_ix].iter())
2426 })
2427 }
2428
2429 pub fn diagnostics_in_range<'a, T, O>(
2430 &'a self,
2431 search_range: Range<T>,
2432 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2433 where
2434 T: 'a + Clone + ToOffset,
2435 O: 'a + FromAnchor,
2436 {
2437 self.diagnostics.range(search_range.clone(), self, true)
2438 }
2439
2440 pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
2441 let mut groups = Vec::new();
2442 self.diagnostics.groups(&mut groups, self);
2443 groups
2444 }
2445
2446 pub fn diagnostic_group<'a, O>(
2447 &'a self,
2448 group_id: usize,
2449 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2450 where
2451 O: 'a + FromAnchor,
2452 {
2453 self.diagnostics.group(group_id, self)
2454 }
2455
2456 pub fn diagnostics_update_count(&self) -> usize {
2457 self.diagnostics_update_count
2458 }
2459
2460 pub fn parse_count(&self) -> usize {
2461 self.parse_count
2462 }
2463
2464 pub fn selections_update_count(&self) -> usize {
2465 self.selections_update_count
2466 }
2467}
2468
2469impl Clone for BufferSnapshot {
2470 fn clone(&self) -> Self {
2471 Self {
2472 text: self.text.clone(),
2473 tree: self.tree.clone(),
2474 remote_selections: self.remote_selections.clone(),
2475 diagnostics: self.diagnostics.clone(),
2476 selections_update_count: self.selections_update_count,
2477 diagnostics_update_count: self.diagnostics_update_count,
2478 is_parsing: self.is_parsing,
2479 language: self.language.clone(),
2480 parse_count: self.parse_count,
2481 }
2482 }
2483}
2484
2485impl Deref for BufferSnapshot {
2486 type Target = text::BufferSnapshot;
2487
2488 fn deref(&self) -> &Self::Target {
2489 &self.text
2490 }
2491}
2492
2493impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
2494 type I = ByteChunks<'a>;
2495
2496 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
2497 ByteChunks(self.0.chunks_in_range(node.byte_range()))
2498 }
2499}
2500
2501pub(crate) struct ByteChunks<'a>(rope::Chunks<'a>);
2502
2503impl<'a> Iterator for ByteChunks<'a> {
2504 type Item = &'a [u8];
2505
2506 fn next(&mut self) -> Option<Self::Item> {
2507 self.0.next().map(str::as_bytes)
2508 }
2509}
2510
2511unsafe impl<'a> Send for BufferChunks<'a> {}
2512
2513impl<'a> BufferChunks<'a> {
2514 pub(crate) fn new(
2515 text: &'a Rope,
2516 range: Range<usize>,
2517 tree: Option<&'a Tree>,
2518 grammar: Option<&'a Arc<Grammar>>,
2519 diagnostic_endpoints: Vec<DiagnosticEndpoint>,
2520 ) -> Self {
2521 let mut highlights = None;
2522 if let Some((grammar, tree)) = grammar.zip(tree) {
2523 let mut query_cursor = QueryCursorHandle::new();
2524
2525 // TODO - add a Tree-sitter API to remove the need for this.
2526 let cursor = unsafe {
2527 std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
2528 };
2529 let captures = cursor.set_byte_range(range.clone()).captures(
2530 &grammar.highlights_query,
2531 tree.root_node(),
2532 TextProvider(text),
2533 );
2534 highlights = Some(BufferChunkHighlights {
2535 captures,
2536 next_capture: None,
2537 stack: Default::default(),
2538 highlight_map: grammar.highlight_map(),
2539 _query_cursor: query_cursor,
2540 })
2541 }
2542
2543 let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
2544 let chunks = text.chunks_in_range(range.clone());
2545
2546 BufferChunks {
2547 range,
2548 chunks,
2549 diagnostic_endpoints,
2550 error_depth: 0,
2551 warning_depth: 0,
2552 information_depth: 0,
2553 hint_depth: 0,
2554 highlights,
2555 }
2556 }
2557
2558 pub fn seek(&mut self, offset: usize) {
2559 self.range.start = offset;
2560 self.chunks.seek(self.range.start);
2561 if let Some(highlights) = self.highlights.as_mut() {
2562 highlights
2563 .stack
2564 .retain(|(end_offset, _)| *end_offset > offset);
2565 if let Some((mat, capture_ix)) = &highlights.next_capture {
2566 let capture = mat.captures[*capture_ix as usize];
2567 if offset >= capture.node.start_byte() {
2568 let next_capture_end = capture.node.end_byte();
2569 if offset < next_capture_end {
2570 highlights.stack.push((
2571 next_capture_end,
2572 highlights.highlight_map.get(capture.index),
2573 ));
2574 }
2575 highlights.next_capture.take();
2576 }
2577 }
2578 highlights.captures.set_byte_range(self.range.clone());
2579 }
2580 }
2581
2582 pub fn offset(&self) -> usize {
2583 self.range.start
2584 }
2585
2586 fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
2587 let depth = match endpoint.severity {
2588 DiagnosticSeverity::ERROR => &mut self.error_depth,
2589 DiagnosticSeverity::WARNING => &mut self.warning_depth,
2590 DiagnosticSeverity::INFORMATION => &mut self.information_depth,
2591 DiagnosticSeverity::HINT => &mut self.hint_depth,
2592 _ => return,
2593 };
2594 if endpoint.is_start {
2595 *depth += 1;
2596 } else {
2597 *depth -= 1;
2598 }
2599 }
2600
2601 fn current_diagnostic_severity(&mut self) -> Option<DiagnosticSeverity> {
2602 if self.error_depth > 0 {
2603 Some(DiagnosticSeverity::ERROR)
2604 } else if self.warning_depth > 0 {
2605 Some(DiagnosticSeverity::WARNING)
2606 } else if self.information_depth > 0 {
2607 Some(DiagnosticSeverity::INFORMATION)
2608 } else if self.hint_depth > 0 {
2609 Some(DiagnosticSeverity::HINT)
2610 } else {
2611 None
2612 }
2613 }
2614}
2615
2616impl<'a> Iterator for BufferChunks<'a> {
2617 type Item = Chunk<'a>;
2618
2619 fn next(&mut self) -> Option<Self::Item> {
2620 let mut next_capture_start = usize::MAX;
2621 let mut next_diagnostic_endpoint = usize::MAX;
2622
2623 if let Some(highlights) = self.highlights.as_mut() {
2624 while let Some((parent_capture_end, _)) = highlights.stack.last() {
2625 if *parent_capture_end <= self.range.start {
2626 highlights.stack.pop();
2627 } else {
2628 break;
2629 }
2630 }
2631
2632 if highlights.next_capture.is_none() {
2633 highlights.next_capture = highlights.captures.next();
2634 }
2635
2636 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
2637 let capture = mat.captures[*capture_ix as usize];
2638 if self.range.start < capture.node.start_byte() {
2639 next_capture_start = capture.node.start_byte();
2640 break;
2641 } else {
2642 let highlight_id = highlights.highlight_map.get(capture.index);
2643 highlights
2644 .stack
2645 .push((capture.node.end_byte(), highlight_id));
2646 highlights.next_capture = highlights.captures.next();
2647 }
2648 }
2649 }
2650
2651 while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
2652 if endpoint.offset <= self.range.start {
2653 self.update_diagnostic_depths(endpoint);
2654 self.diagnostic_endpoints.next();
2655 } else {
2656 next_diagnostic_endpoint = endpoint.offset;
2657 break;
2658 }
2659 }
2660
2661 if let Some(chunk) = self.chunks.peek() {
2662 let chunk_start = self.range.start;
2663 let mut chunk_end = (self.chunks.offset() + chunk.len())
2664 .min(next_capture_start)
2665 .min(next_diagnostic_endpoint);
2666 let mut highlight_id = None;
2667 if let Some(highlights) = self.highlights.as_ref() {
2668 if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
2669 chunk_end = chunk_end.min(*parent_capture_end);
2670 highlight_id = Some(*parent_highlight_id);
2671 }
2672 }
2673
2674 let slice =
2675 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2676 self.range.start = chunk_end;
2677 if self.range.start == self.chunks.offset() + chunk.len() {
2678 self.chunks.next().unwrap();
2679 }
2680
2681 Some(Chunk {
2682 text: slice,
2683 highlight_id,
2684 diagnostic: self.current_diagnostic_severity(),
2685 })
2686 } else {
2687 None
2688 }
2689 }
2690}
2691
2692impl QueryCursorHandle {
2693 pub(crate) fn new() -> Self {
2694 QueryCursorHandle(Some(
2695 QUERY_CURSORS
2696 .lock()
2697 .pop()
2698 .unwrap_or_else(|| QueryCursor::new()),
2699 ))
2700 }
2701}
2702
2703impl Deref for QueryCursorHandle {
2704 type Target = QueryCursor;
2705
2706 fn deref(&self) -> &Self::Target {
2707 self.0.as_ref().unwrap()
2708 }
2709}
2710
2711impl DerefMut for QueryCursorHandle {
2712 fn deref_mut(&mut self) -> &mut Self::Target {
2713 self.0.as_mut().unwrap()
2714 }
2715}
2716
2717impl Drop for QueryCursorHandle {
2718 fn drop(&mut self) {
2719 let mut cursor = self.0.take().unwrap();
2720 cursor.set_byte_range(0..usize::MAX);
2721 cursor.set_point_range(Point::zero().to_ts_point()..Point::MAX.to_ts_point());
2722 QUERY_CURSORS.lock().push(cursor)
2723 }
2724}
2725
2726trait ToTreeSitterPoint {
2727 fn to_ts_point(self) -> tree_sitter::Point;
2728 fn from_ts_point(point: tree_sitter::Point) -> Self;
2729}
2730
2731impl ToTreeSitterPoint for Point {
2732 fn to_ts_point(self) -> tree_sitter::Point {
2733 tree_sitter::Point::new(self.row as usize, self.column as usize)
2734 }
2735
2736 fn from_ts_point(point: tree_sitter::Point) -> Self {
2737 Point::new(point.row as u32, point.column as u32)
2738 }
2739}
2740
2741impl operation_queue::Operation for Operation {
2742 fn lamport_timestamp(&self) -> clock::Lamport {
2743 match self {
2744 Operation::Buffer(_) => {
2745 unreachable!("buffer operations should never be deferred at this layer")
2746 }
2747 Operation::UpdateDiagnostics {
2748 lamport_timestamp, ..
2749 }
2750 | Operation::UpdateSelections {
2751 lamport_timestamp, ..
2752 } => *lamport_timestamp,
2753 Operation::UpdateCompletionTriggers { .. } => {
2754 unreachable!("updating completion triggers should never be deferred")
2755 }
2756 }
2757 }
2758}
2759
2760impl Default for Diagnostic {
2761 fn default() -> Self {
2762 Self {
2763 code: Default::default(),
2764 severity: DiagnosticSeverity::ERROR,
2765 message: Default::default(),
2766 group_id: Default::default(),
2767 is_primary: Default::default(),
2768 is_valid: true,
2769 is_disk_based: false,
2770 }
2771 }
2772}
2773
2774impl<T> Completion<T> {
2775 pub fn sort_key(&self) -> (usize, &str) {
2776 let kind_key = match self.lsp_completion.kind {
2777 Some(lsp::CompletionItemKind::VARIABLE) => 0,
2778 _ => 1,
2779 };
2780 (kind_key, &self.label.text[self.label.filter_range.clone()])
2781 }
2782
2783 pub fn is_snippet(&self) -> bool {
2784 self.lsp_completion.insert_text_format == Some(lsp::InsertTextFormat::SNIPPET)
2785 }
2786}
2787
2788pub fn contiguous_ranges(
2789 values: impl Iterator<Item = u32>,
2790 max_len: usize,
2791) -> impl Iterator<Item = Range<u32>> {
2792 let mut values = values.into_iter();
2793 let mut current_range: Option<Range<u32>> = None;
2794 std::iter::from_fn(move || loop {
2795 if let Some(value) = values.next() {
2796 if let Some(range) = &mut current_range {
2797 if value == range.end && range.len() < max_len {
2798 range.end += 1;
2799 continue;
2800 }
2801 }
2802
2803 let prev_range = current_range.clone();
2804 current_range = Some(value..(value + 1));
2805 if prev_range.is_some() {
2806 return prev_range;
2807 }
2808 } else {
2809 return current_range.take();
2810 }
2811 })
2812}