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