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