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(any(test, feature = "test-support"))]
251pub struct FakeFile {
252 pub path: Arc<Path>,
253}
254
255#[cfg(any(test, 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(any(test, 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
764 pub fn did_save(
765 &mut self,
766 version: clock::Global,
767 mtime: SystemTime,
768 new_file: Option<Box<dyn File>>,
769 cx: &mut ModelContext<Self>,
770 ) {
771 self.saved_mtime = mtime;
772 self.saved_version = version;
773 if let Some(new_file) = new_file {
774 self.file = Some(new_file);
775 }
776 if let Some((state, local_file)) = &self
777 .language_server
778 .as_ref()
779 .zip(self.file.as_ref().and_then(|f| f.as_local()))
780 {
781 cx.background()
782 .spawn(
783 state
784 .server
785 .notify::<lsp::notification::DidSaveTextDocument>(
786 lsp::DidSaveTextDocumentParams {
787 text_document: lsp::TextDocumentIdentifier {
788 uri: lsp::Url::from_file_path(local_file.abs_path(cx)).unwrap(),
789 },
790 text: None,
791 },
792 ),
793 )
794 .detach()
795 }
796 cx.emit(Event::Saved);
797 }
798
799 pub fn did_reload(
800 &mut self,
801 version: clock::Global,
802 mtime: SystemTime,
803 cx: &mut ModelContext<Self>,
804 ) {
805 self.saved_mtime = mtime;
806 self.saved_version = version;
807 if let Some(file) = self.file.as_ref().and_then(|f| f.as_local()) {
808 file.buffer_reloaded(self.remote_id(), &self.saved_version, self.saved_mtime, cx);
809 }
810 cx.emit(Event::Reloaded);
811 cx.notify();
812 }
813
814 pub fn file_updated(
815 &mut self,
816 new_file: Box<dyn File>,
817 cx: &mut ModelContext<Self>,
818 ) -> Task<()> {
819 let old_file = if let Some(file) = self.file.as_ref() {
820 file
821 } else {
822 return Task::ready(());
823 };
824 let mut file_changed = false;
825 let mut task = Task::ready(());
826
827 if new_file.path() != old_file.path() {
828 file_changed = true;
829 }
830
831 if new_file.is_deleted() {
832 if !old_file.is_deleted() {
833 file_changed = true;
834 if !self.is_dirty() {
835 cx.emit(Event::Dirtied);
836 }
837 }
838 } else {
839 let new_mtime = new_file.mtime();
840 if new_mtime != old_file.mtime() {
841 file_changed = true;
842
843 if !self.is_dirty() {
844 task = cx.spawn(|this, mut cx| {
845 async move {
846 let new_text = this.read_with(&cx, |this, cx| {
847 this.file
848 .as_ref()
849 .and_then(|file| file.as_local().map(|f| f.load(cx)))
850 });
851 if let Some(new_text) = new_text {
852 let new_text = new_text.await?;
853 let diff = this
854 .read_with(&cx, |this, cx| this.diff(new_text.into(), cx))
855 .await;
856 this.update(&mut cx, |this, cx| {
857 if this.apply_diff(diff, cx) {
858 this.did_reload(this.version(), new_mtime, cx);
859 }
860 });
861 }
862 Ok(())
863 }
864 .log_err()
865 .map(drop)
866 });
867 }
868 }
869 }
870
871 if file_changed {
872 cx.emit(Event::FileHandleChanged);
873 }
874 self.file = Some(new_file);
875 task
876 }
877
878 pub fn close(&mut self, cx: &mut ModelContext<Self>) {
879 cx.emit(Event::Closed);
880 }
881
882 pub fn language(&self) -> Option<&Arc<Language>> {
883 self.language.as_ref()
884 }
885
886 pub fn language_server(&self) -> Option<&Arc<LanguageServer>> {
887 self.language_server.as_ref().map(|state| &state.server)
888 }
889
890 pub fn parse_count(&self) -> usize {
891 self.parse_count
892 }
893
894 pub fn selections_update_count(&self) -> usize {
895 self.selections_update_count
896 }
897
898 pub fn diagnostics_update_count(&self) -> usize {
899 self.diagnostics_update_count
900 }
901
902 pub(crate) fn syntax_tree(&self) -> Option<Tree> {
903 if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
904 self.interpolate_tree(syntax_tree);
905 Some(syntax_tree.tree.clone())
906 } else {
907 None
908 }
909 }
910
911 #[cfg(any(test, feature = "test-support"))]
912 pub fn is_parsing(&self) -> bool {
913 self.parsing_in_background
914 }
915
916 #[cfg(test)]
917 pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
918 self.sync_parse_timeout = timeout;
919 }
920
921 fn reparse(&mut self, cx: &mut ModelContext<Self>) -> bool {
922 if self.parsing_in_background {
923 return false;
924 }
925
926 if let Some(grammar) = self.grammar().cloned() {
927 let old_tree = self.syntax_tree();
928 let text = self.as_rope().clone();
929 let parsed_version = self.version();
930 let parse_task = cx.background().spawn({
931 let grammar = grammar.clone();
932 async move { grammar.parse_text(&text, old_tree) }
933 });
934
935 match cx
936 .background()
937 .block_with_timeout(self.sync_parse_timeout, parse_task)
938 {
939 Ok(new_tree) => {
940 self.did_finish_parsing(new_tree, parsed_version, cx);
941 return true;
942 }
943 Err(parse_task) => {
944 self.parsing_in_background = true;
945 cx.spawn(move |this, mut cx| async move {
946 let new_tree = parse_task.await;
947 this.update(&mut cx, move |this, cx| {
948 let grammar_changed = this
949 .grammar()
950 .map_or(true, |curr_grammar| !Arc::ptr_eq(&grammar, curr_grammar));
951 let parse_again =
952 this.version.changed_since(&parsed_version) || grammar_changed;
953 this.parsing_in_background = false;
954 this.did_finish_parsing(new_tree, parsed_version, cx);
955
956 if parse_again && this.reparse(cx) {
957 return;
958 }
959 });
960 })
961 .detach();
962 }
963 }
964 }
965 false
966 }
967
968 fn interpolate_tree(&self, tree: &mut SyntaxTree) {
969 for edit in self.edits_since::<(usize, Point)>(&tree.version) {
970 let (bytes, lines) = edit.flatten();
971 tree.tree.edit(&InputEdit {
972 start_byte: bytes.new.start,
973 old_end_byte: bytes.new.start + bytes.old.len(),
974 new_end_byte: bytes.new.end,
975 start_position: lines.new.start.to_ts_point(),
976 old_end_position: (lines.new.start + (lines.old.end - lines.old.start))
977 .to_ts_point(),
978 new_end_position: lines.new.end.to_ts_point(),
979 });
980 }
981 tree.version = self.version();
982 }
983
984 fn did_finish_parsing(
985 &mut self,
986 tree: Tree,
987 version: clock::Global,
988 cx: &mut ModelContext<Self>,
989 ) {
990 self.parse_count += 1;
991 *self.syntax_tree.lock() = Some(SyntaxTree { tree, version });
992 self.request_autoindent(cx);
993 cx.emit(Event::Reparsed);
994 cx.notify();
995 }
996
997 pub fn update_diagnostics<T>(
998 &mut self,
999 mut diagnostics: Vec<DiagnosticEntry<T>>,
1000 version: Option<i32>,
1001 cx: &mut ModelContext<Self>,
1002 ) -> Result<()>
1003 where
1004 T: Copy + Ord + TextDimension + Sub<Output = T> + Clip + ToPoint,
1005 {
1006 fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
1007 Ordering::Equal
1008 .then_with(|| b.is_primary.cmp(&a.is_primary))
1009 .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
1010 .then_with(|| a.severity.cmp(&b.severity))
1011 .then_with(|| a.message.cmp(&b.message))
1012 }
1013
1014 let version = version.map(|version| version as usize);
1015 let content =
1016 if let Some((version, language_server)) = version.zip(self.language_server.as_mut()) {
1017 language_server.snapshot_for_version(version)?
1018 } else {
1019 self.deref()
1020 };
1021
1022 diagnostics.sort_unstable_by(|a, b| {
1023 Ordering::Equal
1024 .then_with(|| a.range.start.cmp(&b.range.start))
1025 .then_with(|| b.range.end.cmp(&a.range.end))
1026 .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
1027 });
1028
1029 let mut sanitized_diagnostics = Vec::new();
1030 let mut edits_since_save = content.edits_since::<T>(&self.saved_version).peekable();
1031 let mut last_edit_old_end = T::default();
1032 let mut last_edit_new_end = T::default();
1033 'outer: for entry in diagnostics {
1034 let mut start = entry.range.start;
1035 let mut end = entry.range.end;
1036
1037 // Some diagnostics are based on files on disk instead of buffers'
1038 // current contents. Adjust these diagnostics' ranges to reflect
1039 // any unsaved edits.
1040 if entry.diagnostic.is_disk_based {
1041 while let Some(edit) = edits_since_save.peek() {
1042 if edit.old.end <= start {
1043 last_edit_old_end = edit.old.end;
1044 last_edit_new_end = edit.new.end;
1045 edits_since_save.next();
1046 } else if edit.old.start <= end && edit.old.end >= start {
1047 continue 'outer;
1048 } else {
1049 break;
1050 }
1051 }
1052
1053 let start_overshoot = start - last_edit_old_end;
1054 start = last_edit_new_end;
1055 start.add_assign(&start_overshoot);
1056
1057 let end_overshoot = end - last_edit_old_end;
1058 end = last_edit_new_end;
1059 end.add_assign(&end_overshoot);
1060 }
1061
1062 let range = start.clip(Bias::Left, content)..end.clip(Bias::Right, content);
1063 let mut range = range.start.to_point(content)..range.end.to_point(content);
1064 // Expand empty ranges by one character
1065 if range.start == range.end {
1066 range.end.column += 1;
1067 range.end = content.clip_point(range.end, Bias::Right);
1068 if range.start == range.end && range.end.column > 0 {
1069 range.start.column -= 1;
1070 range.start = content.clip_point(range.start, Bias::Left);
1071 }
1072 }
1073
1074 sanitized_diagnostics.push(DiagnosticEntry {
1075 range,
1076 diagnostic: entry.diagnostic,
1077 });
1078 }
1079 drop(edits_since_save);
1080
1081 let set = DiagnosticSet::new(sanitized_diagnostics, content);
1082 self.apply_diagnostic_update(set.clone(), cx);
1083
1084 let op = Operation::UpdateDiagnostics {
1085 diagnostics: set.iter().cloned().collect(),
1086 lamport_timestamp: self.text.lamport_clock.tick(),
1087 };
1088 self.send_operation(op, cx);
1089 Ok(())
1090 }
1091
1092 fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
1093 if let Some(indent_columns) = self.compute_autoindents() {
1094 let indent_columns = cx.background().spawn(indent_columns);
1095 match cx
1096 .background()
1097 .block_with_timeout(Duration::from_micros(500), indent_columns)
1098 {
1099 Ok(indent_columns) => self.apply_autoindents(indent_columns, cx),
1100 Err(indent_columns) => {
1101 self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
1102 let indent_columns = indent_columns.await;
1103 this.update(&mut cx, |this, cx| {
1104 this.apply_autoindents(indent_columns, cx);
1105 });
1106 }));
1107 }
1108 }
1109 }
1110 }
1111
1112 fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, u32>>> {
1113 let max_rows_between_yields = 100;
1114 let snapshot = self.snapshot();
1115 if snapshot.language.is_none()
1116 || snapshot.tree.is_none()
1117 || self.autoindent_requests.is_empty()
1118 {
1119 return None;
1120 }
1121
1122 let autoindent_requests = self.autoindent_requests.clone();
1123 Some(async move {
1124 let mut indent_columns = BTreeMap::new();
1125 for request in autoindent_requests {
1126 let old_to_new_rows = request
1127 .edited
1128 .iter()
1129 .map(|anchor| anchor.summary::<Point>(&request.before_edit).row)
1130 .zip(
1131 request
1132 .edited
1133 .iter()
1134 .map(|anchor| anchor.summary::<Point>(&snapshot).row),
1135 )
1136 .collect::<BTreeMap<u32, u32>>();
1137
1138 let mut old_suggestions = HashMap::<u32, u32>::default();
1139 let old_edited_ranges =
1140 contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
1141 for old_edited_range in old_edited_ranges {
1142 let suggestions = request
1143 .before_edit
1144 .suggest_autoindents(old_edited_range.clone())
1145 .into_iter()
1146 .flatten();
1147 for (old_row, suggestion) in old_edited_range.zip(suggestions) {
1148 let indentation_basis = old_to_new_rows
1149 .get(&suggestion.basis_row)
1150 .and_then(|from_row| old_suggestions.get(from_row).copied())
1151 .unwrap_or_else(|| {
1152 request
1153 .before_edit
1154 .indent_column_for_line(suggestion.basis_row)
1155 });
1156 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
1157 old_suggestions.insert(
1158 *old_to_new_rows.get(&old_row).unwrap(),
1159 indentation_basis + delta,
1160 );
1161 }
1162 yield_now().await;
1163 }
1164
1165 // At this point, old_suggestions contains the suggested indentation for all edited lines with respect to the state of the
1166 // buffer before the edit, but keyed by the row for these lines after the edits were applied.
1167 let new_edited_row_ranges =
1168 contiguous_ranges(old_to_new_rows.values().copied(), max_rows_between_yields);
1169 for new_edited_row_range in new_edited_row_ranges {
1170 let suggestions = snapshot
1171 .suggest_autoindents(new_edited_row_range.clone())
1172 .into_iter()
1173 .flatten();
1174 for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
1175 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
1176 let new_indentation = indent_columns
1177 .get(&suggestion.basis_row)
1178 .copied()
1179 .unwrap_or_else(|| {
1180 snapshot.indent_column_for_line(suggestion.basis_row)
1181 })
1182 + delta;
1183 if old_suggestions
1184 .get(&new_row)
1185 .map_or(true, |old_indentation| new_indentation != *old_indentation)
1186 {
1187 indent_columns.insert(new_row, new_indentation);
1188 }
1189 }
1190 yield_now().await;
1191 }
1192
1193 if let Some(inserted) = request.inserted.as_ref() {
1194 let inserted_row_ranges = contiguous_ranges(
1195 inserted
1196 .iter()
1197 .map(|range| range.to_point(&snapshot))
1198 .flat_map(|range| range.start.row..range.end.row + 1),
1199 max_rows_between_yields,
1200 );
1201 for inserted_row_range in inserted_row_ranges {
1202 let suggestions = snapshot
1203 .suggest_autoindents(inserted_row_range.clone())
1204 .into_iter()
1205 .flatten();
1206 for (row, suggestion) in inserted_row_range.zip(suggestions) {
1207 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
1208 let new_indentation = indent_columns
1209 .get(&suggestion.basis_row)
1210 .copied()
1211 .unwrap_or_else(|| {
1212 snapshot.indent_column_for_line(suggestion.basis_row)
1213 })
1214 + delta;
1215 indent_columns.insert(row, new_indentation);
1216 }
1217 yield_now().await;
1218 }
1219 }
1220 }
1221 indent_columns
1222 })
1223 }
1224
1225 fn apply_autoindents(
1226 &mut self,
1227 indent_columns: BTreeMap<u32, u32>,
1228 cx: &mut ModelContext<Self>,
1229 ) {
1230 self.autoindent_requests.clear();
1231 self.start_transaction();
1232 for (row, indent_column) in &indent_columns {
1233 self.set_indent_column_for_line(*row, *indent_column, cx);
1234 }
1235 self.end_transaction(cx);
1236 }
1237
1238 fn set_indent_column_for_line(&mut self, row: u32, column: u32, cx: &mut ModelContext<Self>) {
1239 let current_column = self.indent_column_for_line(row);
1240 if column > current_column {
1241 let offset = Point::new(row, 0).to_offset(&*self);
1242 self.edit(
1243 [offset..offset],
1244 " ".repeat((column - current_column) as usize),
1245 cx,
1246 );
1247 } else if column < current_column {
1248 self.edit(
1249 [Point::new(row, 0)..Point::new(row, current_column - column)],
1250 "",
1251 cx,
1252 );
1253 }
1254 }
1255
1256 pub(crate) fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
1257 // TODO: it would be nice to not allocate here.
1258 let old_text = self.text();
1259 let base_version = self.version();
1260 cx.background().spawn(async move {
1261 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
1262 .iter_all_changes()
1263 .map(|c| (c.tag(), c.value().len()))
1264 .collect::<Vec<_>>();
1265 Diff {
1266 base_version,
1267 new_text,
1268 changes,
1269 }
1270 })
1271 }
1272
1273 pub(crate) fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> bool {
1274 if self.version == diff.base_version {
1275 self.start_transaction();
1276 let mut offset = 0;
1277 for (tag, len) in diff.changes {
1278 let range = offset..(offset + len);
1279 match tag {
1280 ChangeTag::Equal => offset += len,
1281 ChangeTag::Delete => {
1282 self.edit(Some(range), "", cx);
1283 }
1284 ChangeTag::Insert => {
1285 self.edit(Some(offset..offset), &diff.new_text[range], cx);
1286 offset += len;
1287 }
1288 }
1289 }
1290 self.end_transaction(cx);
1291 true
1292 } else {
1293 false
1294 }
1295 }
1296
1297 pub fn is_dirty(&self) -> bool {
1298 !self.saved_version.observed_all(&self.version)
1299 || self.file.as_ref().map_or(false, |file| file.is_deleted())
1300 }
1301
1302 pub fn has_conflict(&self) -> bool {
1303 !self.saved_version.observed_all(&self.version)
1304 && self
1305 .file
1306 .as_ref()
1307 .map_or(false, |file| file.mtime() > self.saved_mtime)
1308 }
1309
1310 pub fn subscribe(&mut self) -> Subscription {
1311 self.text.subscribe()
1312 }
1313
1314 pub fn start_transaction(&mut self) -> Option<TransactionId> {
1315 self.start_transaction_at(Instant::now())
1316 }
1317
1318 pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
1319 self.text.start_transaction_at(now)
1320 }
1321
1322 pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1323 self.end_transaction_at(Instant::now(), cx)
1324 }
1325
1326 pub fn end_transaction_at(
1327 &mut self,
1328 now: Instant,
1329 cx: &mut ModelContext<Self>,
1330 ) -> Option<TransactionId> {
1331 if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
1332 let was_dirty = start_version != self.saved_version;
1333 self.did_edit(&start_version, was_dirty, cx);
1334 Some(transaction_id)
1335 } else {
1336 None
1337 }
1338 }
1339
1340 pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
1341 self.text.push_transaction(transaction, now);
1342 }
1343
1344 pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
1345 self.text.finalize_last_transaction()
1346 }
1347
1348 pub fn forget_transaction(&mut self, transaction_id: TransactionId) {
1349 self.text.forget_transaction(transaction_id);
1350 }
1351
1352 pub fn wait_for_edits(
1353 &mut self,
1354 edit_ids: impl IntoIterator<Item = clock::Local>,
1355 ) -> impl Future<Output = ()> {
1356 self.text.wait_for_edits(edit_ids)
1357 }
1358
1359 pub fn set_active_selections(
1360 &mut self,
1361 selections: Arc<[Selection<Anchor>]>,
1362 cx: &mut ModelContext<Self>,
1363 ) {
1364 let lamport_timestamp = self.text.lamport_clock.tick();
1365 self.remote_selections.insert(
1366 self.text.replica_id(),
1367 SelectionSet {
1368 selections: selections.clone(),
1369 lamport_timestamp,
1370 },
1371 );
1372 self.send_operation(
1373 Operation::UpdateSelections {
1374 selections,
1375 lamport_timestamp,
1376 },
1377 cx,
1378 );
1379 }
1380
1381 pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
1382 self.set_active_selections(Arc::from([]), cx);
1383 }
1384
1385 fn update_language_server(&mut self, cx: &AppContext) {
1386 let language_server = if let Some(language_server) = self.language_server.as_mut() {
1387 language_server
1388 } else {
1389 return;
1390 };
1391 let file = if let Some(file) = self.file.as_ref().and_then(|f| f.as_local()) {
1392 file
1393 } else {
1394 return;
1395 };
1396
1397 let version = post_inc(&mut language_server.next_version);
1398 let snapshot = LanguageServerSnapshot {
1399 buffer_snapshot: self.text.snapshot(),
1400 version,
1401 path: Arc::from(file.abs_path(cx)),
1402 };
1403 language_server
1404 .pending_snapshots
1405 .insert(version, snapshot.clone());
1406 let _ = language_server.latest_snapshot.blocking_send(snapshot);
1407 }
1408
1409 pub fn edit<I, S, T>(
1410 &mut self,
1411 ranges_iter: I,
1412 new_text: T,
1413 cx: &mut ModelContext<Self>,
1414 ) -> Option<clock::Local>
1415 where
1416 I: IntoIterator<Item = Range<S>>,
1417 S: ToOffset,
1418 T: Into<String>,
1419 {
1420 self.edit_internal(ranges_iter, new_text, false, cx)
1421 }
1422
1423 pub fn edit_with_autoindent<I, S, T>(
1424 &mut self,
1425 ranges_iter: I,
1426 new_text: T,
1427 cx: &mut ModelContext<Self>,
1428 ) -> Option<clock::Local>
1429 where
1430 I: IntoIterator<Item = Range<S>>,
1431 S: ToOffset,
1432 T: Into<String>,
1433 {
1434 self.edit_internal(ranges_iter, new_text, true, cx)
1435 }
1436
1437 pub fn edit_internal<I, S, T>(
1438 &mut self,
1439 ranges_iter: I,
1440 new_text: T,
1441 autoindent: bool,
1442 cx: &mut ModelContext<Self>,
1443 ) -> Option<clock::Local>
1444 where
1445 I: IntoIterator<Item = Range<S>>,
1446 S: ToOffset,
1447 T: Into<String>,
1448 {
1449 let new_text = new_text.into();
1450
1451 // Skip invalid ranges and coalesce contiguous ones.
1452 let mut ranges: Vec<Range<usize>> = Vec::new();
1453 for range in ranges_iter {
1454 let range = range.start.to_offset(self)..range.end.to_offset(self);
1455 if !new_text.is_empty() || !range.is_empty() {
1456 if let Some(prev_range) = ranges.last_mut() {
1457 if prev_range.end >= range.start {
1458 prev_range.end = cmp::max(prev_range.end, range.end);
1459 } else {
1460 ranges.push(range);
1461 }
1462 } else {
1463 ranges.push(range);
1464 }
1465 }
1466 }
1467 if ranges.is_empty() {
1468 return None;
1469 }
1470
1471 self.start_transaction();
1472 self.pending_autoindent.take();
1473 let autoindent_request = if autoindent && self.language.is_some() {
1474 let before_edit = self.snapshot();
1475 let edited = ranges
1476 .iter()
1477 .filter_map(|range| {
1478 let start = range.start.to_point(self);
1479 if new_text.starts_with('\n') && start.column == self.line_len(start.row) {
1480 None
1481 } else {
1482 Some(self.anchor_before(range.start))
1483 }
1484 })
1485 .collect();
1486 Some((before_edit, edited))
1487 } else {
1488 None
1489 };
1490
1491 let first_newline_ix = new_text.find('\n');
1492 let new_text_len = new_text.len();
1493
1494 let edit = self.text.edit(ranges.iter().cloned(), new_text);
1495 let edit_id = edit.local_timestamp();
1496
1497 if let Some((before_edit, edited)) = autoindent_request {
1498 let mut inserted = None;
1499 if let Some(first_newline_ix) = first_newline_ix {
1500 let mut delta = 0isize;
1501 inserted = Some(
1502 ranges
1503 .iter()
1504 .map(|range| {
1505 let start =
1506 (delta + range.start as isize) as usize + first_newline_ix + 1;
1507 let end = (delta + range.start as isize) as usize + new_text_len;
1508 delta +=
1509 (range.end as isize - range.start as isize) + new_text_len as isize;
1510 self.anchor_before(start)..self.anchor_after(end)
1511 })
1512 .collect(),
1513 );
1514 }
1515
1516 self.autoindent_requests.push(Arc::new(AutoindentRequest {
1517 before_edit,
1518 edited,
1519 inserted,
1520 }));
1521 }
1522
1523 self.end_transaction(cx);
1524 self.send_operation(Operation::Buffer(edit), cx);
1525 Some(edit_id)
1526 }
1527
1528 pub fn apply_lsp_edits(
1529 &mut self,
1530 edits: impl IntoIterator<Item = lsp::TextEdit>,
1531 version: Option<i32>,
1532 cx: &mut ModelContext<Self>,
1533 ) -> Result<()> {
1534 let mut anchored_edits = Vec::new();
1535 let snapshot =
1536 if let Some((version, language_server)) = version.zip(self.language_server.as_mut()) {
1537 language_server.snapshot_for_version(version as usize)?
1538 } else {
1539 self.deref()
1540 };
1541 for edit in edits {
1542 let range = range_from_lsp(edit.range);
1543 if snapshot.clip_point_utf16(range.start, Bias::Left) != range.start
1544 || snapshot.clip_point_utf16(range.end, Bias::Left) != range.end
1545 {
1546 return Err(anyhow!(
1547 "invalid formatting edits received from language server"
1548 ));
1549 } else {
1550 let start = snapshot.anchor_before(range.start);
1551 let end = snapshot.anchor_before(range.end);
1552 anchored_edits.push((start..end, edit.new_text));
1553 }
1554 }
1555
1556 self.start_transaction();
1557 for (range, new_text) in anchored_edits {
1558 self.edit([range], new_text, cx);
1559 }
1560 self.end_transaction(cx);
1561 Ok(())
1562 }
1563
1564 fn did_edit(
1565 &mut self,
1566 old_version: &clock::Global,
1567 was_dirty: bool,
1568 cx: &mut ModelContext<Self>,
1569 ) {
1570 if self.edits_since::<usize>(old_version).next().is_none() {
1571 return;
1572 }
1573
1574 self.reparse(cx);
1575 self.update_language_server(cx);
1576
1577 cx.emit(Event::Edited);
1578 if !was_dirty {
1579 cx.emit(Event::Dirtied);
1580 }
1581 cx.notify();
1582 }
1583
1584 fn grammar(&self) -> Option<&Arc<Grammar>> {
1585 self.language.as_ref().and_then(|l| l.grammar.as_ref())
1586 }
1587
1588 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1589 &mut self,
1590 ops: I,
1591 cx: &mut ModelContext<Self>,
1592 ) -> Result<()> {
1593 self.pending_autoindent.take();
1594 let was_dirty = self.is_dirty();
1595 let old_version = self.version.clone();
1596 let mut deferred_ops = Vec::new();
1597 let buffer_ops = ops
1598 .into_iter()
1599 .filter_map(|op| match op {
1600 Operation::Buffer(op) => Some(op),
1601 _ => {
1602 if self.can_apply_op(&op) {
1603 self.apply_op(op, cx);
1604 } else {
1605 deferred_ops.push(op);
1606 }
1607 None
1608 }
1609 })
1610 .collect::<Vec<_>>();
1611 self.text.apply_ops(buffer_ops)?;
1612 self.deferred_ops.insert(deferred_ops);
1613 self.flush_deferred_ops(cx);
1614 self.did_edit(&old_version, was_dirty, cx);
1615 // Notify independently of whether the buffer was edited as the operations could include a
1616 // selection update.
1617 cx.notify();
1618 Ok(())
1619 }
1620
1621 fn flush_deferred_ops(&mut self, cx: &mut ModelContext<Self>) {
1622 let mut deferred_ops = Vec::new();
1623 for op in self.deferred_ops.drain().iter().cloned() {
1624 if self.can_apply_op(&op) {
1625 self.apply_op(op, cx);
1626 } else {
1627 deferred_ops.push(op);
1628 }
1629 }
1630 self.deferred_ops.insert(deferred_ops);
1631 }
1632
1633 fn can_apply_op(&self, operation: &Operation) -> bool {
1634 match operation {
1635 Operation::Buffer(_) => {
1636 unreachable!("buffer operations should never be applied at this layer")
1637 }
1638 Operation::UpdateDiagnostics {
1639 diagnostics: diagnostic_set,
1640 ..
1641 } => diagnostic_set.iter().all(|diagnostic| {
1642 self.text.can_resolve(&diagnostic.range.start)
1643 && self.text.can_resolve(&diagnostic.range.end)
1644 }),
1645 Operation::UpdateSelections { selections, .. } => selections
1646 .iter()
1647 .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
1648 Operation::UpdateCompletionTriggers { .. } => true,
1649 }
1650 }
1651
1652 fn apply_op(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1653 match operation {
1654 Operation::Buffer(_) => {
1655 unreachable!("buffer operations should never be applied at this layer")
1656 }
1657 Operation::UpdateDiagnostics {
1658 diagnostics: diagnostic_set,
1659 ..
1660 } => {
1661 let snapshot = self.snapshot();
1662 self.apply_diagnostic_update(
1663 DiagnosticSet::from_sorted_entries(diagnostic_set.iter().cloned(), &snapshot),
1664 cx,
1665 );
1666 }
1667 Operation::UpdateSelections {
1668 selections,
1669 lamport_timestamp,
1670 } => {
1671 if let Some(set) = self.remote_selections.get(&lamport_timestamp.replica_id) {
1672 if set.lamport_timestamp > lamport_timestamp {
1673 return;
1674 }
1675 }
1676
1677 self.remote_selections.insert(
1678 lamport_timestamp.replica_id,
1679 SelectionSet {
1680 selections,
1681 lamport_timestamp,
1682 },
1683 );
1684 self.text.lamport_clock.observe(lamport_timestamp);
1685 self.selections_update_count += 1;
1686 }
1687 Operation::UpdateCompletionTriggers {
1688 triggers,
1689 lamport_timestamp,
1690 } => {
1691 self.completion_triggers = triggers;
1692 self.text.lamport_clock.observe(lamport_timestamp);
1693 }
1694 }
1695 }
1696
1697 fn apply_diagnostic_update(&mut self, diagnostics: DiagnosticSet, cx: &mut ModelContext<Self>) {
1698 self.diagnostics = diagnostics;
1699 self.diagnostics_update_count += 1;
1700 cx.notify();
1701 cx.emit(Event::DiagnosticsUpdated);
1702 }
1703
1704 #[cfg(not(test))]
1705 pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1706 if let Some(file) = &self.file {
1707 file.buffer_updated(self.remote_id(), operation, cx.as_mut());
1708 }
1709 }
1710
1711 #[cfg(test)]
1712 pub fn send_operation(&mut self, operation: Operation, _: &mut ModelContext<Self>) {
1713 self.operations.push(operation);
1714 }
1715
1716 pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1717 self.remote_selections.remove(&replica_id);
1718 cx.notify();
1719 }
1720
1721 pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1722 let was_dirty = self.is_dirty();
1723 let old_version = self.version.clone();
1724
1725 if let Some((transaction_id, operation)) = self.text.undo() {
1726 self.send_operation(Operation::Buffer(operation), cx);
1727 self.did_edit(&old_version, was_dirty, cx);
1728 Some(transaction_id)
1729 } else {
1730 None
1731 }
1732 }
1733
1734 pub fn undo_transaction(
1735 &mut self,
1736 transaction_id: TransactionId,
1737 cx: &mut ModelContext<Self>,
1738 ) -> bool {
1739 let was_dirty = self.is_dirty();
1740 let old_version = self.version.clone();
1741
1742 if let Some(operation) = self.text.undo_transaction(transaction_id) {
1743 self.send_operation(Operation::Buffer(operation), cx);
1744 self.did_edit(&old_version, was_dirty, cx);
1745 true
1746 } else {
1747 false
1748 }
1749 }
1750
1751 pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1752 let was_dirty = self.is_dirty();
1753 let old_version = self.version.clone();
1754
1755 if let Some((transaction_id, operation)) = self.text.redo() {
1756 self.send_operation(Operation::Buffer(operation), cx);
1757 self.did_edit(&old_version, was_dirty, cx);
1758 Some(transaction_id)
1759 } else {
1760 None
1761 }
1762 }
1763
1764 pub fn redo_transaction(
1765 &mut self,
1766 transaction_id: TransactionId,
1767 cx: &mut ModelContext<Self>,
1768 ) -> bool {
1769 let was_dirty = self.is_dirty();
1770 let old_version = self.version.clone();
1771
1772 if let Some(operation) = self.text.redo_transaction(transaction_id) {
1773 self.send_operation(Operation::Buffer(operation), cx);
1774 self.did_edit(&old_version, was_dirty, cx);
1775 true
1776 } else {
1777 false
1778 }
1779 }
1780
1781 pub fn completions<T>(
1782 &self,
1783 position: T,
1784 cx: &mut ModelContext<Self>,
1785 ) -> Task<Result<Vec<Completion<Anchor>>>>
1786 where
1787 T: ToOffset,
1788 {
1789 let file = if let Some(file) = self.file.as_ref() {
1790 file
1791 } else {
1792 return Task::ready(Ok(Default::default()));
1793 };
1794 let language = self.language.clone();
1795
1796 if let Some(file) = file.as_local() {
1797 let server = if let Some(language_server) = self.language_server.as_ref() {
1798 language_server.server.clone()
1799 } else {
1800 return Task::ready(Ok(Default::default()));
1801 };
1802 let abs_path = file.abs_path(cx);
1803 let position = self.offset_to_point_utf16(position.to_offset(self));
1804
1805 cx.spawn(|this, cx| async move {
1806 let completions = server
1807 .request::<lsp::request::Completion>(lsp::CompletionParams {
1808 text_document_position: lsp::TextDocumentPositionParams::new(
1809 lsp::TextDocumentIdentifier::new(
1810 lsp::Url::from_file_path(abs_path).unwrap(),
1811 ),
1812 position.to_lsp_position(),
1813 ),
1814 context: Default::default(),
1815 work_done_progress_params: Default::default(),
1816 partial_result_params: Default::default(),
1817 })
1818 .await?;
1819
1820 let completions = if let Some(completions) = completions {
1821 match completions {
1822 lsp::CompletionResponse::Array(completions) => completions,
1823 lsp::CompletionResponse::List(list) => list.items,
1824 }
1825 } else {
1826 Default::default()
1827 };
1828
1829 this.read_with(&cx, |this, _| {
1830 Ok(completions.into_iter().filter_map(|lsp_completion| {
1831 let (old_range, new_text) = match lsp_completion.text_edit.as_ref()? {
1832 lsp::CompletionTextEdit::Edit(edit) => (range_from_lsp(edit.range), edit.new_text.clone()),
1833 lsp::CompletionTextEdit::InsertAndReplace(_) => {
1834 log::info!("received an insert and replace completion but we don't yet support that");
1835 return None
1836 },
1837 };
1838
1839 let clipped_start = this.clip_point_utf16(old_range.start, Bias::Left);
1840 let clipped_end = this.clip_point_utf16(old_range.end, Bias::Left) ;
1841 if clipped_start == old_range.start && clipped_end == old_range.end {
1842 Some(Completion {
1843 old_range: this.anchor_before(old_range.start)..this.anchor_after(old_range.end),
1844 new_text,
1845 label: language.as_ref().and_then(|l| l.label_for_completion(&lsp_completion)).unwrap_or_else(|| CompletionLabel::plain(&lsp_completion)),
1846 lsp_completion,
1847 })
1848 } else {
1849 None
1850 }
1851 }).collect())
1852 })
1853 })
1854 } else {
1855 file.completions(
1856 self.remote_id(),
1857 self.anchor_before(position),
1858 language,
1859 cx.as_mut(),
1860 )
1861 }
1862 }
1863
1864 pub fn code_actions<T>(
1865 &self,
1866 position: T,
1867 cx: &mut ModelContext<Self>,
1868 ) -> Task<Result<Vec<CodeAction<Anchor>>>>
1869 where
1870 T: ToPointUtf16,
1871 {
1872 let file = if let Some(file) = self.file.as_ref() {
1873 file
1874 } else {
1875 return Task::ready(Ok(Default::default()));
1876 };
1877 let position = position.to_point_utf16(self);
1878 let anchor = self.anchor_after(position);
1879
1880 if let Some(file) = file.as_local() {
1881 let server = if let Some(language_server) = self.language_server.as_ref() {
1882 language_server.server.clone()
1883 } else {
1884 return Task::ready(Ok(Default::default()));
1885 };
1886 let abs_path = file.abs_path(cx);
1887
1888 cx.foreground().spawn(async move {
1889 let actions = server
1890 .request::<lsp::request::CodeActionRequest>(lsp::CodeActionParams {
1891 text_document: lsp::TextDocumentIdentifier::new(
1892 lsp::Url::from_file_path(abs_path).unwrap(),
1893 ),
1894 range: lsp::Range::new(
1895 position.to_lsp_position(),
1896 position.to_lsp_position(),
1897 ),
1898 work_done_progress_params: Default::default(),
1899 partial_result_params: Default::default(),
1900 context: lsp::CodeActionContext {
1901 diagnostics: Default::default(),
1902 only: Some(vec![
1903 lsp::CodeActionKind::QUICKFIX,
1904 lsp::CodeActionKind::REFACTOR,
1905 lsp::CodeActionKind::REFACTOR_EXTRACT,
1906 ]),
1907 },
1908 })
1909 .await?
1910 .unwrap_or_default()
1911 .into_iter()
1912 .filter_map(|entry| {
1913 if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
1914 Some(CodeAction {
1915 position: anchor.clone(),
1916 lsp_action,
1917 })
1918 } else {
1919 None
1920 }
1921 })
1922 .collect();
1923 Ok(actions)
1924 })
1925 } else {
1926 file.code_actions(self.remote_id(), anchor, cx.as_mut())
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<Option<Transaction>>> {
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 this.finalize_last_transaction();
1956 this.start_transaction();
1957 this.apply_lsp_edits(additional_edits, None, cx).log_err();
1958 let transaction = if this.end_transaction(cx).is_some() {
1959 let transaction = this.finalize_last_transaction().unwrap().clone();
1960 if !push_to_history {
1961 this.forget_transaction(transaction.id);
1962 }
1963 Some(transaction)
1964 } else {
1965 None
1966 };
1967 Ok(transaction)
1968 })
1969 } else {
1970 Ok(None)
1971 }
1972 })
1973 } else {
1974 let apply_edits = file.apply_additional_edits_for_completion(
1975 self.remote_id(),
1976 completion,
1977 cx.as_mut(),
1978 );
1979 cx.spawn(|this, mut cx| async move {
1980 if let Some(transaction) = apply_edits.await? {
1981 this.update(&mut cx, |this, _| {
1982 this.wait_for_edits(transaction.edit_ids.iter().copied())
1983 })
1984 .await;
1985 if push_to_history {
1986 this.update(&mut cx, |this, _| {
1987 this.push_transaction(transaction.clone(), Instant::now());
1988 });
1989 }
1990 Ok(Some(transaction))
1991 } else {
1992 Ok(None)
1993 }
1994 })
1995 }
1996 }
1997
1998 pub fn completion_triggers(&self) -> &[String] {
1999 &self.completion_triggers
2000 }
2001}
2002
2003#[cfg(any(test, feature = "test-support"))]
2004impl Buffer {
2005 pub fn set_group_interval(&mut self, group_interval: Duration) {
2006 self.text.set_group_interval(group_interval);
2007 }
2008
2009 pub fn randomly_edit<T>(
2010 &mut self,
2011 rng: &mut T,
2012 old_range_count: usize,
2013 cx: &mut ModelContext<Self>,
2014 ) where
2015 T: rand::Rng,
2016 {
2017 let mut old_ranges: Vec<Range<usize>> = Vec::new();
2018 for _ in 0..old_range_count {
2019 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
2020 if last_end > self.len() {
2021 break;
2022 }
2023 old_ranges.push(self.text.random_byte_range(last_end, rng));
2024 }
2025 let new_text_len = rng.gen_range(0..10);
2026 let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng)
2027 .take(new_text_len)
2028 .collect();
2029 log::info!(
2030 "mutating buffer {} at {:?}: {:?}",
2031 self.replica_id(),
2032 old_ranges,
2033 new_text
2034 );
2035 self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
2036 }
2037
2038 pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
2039 let was_dirty = self.is_dirty();
2040 let old_version = self.version.clone();
2041
2042 let ops = self.text.randomly_undo_redo(rng);
2043 if !ops.is_empty() {
2044 for op in ops {
2045 self.send_operation(Operation::Buffer(op), cx);
2046 self.did_edit(&old_version, was_dirty, cx);
2047 }
2048 }
2049 }
2050}
2051
2052impl Entity for Buffer {
2053 type Event = Event;
2054
2055 fn release(&mut self, cx: &mut gpui::MutableAppContext) {
2056 if let Some(file) = self.file.as_ref() {
2057 file.buffer_removed(self.remote_id(), cx);
2058 if let Some((lang_server, file)) = self.language_server.as_ref().zip(file.as_local()) {
2059 let request = lang_server
2060 .server
2061 .notify::<lsp::notification::DidCloseTextDocument>(
2062 lsp::DidCloseTextDocumentParams {
2063 text_document: lsp::TextDocumentIdentifier::new(
2064 lsp::Url::from_file_path(file.abs_path(cx)).unwrap(),
2065 ),
2066 },
2067 );
2068 cx.foreground().spawn(request).detach_and_log_err(cx);
2069 }
2070 }
2071 }
2072}
2073
2074impl Deref for Buffer {
2075 type Target = TextBuffer;
2076
2077 fn deref(&self) -> &Self::Target {
2078 &self.text
2079 }
2080}
2081
2082impl BufferSnapshot {
2083 fn suggest_autoindents<'a>(
2084 &'a self,
2085 row_range: Range<u32>,
2086 ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
2087 let mut query_cursor = QueryCursorHandle::new();
2088 if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) {
2089 let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
2090
2091 // Get the "indentation ranges" that intersect this row range.
2092 let indent_capture_ix = grammar.indents_query.capture_index_for_name("indent");
2093 let end_capture_ix = grammar.indents_query.capture_index_for_name("end");
2094 query_cursor.set_point_range(
2095 Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point()
2096 ..Point::new(row_range.end, 0).to_ts_point(),
2097 );
2098 let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
2099 for mat in query_cursor.matches(
2100 &grammar.indents_query,
2101 tree.root_node(),
2102 TextProvider(self.as_rope()),
2103 ) {
2104 let mut node_kind = "";
2105 let mut start: Option<Point> = None;
2106 let mut end: Option<Point> = None;
2107 for capture in mat.captures {
2108 if Some(capture.index) == indent_capture_ix {
2109 node_kind = capture.node.kind();
2110 start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
2111 end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
2112 } else if Some(capture.index) == end_capture_ix {
2113 end = Some(Point::from_ts_point(capture.node.start_position().into()));
2114 }
2115 }
2116
2117 if let Some((start, end)) = start.zip(end) {
2118 if start.row == end.row {
2119 continue;
2120 }
2121
2122 let range = start..end;
2123 match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
2124 Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
2125 Ok(ix) => {
2126 let prev_range = &mut indentation_ranges[ix];
2127 prev_range.0.end = prev_range.0.end.max(range.end);
2128 }
2129 }
2130 }
2131 }
2132
2133 let mut prev_row = prev_non_blank_row.unwrap_or(0);
2134 Some(row_range.map(move |row| {
2135 let row_start = Point::new(row, self.indent_column_for_line(row));
2136
2137 let mut indent_from_prev_row = false;
2138 let mut outdent_to_row = u32::MAX;
2139 for (range, _node_kind) in &indentation_ranges {
2140 if range.start.row >= row {
2141 break;
2142 }
2143
2144 if range.start.row == prev_row && range.end > row_start {
2145 indent_from_prev_row = true;
2146 }
2147 if range.end.row >= prev_row && range.end <= row_start {
2148 outdent_to_row = outdent_to_row.min(range.start.row);
2149 }
2150 }
2151
2152 let suggestion = if outdent_to_row == prev_row {
2153 IndentSuggestion {
2154 basis_row: prev_row,
2155 indent: false,
2156 }
2157 } else if indent_from_prev_row {
2158 IndentSuggestion {
2159 basis_row: prev_row,
2160 indent: true,
2161 }
2162 } else if outdent_to_row < prev_row {
2163 IndentSuggestion {
2164 basis_row: outdent_to_row,
2165 indent: false,
2166 }
2167 } else {
2168 IndentSuggestion {
2169 basis_row: prev_row,
2170 indent: false,
2171 }
2172 };
2173
2174 prev_row = row;
2175 suggestion
2176 }))
2177 } else {
2178 None
2179 }
2180 }
2181
2182 fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
2183 while row > 0 {
2184 row -= 1;
2185 if !self.is_line_blank(row) {
2186 return Some(row);
2187 }
2188 }
2189 None
2190 }
2191
2192 pub fn chunks<'a, T: ToOffset>(
2193 &'a self,
2194 range: Range<T>,
2195 language_aware: bool,
2196 ) -> BufferChunks<'a> {
2197 let range = range.start.to_offset(self)..range.end.to_offset(self);
2198
2199 let mut tree = None;
2200 let mut diagnostic_endpoints = Vec::new();
2201 if language_aware {
2202 tree = self.tree.as_ref();
2203 for entry in self.diagnostics_in_range::<_, usize>(range.clone()) {
2204 diagnostic_endpoints.push(DiagnosticEndpoint {
2205 offset: entry.range.start,
2206 is_start: true,
2207 severity: entry.diagnostic.severity,
2208 });
2209 diagnostic_endpoints.push(DiagnosticEndpoint {
2210 offset: entry.range.end,
2211 is_start: false,
2212 severity: entry.diagnostic.severity,
2213 });
2214 }
2215 diagnostic_endpoints
2216 .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
2217 }
2218
2219 BufferChunks::new(
2220 self.text.as_rope(),
2221 range,
2222 tree,
2223 self.grammar(),
2224 diagnostic_endpoints,
2225 )
2226 }
2227
2228 pub fn language(&self) -> Option<&Arc<Language>> {
2229 self.language.as_ref()
2230 }
2231
2232 fn grammar(&self) -> Option<&Arc<Grammar>> {
2233 self.language
2234 .as_ref()
2235 .and_then(|language| language.grammar.as_ref())
2236 }
2237
2238 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2239 let tree = self.tree.as_ref()?;
2240 let range = range.start.to_offset(self)..range.end.to_offset(self);
2241 let mut cursor = tree.root_node().walk();
2242
2243 // Descend to smallest leaf that touches or exceeds the start of the range.
2244 while cursor.goto_first_child_for_byte(range.start).is_some() {}
2245
2246 // Ascend to the smallest ancestor that strictly contains the range.
2247 loop {
2248 let node_range = cursor.node().byte_range();
2249 if node_range.start <= range.start
2250 && node_range.end >= range.end
2251 && node_range.len() > range.len()
2252 {
2253 break;
2254 }
2255 if !cursor.goto_parent() {
2256 break;
2257 }
2258 }
2259
2260 let left_node = cursor.node();
2261
2262 // For an empty range, try to find another node immediately to the right of the range.
2263 if left_node.end_byte() == range.start {
2264 let mut right_node = None;
2265 while !cursor.goto_next_sibling() {
2266 if !cursor.goto_parent() {
2267 break;
2268 }
2269 }
2270
2271 while cursor.node().start_byte() == range.start {
2272 right_node = Some(cursor.node());
2273 if !cursor.goto_first_child() {
2274 break;
2275 }
2276 }
2277
2278 if let Some(right_node) = right_node {
2279 if right_node.is_named() || !left_node.is_named() {
2280 return Some(right_node.byte_range());
2281 }
2282 }
2283 }
2284
2285 Some(left_node.byte_range())
2286 }
2287
2288 pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2289 let tree = self.tree.as_ref()?;
2290 let grammar = self
2291 .language
2292 .as_ref()
2293 .and_then(|language| language.grammar.as_ref())?;
2294
2295 let mut cursor = QueryCursorHandle::new();
2296 let matches = cursor.matches(
2297 &grammar.outline_query,
2298 tree.root_node(),
2299 TextProvider(self.as_rope()),
2300 );
2301
2302 let mut chunks = self.chunks(0..self.len(), true);
2303
2304 let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?;
2305 let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?;
2306 let context_capture_ix = grammar
2307 .outline_query
2308 .capture_index_for_name("context")
2309 .unwrap_or(u32::MAX);
2310
2311 let mut stack = Vec::<Range<usize>>::new();
2312 let items = matches
2313 .filter_map(|mat| {
2314 let item_node = mat.nodes_for_capture_index(item_capture_ix).next()?;
2315 let range = item_node.start_byte()..item_node.end_byte();
2316 let mut text = String::new();
2317 let mut name_ranges = Vec::new();
2318 let mut highlight_ranges = Vec::new();
2319
2320 for capture in mat.captures {
2321 let node_is_name;
2322 if capture.index == name_capture_ix {
2323 node_is_name = true;
2324 } else if capture.index == context_capture_ix {
2325 node_is_name = false;
2326 } else {
2327 continue;
2328 }
2329
2330 let range = capture.node.start_byte()..capture.node.end_byte();
2331 if !text.is_empty() {
2332 text.push(' ');
2333 }
2334 if node_is_name {
2335 let mut start = text.len();
2336 let end = start + range.len();
2337
2338 // When multiple names are captured, then the matcheable text
2339 // includes the whitespace in between the names.
2340 if !name_ranges.is_empty() {
2341 start -= 1;
2342 }
2343
2344 name_ranges.push(start..end);
2345 }
2346
2347 let mut offset = range.start;
2348 chunks.seek(offset);
2349 while let Some(mut chunk) = chunks.next() {
2350 if chunk.text.len() > range.end - offset {
2351 chunk.text = &chunk.text[0..(range.end - offset)];
2352 offset = range.end;
2353 } else {
2354 offset += chunk.text.len();
2355 }
2356 let style = chunk
2357 .highlight_id
2358 .zip(theme)
2359 .and_then(|(highlight, theme)| highlight.style(theme));
2360 if let Some(style) = style {
2361 let start = text.len();
2362 let end = start + chunk.text.len();
2363 highlight_ranges.push((start..end, style));
2364 }
2365 text.push_str(chunk.text);
2366 if offset >= range.end {
2367 break;
2368 }
2369 }
2370 }
2371
2372 while stack.last().map_or(false, |prev_range| {
2373 !prev_range.contains(&range.start) || !prev_range.contains(&range.end)
2374 }) {
2375 stack.pop();
2376 }
2377 stack.push(range.clone());
2378
2379 Some(OutlineItem {
2380 depth: stack.len() - 1,
2381 range: self.anchor_after(range.start)..self.anchor_before(range.end),
2382 text,
2383 highlight_ranges,
2384 name_ranges,
2385 })
2386 })
2387 .collect::<Vec<_>>();
2388
2389 if items.is_empty() {
2390 None
2391 } else {
2392 Some(Outline::new(items))
2393 }
2394 }
2395
2396 pub fn enclosing_bracket_ranges<T: ToOffset>(
2397 &self,
2398 range: Range<T>,
2399 ) -> Option<(Range<usize>, Range<usize>)> {
2400 let (grammar, tree) = self.grammar().zip(self.tree.as_ref())?;
2401 let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?;
2402 let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?;
2403
2404 // Find bracket pairs that *inclusively* contain the given range.
2405 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
2406 let mut cursor = QueryCursorHandle::new();
2407 let matches = cursor.set_byte_range(range).matches(
2408 &grammar.brackets_query,
2409 tree.root_node(),
2410 TextProvider(self.as_rope()),
2411 );
2412
2413 // Get the ranges of the innermost pair of brackets.
2414 matches
2415 .filter_map(|mat| {
2416 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
2417 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
2418 Some((open.byte_range(), close.byte_range()))
2419 })
2420 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
2421 }
2422
2423 /*
2424 impl BufferSnapshot
2425 pub fn remote_selections_in_range(&self, Range<Anchor>) -> impl Iterator<Item = (ReplicaId, impl Iterator<Item = &Selection<Anchor>>)>
2426 pub fn remote_selections_in_range(&self, Range<Anchor>) -> impl Iterator<Item = (ReplicaId, i
2427 */
2428
2429 pub fn remote_selections_in_range<'a>(
2430 &'a self,
2431 range: Range<Anchor>,
2432 ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = &'a Selection<Anchor>>)>
2433 {
2434 self.remote_selections
2435 .iter()
2436 .filter(|(replica_id, set)| {
2437 **replica_id != self.text.replica_id() && !set.selections.is_empty()
2438 })
2439 .map(move |(replica_id, set)| {
2440 let start_ix = match set.selections.binary_search_by(|probe| {
2441 probe
2442 .end
2443 .cmp(&range.start, self)
2444 .unwrap()
2445 .then(Ordering::Greater)
2446 }) {
2447 Ok(ix) | Err(ix) => ix,
2448 };
2449 let end_ix = match set.selections.binary_search_by(|probe| {
2450 probe
2451 .start
2452 .cmp(&range.end, self)
2453 .unwrap()
2454 .then(Ordering::Less)
2455 }) {
2456 Ok(ix) | Err(ix) => ix,
2457 };
2458
2459 (*replica_id, set.selections[start_ix..end_ix].iter())
2460 })
2461 }
2462
2463 pub fn diagnostics_in_range<'a, T, O>(
2464 &'a self,
2465 search_range: Range<T>,
2466 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2467 where
2468 T: 'a + Clone + ToOffset,
2469 O: 'a + FromAnchor,
2470 {
2471 self.diagnostics.range(search_range.clone(), self, true)
2472 }
2473
2474 pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
2475 let mut groups = Vec::new();
2476 self.diagnostics.groups(&mut groups, self);
2477 groups
2478 }
2479
2480 pub fn diagnostic_group<'a, O>(
2481 &'a self,
2482 group_id: usize,
2483 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2484 where
2485 O: 'a + FromAnchor,
2486 {
2487 self.diagnostics.group(group_id, self)
2488 }
2489
2490 pub fn diagnostics_update_count(&self) -> usize {
2491 self.diagnostics_update_count
2492 }
2493
2494 pub fn parse_count(&self) -> usize {
2495 self.parse_count
2496 }
2497
2498 pub fn selections_update_count(&self) -> usize {
2499 self.selections_update_count
2500 }
2501}
2502
2503impl Clone for BufferSnapshot {
2504 fn clone(&self) -> Self {
2505 Self {
2506 text: self.text.clone(),
2507 tree: self.tree.clone(),
2508 remote_selections: self.remote_selections.clone(),
2509 diagnostics: self.diagnostics.clone(),
2510 selections_update_count: self.selections_update_count,
2511 diagnostics_update_count: self.diagnostics_update_count,
2512 is_parsing: self.is_parsing,
2513 language: self.language.clone(),
2514 parse_count: self.parse_count,
2515 }
2516 }
2517}
2518
2519impl Deref for BufferSnapshot {
2520 type Target = text::BufferSnapshot;
2521
2522 fn deref(&self) -> &Self::Target {
2523 &self.text
2524 }
2525}
2526
2527impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
2528 type I = ByteChunks<'a>;
2529
2530 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
2531 ByteChunks(self.0.chunks_in_range(node.byte_range()))
2532 }
2533}
2534
2535pub(crate) struct ByteChunks<'a>(rope::Chunks<'a>);
2536
2537impl<'a> Iterator for ByteChunks<'a> {
2538 type Item = &'a [u8];
2539
2540 fn next(&mut self) -> Option<Self::Item> {
2541 self.0.next().map(str::as_bytes)
2542 }
2543}
2544
2545unsafe impl<'a> Send for BufferChunks<'a> {}
2546
2547impl<'a> BufferChunks<'a> {
2548 pub(crate) fn new(
2549 text: &'a Rope,
2550 range: Range<usize>,
2551 tree: Option<&'a Tree>,
2552 grammar: Option<&'a Arc<Grammar>>,
2553 diagnostic_endpoints: Vec<DiagnosticEndpoint>,
2554 ) -> Self {
2555 let mut highlights = None;
2556 if let Some((grammar, tree)) = grammar.zip(tree) {
2557 let mut query_cursor = QueryCursorHandle::new();
2558
2559 // TODO - add a Tree-sitter API to remove the need for this.
2560 let cursor = unsafe {
2561 std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
2562 };
2563 let captures = cursor.set_byte_range(range.clone()).captures(
2564 &grammar.highlights_query,
2565 tree.root_node(),
2566 TextProvider(text),
2567 );
2568 highlights = Some(BufferChunkHighlights {
2569 captures,
2570 next_capture: None,
2571 stack: Default::default(),
2572 highlight_map: grammar.highlight_map(),
2573 _query_cursor: query_cursor,
2574 })
2575 }
2576
2577 let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
2578 let chunks = text.chunks_in_range(range.clone());
2579
2580 BufferChunks {
2581 range,
2582 chunks,
2583 diagnostic_endpoints,
2584 error_depth: 0,
2585 warning_depth: 0,
2586 information_depth: 0,
2587 hint_depth: 0,
2588 highlights,
2589 }
2590 }
2591
2592 pub fn seek(&mut self, offset: usize) {
2593 self.range.start = offset;
2594 self.chunks.seek(self.range.start);
2595 if let Some(highlights) = self.highlights.as_mut() {
2596 highlights
2597 .stack
2598 .retain(|(end_offset, _)| *end_offset > offset);
2599 if let Some((mat, capture_ix)) = &highlights.next_capture {
2600 let capture = mat.captures[*capture_ix as usize];
2601 if offset >= capture.node.start_byte() {
2602 let next_capture_end = capture.node.end_byte();
2603 if offset < next_capture_end {
2604 highlights.stack.push((
2605 next_capture_end,
2606 highlights.highlight_map.get(capture.index),
2607 ));
2608 }
2609 highlights.next_capture.take();
2610 }
2611 }
2612 highlights.captures.set_byte_range(self.range.clone());
2613 }
2614 }
2615
2616 pub fn offset(&self) -> usize {
2617 self.range.start
2618 }
2619
2620 fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
2621 let depth = match endpoint.severity {
2622 DiagnosticSeverity::ERROR => &mut self.error_depth,
2623 DiagnosticSeverity::WARNING => &mut self.warning_depth,
2624 DiagnosticSeverity::INFORMATION => &mut self.information_depth,
2625 DiagnosticSeverity::HINT => &mut self.hint_depth,
2626 _ => return,
2627 };
2628 if endpoint.is_start {
2629 *depth += 1;
2630 } else {
2631 *depth -= 1;
2632 }
2633 }
2634
2635 fn current_diagnostic_severity(&mut self) -> Option<DiagnosticSeverity> {
2636 if self.error_depth > 0 {
2637 Some(DiagnosticSeverity::ERROR)
2638 } else if self.warning_depth > 0 {
2639 Some(DiagnosticSeverity::WARNING)
2640 } else if self.information_depth > 0 {
2641 Some(DiagnosticSeverity::INFORMATION)
2642 } else if self.hint_depth > 0 {
2643 Some(DiagnosticSeverity::HINT)
2644 } else {
2645 None
2646 }
2647 }
2648}
2649
2650impl<'a> Iterator for BufferChunks<'a> {
2651 type Item = Chunk<'a>;
2652
2653 fn next(&mut self) -> Option<Self::Item> {
2654 let mut next_capture_start = usize::MAX;
2655 let mut next_diagnostic_endpoint = usize::MAX;
2656
2657 if let Some(highlights) = self.highlights.as_mut() {
2658 while let Some((parent_capture_end, _)) = highlights.stack.last() {
2659 if *parent_capture_end <= self.range.start {
2660 highlights.stack.pop();
2661 } else {
2662 break;
2663 }
2664 }
2665
2666 if highlights.next_capture.is_none() {
2667 highlights.next_capture = highlights.captures.next();
2668 }
2669
2670 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
2671 let capture = mat.captures[*capture_ix as usize];
2672 if self.range.start < capture.node.start_byte() {
2673 next_capture_start = capture.node.start_byte();
2674 break;
2675 } else {
2676 let highlight_id = highlights.highlight_map.get(capture.index);
2677 highlights
2678 .stack
2679 .push((capture.node.end_byte(), highlight_id));
2680 highlights.next_capture = highlights.captures.next();
2681 }
2682 }
2683 }
2684
2685 while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
2686 if endpoint.offset <= self.range.start {
2687 self.update_diagnostic_depths(endpoint);
2688 self.diagnostic_endpoints.next();
2689 } else {
2690 next_diagnostic_endpoint = endpoint.offset;
2691 break;
2692 }
2693 }
2694
2695 if let Some(chunk) = self.chunks.peek() {
2696 let chunk_start = self.range.start;
2697 let mut chunk_end = (self.chunks.offset() + chunk.len())
2698 .min(next_capture_start)
2699 .min(next_diagnostic_endpoint);
2700 let mut highlight_id = None;
2701 if let Some(highlights) = self.highlights.as_ref() {
2702 if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
2703 chunk_end = chunk_end.min(*parent_capture_end);
2704 highlight_id = Some(*parent_highlight_id);
2705 }
2706 }
2707
2708 let slice =
2709 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2710 self.range.start = chunk_end;
2711 if self.range.start == self.chunks.offset() + chunk.len() {
2712 self.chunks.next().unwrap();
2713 }
2714
2715 Some(Chunk {
2716 text: slice,
2717 highlight_id,
2718 diagnostic: self.current_diagnostic_severity(),
2719 })
2720 } else {
2721 None
2722 }
2723 }
2724}
2725
2726impl QueryCursorHandle {
2727 pub(crate) fn new() -> Self {
2728 QueryCursorHandle(Some(
2729 QUERY_CURSORS
2730 .lock()
2731 .pop()
2732 .unwrap_or_else(|| QueryCursor::new()),
2733 ))
2734 }
2735}
2736
2737impl Deref for QueryCursorHandle {
2738 type Target = QueryCursor;
2739
2740 fn deref(&self) -> &Self::Target {
2741 self.0.as_ref().unwrap()
2742 }
2743}
2744
2745impl DerefMut for QueryCursorHandle {
2746 fn deref_mut(&mut self) -> &mut Self::Target {
2747 self.0.as_mut().unwrap()
2748 }
2749}
2750
2751impl Drop for QueryCursorHandle {
2752 fn drop(&mut self) {
2753 let mut cursor = self.0.take().unwrap();
2754 cursor.set_byte_range(0..usize::MAX);
2755 cursor.set_point_range(Point::zero().to_ts_point()..Point::MAX.to_ts_point());
2756 QUERY_CURSORS.lock().push(cursor)
2757 }
2758}
2759
2760trait ToTreeSitterPoint {
2761 fn to_ts_point(self) -> tree_sitter::Point;
2762 fn from_ts_point(point: tree_sitter::Point) -> Self;
2763}
2764
2765impl ToTreeSitterPoint for Point {
2766 fn to_ts_point(self) -> tree_sitter::Point {
2767 tree_sitter::Point::new(self.row as usize, self.column as usize)
2768 }
2769
2770 fn from_ts_point(point: tree_sitter::Point) -> Self {
2771 Point::new(point.row as u32, point.column as u32)
2772 }
2773}
2774
2775impl operation_queue::Operation for Operation {
2776 fn lamport_timestamp(&self) -> clock::Lamport {
2777 match self {
2778 Operation::Buffer(_) => {
2779 unreachable!("buffer operations should never be deferred at this layer")
2780 }
2781 Operation::UpdateDiagnostics {
2782 lamport_timestamp, ..
2783 }
2784 | Operation::UpdateSelections {
2785 lamport_timestamp, ..
2786 }
2787 | Operation::UpdateCompletionTriggers {
2788 lamport_timestamp, ..
2789 } => *lamport_timestamp,
2790 }
2791 }
2792}
2793
2794impl LanguageServerState {
2795 fn snapshot_for_version(&mut self, version: usize) -> Result<&text::BufferSnapshot> {
2796 const OLD_VERSIONS_TO_RETAIN: usize = 10;
2797
2798 self.pending_snapshots
2799 .retain(|&v, _| v + OLD_VERSIONS_TO_RETAIN >= version);
2800 let snapshot = self
2801 .pending_snapshots
2802 .get(&version)
2803 .ok_or_else(|| anyhow!("missing snapshot"))?;
2804 Ok(&snapshot.buffer_snapshot)
2805 }
2806}
2807
2808impl Default for Diagnostic {
2809 fn default() -> Self {
2810 Self {
2811 code: Default::default(),
2812 severity: DiagnosticSeverity::ERROR,
2813 message: Default::default(),
2814 group_id: Default::default(),
2815 is_primary: Default::default(),
2816 is_valid: true,
2817 is_disk_based: false,
2818 }
2819 }
2820}
2821
2822impl<T> Completion<T> {
2823 pub fn sort_key(&self) -> (usize, &str) {
2824 let kind_key = match self.lsp_completion.kind {
2825 Some(lsp::CompletionItemKind::VARIABLE) => 0,
2826 _ => 1,
2827 };
2828 (kind_key, &self.label.text[self.label.filter_range.clone()])
2829 }
2830
2831 pub fn is_snippet(&self) -> bool {
2832 self.lsp_completion.insert_text_format == Some(lsp::InsertTextFormat::SNIPPET)
2833 }
2834}
2835
2836pub fn contiguous_ranges(
2837 values: impl Iterator<Item = u32>,
2838 max_len: usize,
2839) -> impl Iterator<Item = Range<u32>> {
2840 let mut values = values.into_iter();
2841 let mut current_range: Option<Range<u32>> = None;
2842 std::iter::from_fn(move || loop {
2843 if let Some(value) = values.next() {
2844 if let Some(range) = &mut current_range {
2845 if value == range.end && range.len() < max_len {
2846 range.end += 1;
2847 continue;
2848 }
2849 }
2850
2851 let prev_range = current_range.clone();
2852 current_range = Some(value..(value + 1));
2853 if prev_range.is_some() {
2854 return prev_range;
2855 }
2856 } else {
2857 return current_range.take();
2858 }
2859 })
2860}