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