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