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