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