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