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