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