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