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