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