1use crate::{
2 DebuggerTextObject, LanguageScope, Outline, OutlineConfig, RunnableCapture, RunnableTag,
3 TextObject, TreeSitterOptions,
4 diagnostic_set::{DiagnosticEntry, DiagnosticGroup},
5 language_settings::{LanguageSettings, language_settings},
6 outline::OutlineItem,
7 syntax_map::{
8 SyntaxLayer, SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures, SyntaxMapMatch,
9 SyntaxMapMatches, SyntaxSnapshot, ToTreeSitterPoint,
10 },
11 task_context::RunnableRange,
12 text_diff::text_diff,
13};
14pub use crate::{
15 Grammar, Language, LanguageRegistry,
16 diagnostic_set::DiagnosticSet,
17 highlight_map::{HighlightId, HighlightMap},
18 proto,
19};
20use anyhow::{Context as _, Result};
21pub use clock::ReplicaId;
22use clock::{AGENT_REPLICA_ID, Lamport};
23use collections::HashMap;
24use fs::MTime;
25use futures::channel::oneshot;
26use gpui::{
27 App, AppContext as _, Context, Entity, EventEmitter, HighlightStyle, SharedString, StyledText,
28 Task, TaskLabel, TextStyle,
29};
30
31use lsp::{LanguageServerId, NumberOrString};
32use parking_lot::Mutex;
33use serde::{Deserialize, Serialize};
34use serde_json::Value;
35use settings::WorktreeId;
36use smallvec::SmallVec;
37use smol::future::yield_now;
38use std::{
39 any::Any,
40 borrow::Cow,
41 cell::Cell,
42 cmp::{self, Ordering, Reverse},
43 collections::{BTreeMap, BTreeSet},
44 ffi::OsStr,
45 future::Future,
46 iter::{self, Iterator, Peekable},
47 mem,
48 num::NonZeroU32,
49 ops::{Deref, Range},
50 path::{Path, PathBuf},
51 rc,
52 sync::{Arc, LazyLock},
53 time::{Duration, Instant},
54 vec,
55};
56use sum_tree::TreeMap;
57use text::operation_queue::OperationQueue;
58use text::*;
59pub use text::{
60 Anchor, Bias, Buffer as TextBuffer, BufferId, BufferSnapshot as TextBufferSnapshot, Edit,
61 LineIndent, OffsetRangeExt, OffsetUtf16, Patch, Point, PointUtf16, Rope, Selection,
62 SelectionGoal, Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint,
63 ToPointUtf16, Transaction, TransactionId, Unclipped,
64};
65use theme::{ActiveTheme as _, SyntaxTheme};
66#[cfg(any(test, feature = "test-support"))]
67use util::RandomCharIter;
68use util::{RangeExt, debug_panic, maybe};
69
70#[cfg(any(test, feature = "test-support"))]
71pub use {tree_sitter_python, tree_sitter_rust, tree_sitter_typescript};
72
73pub use lsp::DiagnosticSeverity;
74
75/// A label for the background task spawned by the buffer to compute
76/// a diff against the contents of its file.
77pub static BUFFER_DIFF_TASK: LazyLock<TaskLabel> = LazyLock::new(TaskLabel::new);
78
79/// Indicate whether a [`Buffer`] has permissions to edit.
80#[derive(PartialEq, Clone, Copy, Debug)]
81pub enum Capability {
82 /// The buffer is a mutable replica.
83 ReadWrite,
84 /// The buffer is a read-only replica.
85 ReadOnly,
86}
87
88pub type BufferRow = u32;
89
90/// An in-memory representation of a source code file, including its text,
91/// syntax trees, git status, and diagnostics.
92pub struct Buffer {
93 text: TextBuffer,
94 branch_state: Option<BufferBranchState>,
95 /// Filesystem state, `None` when there is no path.
96 file: Option<Arc<dyn File>>,
97 /// The mtime of the file when this buffer was last loaded from
98 /// or saved to disk.
99 saved_mtime: Option<MTime>,
100 /// The version vector when this buffer was last loaded from
101 /// or saved to disk.
102 saved_version: clock::Global,
103 preview_version: clock::Global,
104 transaction_depth: usize,
105 was_dirty_before_starting_transaction: Option<bool>,
106 reload_task: Option<Task<Result<()>>>,
107 language: Option<Arc<Language>>,
108 autoindent_requests: Vec<Arc<AutoindentRequest>>,
109 wait_for_autoindent_txs: Vec<oneshot::Sender<()>>,
110 pending_autoindent: Option<Task<()>>,
111 sync_parse_timeout: Duration,
112 syntax_map: Mutex<SyntaxMap>,
113 reparse: Option<Task<()>>,
114 parse_status: (watch::Sender<ParseStatus>, watch::Receiver<ParseStatus>),
115 non_text_state_update_count: usize,
116 diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
117 remote_selections: TreeMap<ReplicaId, SelectionSet>,
118 diagnostics_timestamp: clock::Lamport,
119 completion_triggers: BTreeSet<String>,
120 completion_triggers_per_language_server: HashMap<LanguageServerId, BTreeSet<String>>,
121 completion_triggers_timestamp: clock::Lamport,
122 deferred_ops: OperationQueue<Operation>,
123 capability: Capability,
124 has_conflict: bool,
125 /// Memoize calls to has_changes_since(saved_version).
126 /// The contents of a cell are (self.version, has_changes) at the time of a last call.
127 has_unsaved_edits: Cell<(clock::Global, bool)>,
128 change_bits: Vec<rc::Weak<Cell<bool>>>,
129 _subscriptions: Vec<gpui::Subscription>,
130}
131
132#[derive(Copy, Clone, Debug, PartialEq, Eq)]
133pub enum ParseStatus {
134 Idle,
135 Parsing,
136}
137
138struct BufferBranchState {
139 base_buffer: Entity<Buffer>,
140 merged_operations: Vec<Lamport>,
141}
142
143/// An immutable, cheaply cloneable representation of a fixed
144/// state of a buffer.
145pub struct BufferSnapshot {
146 pub text: text::BufferSnapshot,
147 pub(crate) syntax: SyntaxSnapshot,
148 file: Option<Arc<dyn File>>,
149 diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
150 remote_selections: TreeMap<ReplicaId, SelectionSet>,
151 language: Option<Arc<Language>>,
152 non_text_state_update_count: usize,
153}
154
155/// The kind and amount of indentation in a particular line. For now,
156/// assumes that indentation is all the same character.
157#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
158pub struct IndentSize {
159 /// The number of bytes that comprise the indentation.
160 pub len: u32,
161 /// The kind of whitespace used for indentation.
162 pub kind: IndentKind,
163}
164
165/// A whitespace character that's used for indentation.
166#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
167pub enum IndentKind {
168 /// An ASCII space character.
169 #[default]
170 Space,
171 /// An ASCII tab character.
172 Tab,
173}
174
175/// The shape of a selection cursor.
176#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
177pub enum CursorShape {
178 /// A vertical bar
179 #[default]
180 Bar,
181 /// A block that surrounds the following character
182 Block,
183 /// An underline that runs along the following character
184 Underline,
185 /// A box drawn around the following character
186 Hollow,
187}
188
189impl From<settings::CursorShape> for CursorShape {
190 fn from(shape: settings::CursorShape) -> Self {
191 match shape {
192 settings::CursorShape::Bar => CursorShape::Bar,
193 settings::CursorShape::Block => CursorShape::Block,
194 settings::CursorShape::Underline => CursorShape::Underline,
195 settings::CursorShape::Hollow => CursorShape::Hollow,
196 }
197 }
198}
199
200#[derive(Clone, Debug)]
201struct SelectionSet {
202 line_mode: bool,
203 cursor_shape: CursorShape,
204 selections: Arc<[Selection<Anchor>]>,
205 lamport_timestamp: clock::Lamport,
206}
207
208/// A diagnostic associated with a certain range of a buffer.
209#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
210pub struct Diagnostic {
211 /// The name of the service that produced this diagnostic.
212 pub source: Option<String>,
213 /// A machine-readable code that identifies this diagnostic.
214 pub code: Option<NumberOrString>,
215 pub code_description: Option<lsp::Uri>,
216 /// Whether this diagnostic is a hint, warning, or error.
217 pub severity: DiagnosticSeverity,
218 /// The human-readable message associated with this diagnostic.
219 pub message: String,
220 /// The human-readable message (in markdown format)
221 pub markdown: Option<String>,
222 /// An id that identifies the group to which this diagnostic belongs.
223 ///
224 /// When a language server produces a diagnostic with
225 /// one or more associated diagnostics, those diagnostics are all
226 /// assigned a single group ID.
227 pub group_id: usize,
228 /// Whether this diagnostic is the primary diagnostic for its group.
229 ///
230 /// In a given group, the primary diagnostic is the top-level diagnostic
231 /// returned by the language server. The non-primary diagnostics are the
232 /// associated diagnostics.
233 pub is_primary: bool,
234 /// Whether this diagnostic is considered to originate from an analysis of
235 /// files on disk, as opposed to any unsaved buffer contents. This is a
236 /// property of a given diagnostic source, and is configured for a given
237 /// language server via the [`LspAdapter::disk_based_diagnostic_sources`](crate::LspAdapter::disk_based_diagnostic_sources) method
238 /// for the language server.
239 pub is_disk_based: bool,
240 /// Whether this diagnostic marks unnecessary code.
241 pub is_unnecessary: bool,
242 /// Quick separation of diagnostics groups based by their source.
243 pub source_kind: DiagnosticSourceKind,
244 /// Data from language server that produced this diagnostic. Passed back to the LS when we request code actions for this diagnostic.
245 pub data: Option<Value>,
246 /// Whether to underline the corresponding text range in the editor.
247 pub underline: bool,
248}
249
250#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
251pub enum DiagnosticSourceKind {
252 Pulled,
253 Pushed,
254 Other,
255}
256
257/// An operation used to synchronize this buffer with its other replicas.
258#[derive(Clone, Debug, PartialEq)]
259pub enum Operation {
260 /// A text operation.
261 Buffer(text::Operation),
262
263 /// An update to the buffer's diagnostics.
264 UpdateDiagnostics {
265 /// The id of the language server that produced the new diagnostics.
266 server_id: LanguageServerId,
267 /// The diagnostics.
268 diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
269 /// The buffer's lamport timestamp.
270 lamport_timestamp: clock::Lamport,
271 },
272
273 /// An update to the most recent selections in this buffer.
274 UpdateSelections {
275 /// The selections.
276 selections: Arc<[Selection<Anchor>]>,
277 /// The buffer's lamport timestamp.
278 lamport_timestamp: clock::Lamport,
279 /// Whether the selections are in 'line mode'.
280 line_mode: bool,
281 /// The [`CursorShape`] associated with these selections.
282 cursor_shape: CursorShape,
283 },
284
285 /// An update to the characters that should trigger autocompletion
286 /// for this buffer.
287 UpdateCompletionTriggers {
288 /// The characters that trigger autocompletion.
289 triggers: Vec<String>,
290 /// The buffer's lamport timestamp.
291 lamport_timestamp: clock::Lamport,
292 /// The language server ID.
293 server_id: LanguageServerId,
294 },
295
296 /// An update to the line ending type of this buffer.
297 UpdateLineEnding {
298 /// The line ending type.
299 line_ending: LineEnding,
300 /// The buffer's lamport timestamp.
301 lamport_timestamp: clock::Lamport,
302 },
303}
304
305/// An event that occurs in a buffer.
306#[derive(Clone, Debug, PartialEq)]
307pub enum BufferEvent {
308 /// The buffer was changed in a way that must be
309 /// propagated to its other replicas.
310 Operation {
311 operation: Operation,
312 is_local: bool,
313 },
314 /// The buffer was edited.
315 Edited,
316 /// The buffer's `dirty` bit changed.
317 DirtyChanged,
318 /// The buffer was saved.
319 Saved,
320 /// The buffer's file was changed on disk.
321 FileHandleChanged,
322 /// The buffer was reloaded.
323 Reloaded,
324 /// The buffer is in need of a reload
325 ReloadNeeded,
326 /// The buffer's language was changed.
327 LanguageChanged,
328 /// The buffer's syntax trees were updated.
329 Reparsed,
330 /// The buffer's diagnostics were updated.
331 DiagnosticsUpdated,
332 /// The buffer gained or lost editing capabilities.
333 CapabilityChanged,
334}
335
336/// The file associated with a buffer.
337pub trait File: Send + Sync + Any {
338 /// Returns the [`LocalFile`] associated with this file, if the
339 /// file is local.
340 fn as_local(&self) -> Option<&dyn LocalFile>;
341
342 /// Returns whether this file is local.
343 fn is_local(&self) -> bool {
344 self.as_local().is_some()
345 }
346
347 /// Returns whether the file is new, exists in storage, or has been deleted. Includes metadata
348 /// only available in some states, such as modification time.
349 fn disk_state(&self) -> DiskState;
350
351 /// Returns the path of this file relative to the worktree's root directory.
352 fn path(&self) -> &Arc<Path>;
353
354 /// Returns the path of this file relative to the worktree's parent directory (this means it
355 /// includes the name of the worktree's root folder).
356 fn full_path(&self, cx: &App) -> PathBuf;
357
358 /// Returns the last component of this handle's absolute path. If this handle refers to the root
359 /// of its worktree, then this method will return the name of the worktree itself.
360 fn file_name<'a>(&'a self, cx: &'a App) -> &'a OsStr;
361
362 /// Returns the id of the worktree to which this file belongs.
363 ///
364 /// This is needed for looking up project-specific settings.
365 fn worktree_id(&self, cx: &App) -> WorktreeId;
366
367 /// Converts this file into a protobuf message.
368 fn to_proto(&self, cx: &App) -> rpc::proto::File;
369
370 /// Return whether Zed considers this to be a private file.
371 fn is_private(&self) -> bool;
372}
373
374/// The file's storage status - whether it's stored (`Present`), and if so when it was last
375/// modified. In the case where the file is not stored, it can be either `New` or `Deleted`. In the
376/// UI these two states are distinguished. For example, the buffer tab does not display a deletion
377/// indicator for new files.
378#[derive(Copy, Clone, Debug, PartialEq)]
379pub enum DiskState {
380 /// File created in Zed that has not been saved.
381 New,
382 /// File present on the filesystem.
383 Present { mtime: MTime },
384 /// Deleted file that was previously present.
385 Deleted,
386}
387
388impl DiskState {
389 /// Returns the file's last known modification time on disk.
390 pub fn mtime(self) -> Option<MTime> {
391 match self {
392 DiskState::New => None,
393 DiskState::Present { mtime } => Some(mtime),
394 DiskState::Deleted => None,
395 }
396 }
397
398 pub fn exists(&self) -> bool {
399 match self {
400 DiskState::New => false,
401 DiskState::Present { .. } => true,
402 DiskState::Deleted => false,
403 }
404 }
405}
406
407/// The file associated with a buffer, in the case where the file is on the local disk.
408pub trait LocalFile: File {
409 /// Returns the absolute path of this file
410 fn abs_path(&self, cx: &App) -> PathBuf;
411
412 /// Loads the file contents from disk and returns them as a UTF-8 encoded string.
413 fn load(&self, cx: &App) -> Task<Result<String>>;
414
415 /// Loads the file's contents from disk.
416 fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>>;
417}
418
419/// The auto-indent behavior associated with an editing operation.
420/// For some editing operations, each affected line of text has its
421/// indentation recomputed. For other operations, the entire block
422/// of edited text is adjusted uniformly.
423#[derive(Clone, Debug)]
424pub enum AutoindentMode {
425 /// Indent each line of inserted text.
426 EachLine,
427 /// Apply the same indentation adjustment to all of the lines
428 /// in a given insertion.
429 Block {
430 /// The original indentation column of the first line of each
431 /// insertion, if it has been copied.
432 ///
433 /// Knowing this makes it possible to preserve the relative indentation
434 /// of every line in the insertion from when it was copied.
435 ///
436 /// If the original indent column is `a`, and the first line of insertion
437 /// is then auto-indented to column `b`, then every other line of
438 /// the insertion will be auto-indented to column `b - a`
439 original_indent_columns: Vec<Option<u32>>,
440 },
441}
442
443#[derive(Clone)]
444struct AutoindentRequest {
445 before_edit: BufferSnapshot,
446 entries: Vec<AutoindentRequestEntry>,
447 is_block_mode: bool,
448 ignore_empty_lines: bool,
449}
450
451#[derive(Debug, Clone)]
452struct AutoindentRequestEntry {
453 /// A range of the buffer whose indentation should be adjusted.
454 range: Range<Anchor>,
455 /// Whether or not these lines should be considered brand new, for the
456 /// purpose of auto-indent. When text is not new, its indentation will
457 /// only be adjusted if the suggested indentation level has *changed*
458 /// since the edit was made.
459 first_line_is_new: bool,
460 indent_size: IndentSize,
461 original_indent_column: Option<u32>,
462}
463
464#[derive(Debug)]
465struct IndentSuggestion {
466 basis_row: u32,
467 delta: Ordering,
468 within_error: bool,
469}
470
471struct BufferChunkHighlights<'a> {
472 captures: SyntaxMapCaptures<'a>,
473 next_capture: Option<SyntaxMapCapture<'a>>,
474 stack: Vec<(usize, HighlightId)>,
475 highlight_maps: Vec<HighlightMap>,
476}
477
478/// An iterator that yields chunks of a buffer's text, along with their
479/// syntax highlights and diagnostic status.
480pub struct BufferChunks<'a> {
481 buffer_snapshot: Option<&'a BufferSnapshot>,
482 range: Range<usize>,
483 chunks: text::Chunks<'a>,
484 diagnostic_endpoints: Option<Peekable<vec::IntoIter<DiagnosticEndpoint>>>,
485 error_depth: usize,
486 warning_depth: usize,
487 information_depth: usize,
488 hint_depth: usize,
489 unnecessary_depth: usize,
490 underline: bool,
491 highlights: Option<BufferChunkHighlights<'a>>,
492}
493
494/// A chunk of a buffer's text, along with its syntax highlight and
495/// diagnostic status.
496#[derive(Clone, Debug, Default)]
497pub struct Chunk<'a> {
498 /// The text of the chunk.
499 pub text: &'a str,
500 /// The syntax highlighting style of the chunk.
501 pub syntax_highlight_id: Option<HighlightId>,
502 /// The highlight style that has been applied to this chunk in
503 /// the editor.
504 pub highlight_style: Option<HighlightStyle>,
505 /// The severity of diagnostic associated with this chunk, if any.
506 pub diagnostic_severity: Option<DiagnosticSeverity>,
507 /// Whether this chunk of text is marked as unnecessary.
508 pub is_unnecessary: bool,
509 /// Whether this chunk of text was originally a tab character.
510 pub is_tab: bool,
511 /// A bitset of which characters are tabs in this string.
512 pub tabs: u128,
513 /// Bitmap of character indices in this chunk
514 pub chars: u128,
515 /// Whether this chunk of text was originally a tab character.
516 pub is_inlay: bool,
517 /// Whether to underline the corresponding text range in the editor.
518 pub underline: bool,
519}
520
521/// A set of edits to a given version of a buffer, computed asynchronously.
522#[derive(Debug)]
523pub struct Diff {
524 pub base_version: clock::Global,
525 pub line_ending: LineEnding,
526 pub edits: Vec<(Range<usize>, Arc<str>)>,
527}
528
529#[derive(Debug, Clone, Copy)]
530pub(crate) struct DiagnosticEndpoint {
531 offset: usize,
532 is_start: bool,
533 underline: bool,
534 severity: DiagnosticSeverity,
535 is_unnecessary: bool,
536}
537
538/// A class of characters, used for characterizing a run of text.
539#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
540pub enum CharKind {
541 /// Whitespace.
542 Whitespace,
543 /// Punctuation.
544 Punctuation,
545 /// Word.
546 Word,
547}
548
549/// A runnable is a set of data about a region that could be resolved into a task
550pub struct Runnable {
551 pub tags: SmallVec<[RunnableTag; 1]>,
552 pub language: Arc<Language>,
553 pub buffer: BufferId,
554}
555
556#[derive(Default, Clone, Debug)]
557pub struct HighlightedText {
558 pub text: SharedString,
559 pub highlights: Vec<(Range<usize>, HighlightStyle)>,
560}
561
562#[derive(Default, Debug)]
563struct HighlightedTextBuilder {
564 pub text: String,
565 pub highlights: Vec<(Range<usize>, HighlightStyle)>,
566}
567
568impl HighlightedText {
569 pub fn from_buffer_range<T: ToOffset>(
570 range: Range<T>,
571 snapshot: &text::BufferSnapshot,
572 syntax_snapshot: &SyntaxSnapshot,
573 override_style: Option<HighlightStyle>,
574 syntax_theme: &SyntaxTheme,
575 ) -> Self {
576 let mut highlighted_text = HighlightedTextBuilder::default();
577 highlighted_text.add_text_from_buffer_range(
578 range,
579 snapshot,
580 syntax_snapshot,
581 override_style,
582 syntax_theme,
583 );
584 highlighted_text.build()
585 }
586
587 pub fn to_styled_text(&self, default_style: &TextStyle) -> StyledText {
588 gpui::StyledText::new(self.text.clone())
589 .with_default_highlights(default_style, self.highlights.iter().cloned())
590 }
591
592 /// Returns the first line without leading whitespace unless highlighted
593 /// and a boolean indicating if there are more lines after
594 pub fn first_line_preview(self) -> (Self, bool) {
595 let newline_ix = self.text.find('\n').unwrap_or(self.text.len());
596 let first_line = &self.text[..newline_ix];
597
598 // Trim leading whitespace, unless an edit starts prior to it.
599 let mut preview_start_ix = first_line.len() - first_line.trim_start().len();
600 if let Some((first_highlight_range, _)) = self.highlights.first() {
601 preview_start_ix = preview_start_ix.min(first_highlight_range.start);
602 }
603
604 let preview_text = &first_line[preview_start_ix..];
605 let preview_highlights = self
606 .highlights
607 .into_iter()
608 .take_while(|(range, _)| range.start < newline_ix)
609 .filter_map(|(mut range, highlight)| {
610 range.start = range.start.saturating_sub(preview_start_ix);
611 range.end = range.end.saturating_sub(preview_start_ix).min(newline_ix);
612 if range.is_empty() {
613 None
614 } else {
615 Some((range, highlight))
616 }
617 });
618
619 let preview = Self {
620 text: SharedString::new(preview_text),
621 highlights: preview_highlights.collect(),
622 };
623
624 (preview, self.text.len() > newline_ix)
625 }
626}
627
628impl HighlightedTextBuilder {
629 pub fn build(self) -> HighlightedText {
630 HighlightedText {
631 text: self.text.into(),
632 highlights: self.highlights,
633 }
634 }
635
636 pub fn add_text_from_buffer_range<T: ToOffset>(
637 &mut self,
638 range: Range<T>,
639 snapshot: &text::BufferSnapshot,
640 syntax_snapshot: &SyntaxSnapshot,
641 override_style: Option<HighlightStyle>,
642 syntax_theme: &SyntaxTheme,
643 ) {
644 let range = range.to_offset(snapshot);
645 for chunk in Self::highlighted_chunks(range, snapshot, syntax_snapshot) {
646 let start = self.text.len();
647 self.text.push_str(chunk.text);
648 let end = self.text.len();
649
650 if let Some(highlight_style) = chunk
651 .syntax_highlight_id
652 .and_then(|id| id.style(syntax_theme))
653 {
654 let highlight_style = override_style.map_or(highlight_style, |override_style| {
655 highlight_style.highlight(override_style)
656 });
657 self.highlights.push((start..end, highlight_style));
658 } else if let Some(override_style) = override_style {
659 self.highlights.push((start..end, override_style));
660 }
661 }
662 }
663
664 fn highlighted_chunks<'a>(
665 range: Range<usize>,
666 snapshot: &'a text::BufferSnapshot,
667 syntax_snapshot: &'a SyntaxSnapshot,
668 ) -> BufferChunks<'a> {
669 let captures = syntax_snapshot.captures(range.clone(), snapshot, |grammar| {
670 grammar.highlights_query.as_ref()
671 });
672
673 let highlight_maps = captures
674 .grammars()
675 .iter()
676 .map(|grammar| grammar.highlight_map())
677 .collect();
678
679 BufferChunks::new(
680 snapshot.as_rope(),
681 range,
682 Some((captures, highlight_maps)),
683 false,
684 None,
685 )
686 }
687}
688
689#[derive(Clone)]
690pub struct EditPreview {
691 old_snapshot: text::BufferSnapshot,
692 applied_edits_snapshot: text::BufferSnapshot,
693 syntax_snapshot: SyntaxSnapshot,
694}
695
696impl EditPreview {
697 pub fn highlight_edits(
698 &self,
699 current_snapshot: &BufferSnapshot,
700 edits: &[(Range<Anchor>, String)],
701 include_deletions: bool,
702 cx: &App,
703 ) -> HighlightedText {
704 let Some(visible_range_in_preview_snapshot) = self.compute_visible_range(edits) else {
705 return HighlightedText::default();
706 };
707
708 let mut highlighted_text = HighlightedTextBuilder::default();
709
710 let mut offset_in_preview_snapshot = visible_range_in_preview_snapshot.start;
711
712 let insertion_highlight_style = HighlightStyle {
713 background_color: Some(cx.theme().status().created_background),
714 ..Default::default()
715 };
716 let deletion_highlight_style = HighlightStyle {
717 background_color: Some(cx.theme().status().deleted_background),
718 ..Default::default()
719 };
720 let syntax_theme = cx.theme().syntax();
721
722 for (range, edit_text) in edits {
723 let edit_new_end_in_preview_snapshot = range
724 .end
725 .bias_right(&self.old_snapshot)
726 .to_offset(&self.applied_edits_snapshot);
727 let edit_start_in_preview_snapshot = edit_new_end_in_preview_snapshot - edit_text.len();
728
729 let unchanged_range_in_preview_snapshot =
730 offset_in_preview_snapshot..edit_start_in_preview_snapshot;
731 if !unchanged_range_in_preview_snapshot.is_empty() {
732 highlighted_text.add_text_from_buffer_range(
733 unchanged_range_in_preview_snapshot,
734 &self.applied_edits_snapshot,
735 &self.syntax_snapshot,
736 None,
737 syntax_theme,
738 );
739 }
740
741 let range_in_current_snapshot = range.to_offset(current_snapshot);
742 if include_deletions && !range_in_current_snapshot.is_empty() {
743 highlighted_text.add_text_from_buffer_range(
744 range_in_current_snapshot,
745 ¤t_snapshot.text,
746 ¤t_snapshot.syntax,
747 Some(deletion_highlight_style),
748 syntax_theme,
749 );
750 }
751
752 if !edit_text.is_empty() {
753 highlighted_text.add_text_from_buffer_range(
754 edit_start_in_preview_snapshot..edit_new_end_in_preview_snapshot,
755 &self.applied_edits_snapshot,
756 &self.syntax_snapshot,
757 Some(insertion_highlight_style),
758 syntax_theme,
759 );
760 }
761
762 offset_in_preview_snapshot = edit_new_end_in_preview_snapshot;
763 }
764
765 highlighted_text.add_text_from_buffer_range(
766 offset_in_preview_snapshot..visible_range_in_preview_snapshot.end,
767 &self.applied_edits_snapshot,
768 &self.syntax_snapshot,
769 None,
770 syntax_theme,
771 );
772
773 highlighted_text.build()
774 }
775
776 fn compute_visible_range(&self, edits: &[(Range<Anchor>, String)]) -> Option<Range<usize>> {
777 let (first, _) = edits.first()?;
778 let (last, _) = edits.last()?;
779
780 let start = first
781 .start
782 .bias_left(&self.old_snapshot)
783 .to_point(&self.applied_edits_snapshot);
784 let end = last
785 .end
786 .bias_right(&self.old_snapshot)
787 .to_point(&self.applied_edits_snapshot);
788
789 // Ensure that the first line of the first edit and the last line of the last edit are always fully visible
790 let range = Point::new(start.row, 0)
791 ..Point::new(end.row, self.applied_edits_snapshot.line_len(end.row));
792
793 Some(range.to_offset(&self.applied_edits_snapshot))
794 }
795}
796
797#[derive(Clone, Debug, PartialEq, Eq)]
798pub struct BracketMatch {
799 pub open_range: Range<usize>,
800 pub close_range: Range<usize>,
801 pub newline_only: bool,
802}
803
804impl Buffer {
805 /// Create a new buffer with the given base text.
806 pub fn local<T: Into<String>>(base_text: T, cx: &Context<Self>) -> Self {
807 Self::build(
808 TextBuffer::new(0, cx.entity_id().as_non_zero_u64().into(), base_text.into()),
809 None,
810 Capability::ReadWrite,
811 )
812 }
813
814 /// Create a new buffer with the given base text that has proper line endings and other normalization applied.
815 pub fn local_normalized(
816 base_text_normalized: Rope,
817 line_ending: LineEnding,
818 cx: &Context<Self>,
819 ) -> Self {
820 Self::build(
821 TextBuffer::new_normalized(
822 0,
823 cx.entity_id().as_non_zero_u64().into(),
824 line_ending,
825 base_text_normalized,
826 ),
827 None,
828 Capability::ReadWrite,
829 )
830 }
831
832 /// Create a new buffer that is a replica of a remote buffer.
833 pub fn remote(
834 remote_id: BufferId,
835 replica_id: ReplicaId,
836 capability: Capability,
837 base_text: impl Into<String>,
838 ) -> Self {
839 Self::build(
840 TextBuffer::new(replica_id, remote_id, base_text.into()),
841 None,
842 capability,
843 )
844 }
845
846 /// Create a new buffer that is a replica of a remote buffer, populating its
847 /// state from the given protobuf message.
848 pub fn from_proto(
849 replica_id: ReplicaId,
850 capability: Capability,
851 message: proto::BufferState,
852 file: Option<Arc<dyn File>>,
853 ) -> Result<Self> {
854 let buffer_id = BufferId::new(message.id).context("Could not deserialize buffer_id")?;
855 let buffer = TextBuffer::new(replica_id, buffer_id, message.base_text);
856 let mut this = Self::build(buffer, file, capability);
857 this.text.set_line_ending(proto::deserialize_line_ending(
858 rpc::proto::LineEnding::from_i32(message.line_ending).context("missing line_ending")?,
859 ));
860 this.saved_version = proto::deserialize_version(&message.saved_version);
861 this.saved_mtime = message.saved_mtime.map(|time| time.into());
862 Ok(this)
863 }
864
865 /// Serialize the buffer's state to a protobuf message.
866 pub fn to_proto(&self, cx: &App) -> proto::BufferState {
867 proto::BufferState {
868 id: self.remote_id().into(),
869 file: self.file.as_ref().map(|f| f.to_proto(cx)),
870 base_text: self.base_text().to_string(),
871 line_ending: proto::serialize_line_ending(self.line_ending()) as i32,
872 saved_version: proto::serialize_version(&self.saved_version),
873 saved_mtime: self.saved_mtime.map(|time| time.into()),
874 }
875 }
876
877 /// Serialize as protobufs all of the changes to the buffer since the given version.
878 pub fn serialize_ops(
879 &self,
880 since: Option<clock::Global>,
881 cx: &App,
882 ) -> Task<Vec<proto::Operation>> {
883 let mut operations = Vec::new();
884 operations.extend(self.deferred_ops.iter().map(proto::serialize_operation));
885
886 operations.extend(self.remote_selections.iter().map(|(_, set)| {
887 proto::serialize_operation(&Operation::UpdateSelections {
888 selections: set.selections.clone(),
889 lamport_timestamp: set.lamport_timestamp,
890 line_mode: set.line_mode,
891 cursor_shape: set.cursor_shape,
892 })
893 }));
894
895 for (server_id, diagnostics) in &self.diagnostics {
896 operations.push(proto::serialize_operation(&Operation::UpdateDiagnostics {
897 lamport_timestamp: self.diagnostics_timestamp,
898 server_id: *server_id,
899 diagnostics: diagnostics.iter().cloned().collect(),
900 }));
901 }
902
903 for (server_id, completions) in &self.completion_triggers_per_language_server {
904 operations.push(proto::serialize_operation(
905 &Operation::UpdateCompletionTriggers {
906 triggers: completions.iter().cloned().collect(),
907 lamport_timestamp: self.completion_triggers_timestamp,
908 server_id: *server_id,
909 },
910 ));
911 }
912
913 let text_operations = self.text.operations().clone();
914 cx.background_spawn(async move {
915 let since = since.unwrap_or_default();
916 operations.extend(
917 text_operations
918 .iter()
919 .filter(|(_, op)| !since.observed(op.timestamp()))
920 .map(|(_, op)| proto::serialize_operation(&Operation::Buffer(op.clone()))),
921 );
922 operations.sort_unstable_by_key(proto::lamport_timestamp_for_operation);
923 operations
924 })
925 }
926
927 /// Assign a language to the buffer, returning the buffer.
928 pub fn with_language(mut self, language: Arc<Language>, cx: &mut Context<Self>) -> Self {
929 self.set_language(Some(language), cx);
930 self
931 }
932
933 /// Returns the [`Capability`] of this buffer.
934 pub fn capability(&self) -> Capability {
935 self.capability
936 }
937
938 /// Whether this buffer can only be read.
939 pub fn read_only(&self) -> bool {
940 self.capability == Capability::ReadOnly
941 }
942
943 /// Builds a [`Buffer`] with the given underlying [`TextBuffer`], diff base, [`File`] and [`Capability`].
944 pub fn build(buffer: TextBuffer, file: Option<Arc<dyn File>>, capability: Capability) -> Self {
945 let saved_mtime = file.as_ref().and_then(|file| file.disk_state().mtime());
946 let snapshot = buffer.snapshot();
947 let syntax_map = Mutex::new(SyntaxMap::new(&snapshot));
948 Self {
949 saved_mtime,
950 saved_version: buffer.version(),
951 preview_version: buffer.version(),
952 reload_task: None,
953 transaction_depth: 0,
954 was_dirty_before_starting_transaction: None,
955 has_unsaved_edits: Cell::new((buffer.version(), false)),
956 text: buffer,
957 branch_state: None,
958 file,
959 capability,
960 syntax_map,
961 reparse: None,
962 non_text_state_update_count: 0,
963 sync_parse_timeout: Duration::from_millis(1),
964 parse_status: watch::channel(ParseStatus::Idle),
965 autoindent_requests: Default::default(),
966 wait_for_autoindent_txs: Default::default(),
967 pending_autoindent: Default::default(),
968 language: None,
969 remote_selections: Default::default(),
970 diagnostics: Default::default(),
971 diagnostics_timestamp: Default::default(),
972 completion_triggers: Default::default(),
973 completion_triggers_per_language_server: Default::default(),
974 completion_triggers_timestamp: Default::default(),
975 deferred_ops: OperationQueue::new(),
976 has_conflict: false,
977 change_bits: Default::default(),
978 _subscriptions: Vec::new(),
979 }
980 }
981
982 pub fn build_snapshot(
983 text: Rope,
984 language: Option<Arc<Language>>,
985 language_registry: Option<Arc<LanguageRegistry>>,
986 cx: &mut App,
987 ) -> impl Future<Output = BufferSnapshot> + use<> {
988 let entity_id = cx.reserve_entity::<Self>().entity_id();
989 let buffer_id = entity_id.as_non_zero_u64().into();
990 async move {
991 let text =
992 TextBuffer::new_normalized(0, buffer_id, Default::default(), text).snapshot();
993 let mut syntax = SyntaxMap::new(&text).snapshot();
994 if let Some(language) = language.clone() {
995 let language_registry = language_registry.clone();
996 syntax.reparse(&text, language_registry, language);
997 }
998 BufferSnapshot {
999 text,
1000 syntax,
1001 file: None,
1002 diagnostics: Default::default(),
1003 remote_selections: Default::default(),
1004 language,
1005 non_text_state_update_count: 0,
1006 }
1007 }
1008 }
1009
1010 pub fn build_empty_snapshot(cx: &mut App) -> BufferSnapshot {
1011 let entity_id = cx.reserve_entity::<Self>().entity_id();
1012 let buffer_id = entity_id.as_non_zero_u64().into();
1013 let text =
1014 TextBuffer::new_normalized(0, buffer_id, Default::default(), Rope::new()).snapshot();
1015 let syntax = SyntaxMap::new(&text).snapshot();
1016 BufferSnapshot {
1017 text,
1018 syntax,
1019 file: None,
1020 diagnostics: Default::default(),
1021 remote_selections: Default::default(),
1022 language: None,
1023 non_text_state_update_count: 0,
1024 }
1025 }
1026
1027 #[cfg(any(test, feature = "test-support"))]
1028 pub fn build_snapshot_sync(
1029 text: Rope,
1030 language: Option<Arc<Language>>,
1031 language_registry: Option<Arc<LanguageRegistry>>,
1032 cx: &mut App,
1033 ) -> BufferSnapshot {
1034 let entity_id = cx.reserve_entity::<Self>().entity_id();
1035 let buffer_id = entity_id.as_non_zero_u64().into();
1036 let text = TextBuffer::new_normalized(0, buffer_id, Default::default(), text).snapshot();
1037 let mut syntax = SyntaxMap::new(&text).snapshot();
1038 if let Some(language) = language.clone() {
1039 syntax.reparse(&text, language_registry, language);
1040 }
1041 BufferSnapshot {
1042 text,
1043 syntax,
1044 file: None,
1045 diagnostics: Default::default(),
1046 remote_selections: Default::default(),
1047 language,
1048 non_text_state_update_count: 0,
1049 }
1050 }
1051
1052 /// Retrieve a snapshot of the buffer's current state. This is computationally
1053 /// cheap, and allows reading from the buffer on a background thread.
1054 pub fn snapshot(&self) -> BufferSnapshot {
1055 let text = self.text.snapshot();
1056 let mut syntax_map = self.syntax_map.lock();
1057 syntax_map.interpolate(&text);
1058 let syntax = syntax_map.snapshot();
1059
1060 BufferSnapshot {
1061 text,
1062 syntax,
1063 file: self.file.clone(),
1064 remote_selections: self.remote_selections.clone(),
1065 diagnostics: self.diagnostics.clone(),
1066 language: self.language.clone(),
1067 non_text_state_update_count: self.non_text_state_update_count,
1068 }
1069 }
1070
1071 pub fn branch(&mut self, cx: &mut Context<Self>) -> Entity<Self> {
1072 let this = cx.entity();
1073 cx.new(|cx| {
1074 let mut branch = Self {
1075 branch_state: Some(BufferBranchState {
1076 base_buffer: this.clone(),
1077 merged_operations: Default::default(),
1078 }),
1079 language: self.language.clone(),
1080 has_conflict: self.has_conflict,
1081 has_unsaved_edits: Cell::new(self.has_unsaved_edits.get_mut().clone()),
1082 _subscriptions: vec![cx.subscribe(&this, Self::on_base_buffer_event)],
1083 ..Self::build(self.text.branch(), self.file.clone(), self.capability())
1084 };
1085 if let Some(language_registry) = self.language_registry() {
1086 branch.set_language_registry(language_registry);
1087 }
1088
1089 // Reparse the branch buffer so that we get syntax highlighting immediately.
1090 branch.reparse(cx);
1091
1092 branch
1093 })
1094 }
1095
1096 pub fn preview_edits(
1097 &self,
1098 edits: Arc<[(Range<Anchor>, String)]>,
1099 cx: &App,
1100 ) -> Task<EditPreview> {
1101 let registry = self.language_registry();
1102 let language = self.language().cloned();
1103 let old_snapshot = self.text.snapshot();
1104 let mut branch_buffer = self.text.branch();
1105 let mut syntax_snapshot = self.syntax_map.lock().snapshot();
1106 cx.background_spawn(async move {
1107 if !edits.is_empty() {
1108 if let Some(language) = language.clone() {
1109 syntax_snapshot.reparse(&old_snapshot, registry.clone(), language);
1110 }
1111
1112 branch_buffer.edit(edits.iter().cloned());
1113 let snapshot = branch_buffer.snapshot();
1114 syntax_snapshot.interpolate(&snapshot);
1115
1116 if let Some(language) = language {
1117 syntax_snapshot.reparse(&snapshot, registry, language);
1118 }
1119 }
1120 EditPreview {
1121 old_snapshot,
1122 applied_edits_snapshot: branch_buffer.snapshot(),
1123 syntax_snapshot,
1124 }
1125 })
1126 }
1127
1128 /// Applies all of the changes in this buffer that intersect any of the
1129 /// given `ranges` to its base buffer.
1130 ///
1131 /// If `ranges` is empty, then all changes will be applied. This buffer must
1132 /// be a branch buffer to call this method.
1133 pub fn merge_into_base(&mut self, ranges: Vec<Range<usize>>, cx: &mut Context<Self>) {
1134 let Some(base_buffer) = self.base_buffer() else {
1135 debug_panic!("not a branch buffer");
1136 return;
1137 };
1138
1139 let mut ranges = if ranges.is_empty() {
1140 &[0..usize::MAX]
1141 } else {
1142 ranges.as_slice()
1143 }
1144 .iter()
1145 .peekable();
1146
1147 let mut edits = Vec::new();
1148 for edit in self.edits_since::<usize>(&base_buffer.read(cx).version()) {
1149 let mut is_included = false;
1150 while let Some(range) = ranges.peek() {
1151 if range.end < edit.new.start {
1152 ranges.next().unwrap();
1153 } else {
1154 if range.start <= edit.new.end {
1155 is_included = true;
1156 }
1157 break;
1158 }
1159 }
1160
1161 if is_included {
1162 edits.push((
1163 edit.old.clone(),
1164 self.text_for_range(edit.new.clone()).collect::<String>(),
1165 ));
1166 }
1167 }
1168
1169 let operation = base_buffer.update(cx, |base_buffer, cx| {
1170 // cx.emit(BufferEvent::DiffBaseChanged);
1171 base_buffer.edit(edits, None, cx)
1172 });
1173
1174 if let Some(operation) = operation
1175 && let Some(BufferBranchState {
1176 merged_operations, ..
1177 }) = &mut self.branch_state
1178 {
1179 merged_operations.push(operation);
1180 }
1181 }
1182
1183 fn on_base_buffer_event(
1184 &mut self,
1185 _: Entity<Buffer>,
1186 event: &BufferEvent,
1187 cx: &mut Context<Self>,
1188 ) {
1189 let BufferEvent::Operation { operation, .. } = event else {
1190 return;
1191 };
1192 let Some(BufferBranchState {
1193 merged_operations, ..
1194 }) = &mut self.branch_state
1195 else {
1196 return;
1197 };
1198
1199 let mut operation_to_undo = None;
1200 if let Operation::Buffer(text::Operation::Edit(operation)) = &operation
1201 && let Ok(ix) = merged_operations.binary_search(&operation.timestamp)
1202 {
1203 merged_operations.remove(ix);
1204 operation_to_undo = Some(operation.timestamp);
1205 }
1206
1207 self.apply_ops([operation.clone()], cx);
1208
1209 if let Some(timestamp) = operation_to_undo {
1210 let counts = [(timestamp, u32::MAX)].into_iter().collect();
1211 self.undo_operations(counts, cx);
1212 }
1213 }
1214
1215 #[cfg(test)]
1216 pub(crate) fn as_text_snapshot(&self) -> &text::BufferSnapshot {
1217 &self.text
1218 }
1219
1220 /// Retrieve a snapshot of the buffer's raw text, without any
1221 /// language-related state like the syntax tree or diagnostics.
1222 pub fn text_snapshot(&self) -> text::BufferSnapshot {
1223 self.text.snapshot()
1224 }
1225
1226 /// The file associated with the buffer, if any.
1227 pub fn file(&self) -> Option<&Arc<dyn File>> {
1228 self.file.as_ref()
1229 }
1230
1231 /// The version of the buffer that was last saved or reloaded from disk.
1232 pub fn saved_version(&self) -> &clock::Global {
1233 &self.saved_version
1234 }
1235
1236 /// The mtime of the buffer's file when the buffer was last saved or reloaded from disk.
1237 pub fn saved_mtime(&self) -> Option<MTime> {
1238 self.saved_mtime
1239 }
1240
1241 /// Assign a language to the buffer.
1242 pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut Context<Self>) {
1243 self.non_text_state_update_count += 1;
1244 self.syntax_map.lock().clear(&self.text);
1245 self.language = language;
1246 self.was_changed();
1247 self.reparse(cx);
1248 cx.emit(BufferEvent::LanguageChanged);
1249 }
1250
1251 /// Assign a language registry to the buffer. This allows the buffer to retrieve
1252 /// other languages if parts of the buffer are written in different languages.
1253 pub fn set_language_registry(&self, language_registry: Arc<LanguageRegistry>) {
1254 self.syntax_map
1255 .lock()
1256 .set_language_registry(language_registry);
1257 }
1258
1259 pub fn language_registry(&self) -> Option<Arc<LanguageRegistry>> {
1260 self.syntax_map.lock().language_registry()
1261 }
1262
1263 /// Assign the line ending type to the buffer.
1264 pub fn set_line_ending(&mut self, line_ending: LineEnding, cx: &mut Context<Self>) {
1265 self.text.set_line_ending(line_ending);
1266
1267 let lamport_timestamp = self.text.lamport_clock.tick();
1268 self.send_operation(
1269 Operation::UpdateLineEnding {
1270 line_ending,
1271 lamport_timestamp,
1272 },
1273 true,
1274 cx,
1275 );
1276 }
1277
1278 /// Assign the buffer a new [`Capability`].
1279 pub fn set_capability(&mut self, capability: Capability, cx: &mut Context<Self>) {
1280 if self.capability != capability {
1281 self.capability = capability;
1282 cx.emit(BufferEvent::CapabilityChanged)
1283 }
1284 }
1285
1286 /// This method is called to signal that the buffer has been saved.
1287 pub fn did_save(
1288 &mut self,
1289 version: clock::Global,
1290 mtime: Option<MTime>,
1291 cx: &mut Context<Self>,
1292 ) {
1293 self.saved_version = version;
1294 self.has_unsaved_edits
1295 .set((self.saved_version().clone(), false));
1296 self.has_conflict = false;
1297 self.saved_mtime = mtime;
1298 self.was_changed();
1299 cx.emit(BufferEvent::Saved);
1300 cx.notify();
1301 }
1302
1303 /// Reloads the contents of the buffer from disk.
1304 pub fn reload(&mut self, cx: &Context<Self>) -> oneshot::Receiver<Option<Transaction>> {
1305 let (tx, rx) = futures::channel::oneshot::channel();
1306 let prev_version = self.text.version();
1307 self.reload_task = Some(cx.spawn(async move |this, cx| {
1308 let Some((new_mtime, new_text)) = this.update(cx, |this, cx| {
1309 let file = this.file.as_ref()?.as_local()?;
1310
1311 Some((file.disk_state().mtime(), file.load(cx)))
1312 })?
1313 else {
1314 return Ok(());
1315 };
1316
1317 let new_text = new_text.await?;
1318 let diff = this
1319 .update(cx, |this, cx| this.diff(new_text.clone(), cx))?
1320 .await;
1321 this.update(cx, |this, cx| {
1322 if this.version() == diff.base_version {
1323 this.finalize_last_transaction();
1324 this.apply_diff(diff, cx);
1325 tx.send(this.finalize_last_transaction().cloned()).ok();
1326 this.has_conflict = false;
1327 this.did_reload(this.version(), this.line_ending(), new_mtime, cx);
1328 } else {
1329 if !diff.edits.is_empty()
1330 || this
1331 .edits_since::<usize>(&diff.base_version)
1332 .next()
1333 .is_some()
1334 {
1335 this.has_conflict = true;
1336 }
1337
1338 this.did_reload(prev_version, this.line_ending(), this.saved_mtime, cx);
1339 }
1340
1341 this.reload_task.take();
1342 })
1343 }));
1344 rx
1345 }
1346
1347 /// This method is called to signal that the buffer has been reloaded.
1348 pub fn did_reload(
1349 &mut self,
1350 version: clock::Global,
1351 line_ending: LineEnding,
1352 mtime: Option<MTime>,
1353 cx: &mut Context<Self>,
1354 ) {
1355 self.saved_version = version;
1356 self.has_unsaved_edits
1357 .set((self.saved_version.clone(), false));
1358 self.text.set_line_ending(line_ending);
1359 self.saved_mtime = mtime;
1360 cx.emit(BufferEvent::Reloaded);
1361 cx.notify();
1362 }
1363
1364 /// Updates the [`File`] backing this buffer. This should be called when
1365 /// the file has changed or has been deleted.
1366 pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut Context<Self>) {
1367 let was_dirty = self.is_dirty();
1368 let mut file_changed = false;
1369
1370 if let Some(old_file) = self.file.as_ref() {
1371 if new_file.path() != old_file.path() {
1372 file_changed = true;
1373 }
1374
1375 let old_state = old_file.disk_state();
1376 let new_state = new_file.disk_state();
1377 if old_state != new_state {
1378 file_changed = true;
1379 if !was_dirty && matches!(new_state, DiskState::Present { .. }) {
1380 cx.emit(BufferEvent::ReloadNeeded)
1381 }
1382 }
1383 } else {
1384 file_changed = true;
1385 };
1386
1387 self.file = Some(new_file);
1388 if file_changed {
1389 self.was_changed();
1390 self.non_text_state_update_count += 1;
1391 if was_dirty != self.is_dirty() {
1392 cx.emit(BufferEvent::DirtyChanged);
1393 }
1394 cx.emit(BufferEvent::FileHandleChanged);
1395 cx.notify();
1396 }
1397 }
1398
1399 pub fn base_buffer(&self) -> Option<Entity<Self>> {
1400 Some(self.branch_state.as_ref()?.base_buffer.clone())
1401 }
1402
1403 /// Returns the primary [`Language`] assigned to this [`Buffer`].
1404 pub fn language(&self) -> Option<&Arc<Language>> {
1405 self.language.as_ref()
1406 }
1407
1408 /// Returns the [`Language`] at the given location.
1409 pub fn language_at<D: ToOffset>(&self, position: D) -> Option<Arc<Language>> {
1410 let offset = position.to_offset(self);
1411 let mut is_first = true;
1412 let start_anchor = self.anchor_before(offset);
1413 let end_anchor = self.anchor_after(offset);
1414 self.syntax_map
1415 .lock()
1416 .layers_for_range(offset..offset, &self.text, false)
1417 .filter(|layer| {
1418 if is_first {
1419 is_first = false;
1420 return true;
1421 }
1422
1423 layer
1424 .included_sub_ranges
1425 .map(|sub_ranges| {
1426 sub_ranges.iter().any(|sub_range| {
1427 let is_before_start = sub_range.end.cmp(&start_anchor, self).is_lt();
1428 let is_after_end = sub_range.start.cmp(&end_anchor, self).is_gt();
1429 !is_before_start && !is_after_end
1430 })
1431 })
1432 .unwrap_or(true)
1433 })
1434 .last()
1435 .map(|info| info.language.clone())
1436 .or_else(|| self.language.clone())
1437 }
1438
1439 /// Returns each [`Language`] for the active syntax layers at the given location.
1440 pub fn languages_at<D: ToOffset>(&self, position: D) -> Vec<Arc<Language>> {
1441 let offset = position.to_offset(self);
1442 let mut languages: Vec<Arc<Language>> = self
1443 .syntax_map
1444 .lock()
1445 .layers_for_range(offset..offset, &self.text, false)
1446 .map(|info| info.language.clone())
1447 .collect();
1448
1449 if languages.is_empty()
1450 && let Some(buffer_language) = self.language()
1451 {
1452 languages.push(buffer_language.clone());
1453 }
1454
1455 languages
1456 }
1457
1458 /// An integer version number that accounts for all updates besides
1459 /// the buffer's text itself (which is versioned via a version vector).
1460 pub fn non_text_state_update_count(&self) -> usize {
1461 self.non_text_state_update_count
1462 }
1463
1464 /// Whether the buffer is being parsed in the background.
1465 #[cfg(any(test, feature = "test-support"))]
1466 pub fn is_parsing(&self) -> bool {
1467 self.reparse.is_some()
1468 }
1469
1470 /// Indicates whether the buffer contains any regions that may be
1471 /// written in a language that hasn't been loaded yet.
1472 pub fn contains_unknown_injections(&self) -> bool {
1473 self.syntax_map.lock().contains_unknown_injections()
1474 }
1475
1476 #[cfg(any(test, feature = "test-support"))]
1477 pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
1478 self.sync_parse_timeout = timeout;
1479 }
1480
1481 /// Called after an edit to synchronize the buffer's main parse tree with
1482 /// the buffer's new underlying state.
1483 ///
1484 /// Locks the syntax map and interpolates the edits since the last reparse
1485 /// into the foreground syntax tree.
1486 ///
1487 /// Then takes a stable snapshot of the syntax map before unlocking it.
1488 /// The snapshot with the interpolated edits is sent to a background thread,
1489 /// where we ask Tree-sitter to perform an incremental parse.
1490 ///
1491 /// Meanwhile, in the foreground, we block the main thread for up to 1ms
1492 /// waiting on the parse to complete. As soon as it completes, we proceed
1493 /// synchronously, unless a 1ms timeout elapses.
1494 ///
1495 /// If we time out waiting on the parse, we spawn a second task waiting
1496 /// until the parse does complete and return with the interpolated tree still
1497 /// in the foreground. When the background parse completes, call back into
1498 /// the main thread and assign the foreground parse state.
1499 ///
1500 /// If the buffer or grammar changed since the start of the background parse,
1501 /// initiate an additional reparse recursively. To avoid concurrent parses
1502 /// for the same buffer, we only initiate a new parse if we are not already
1503 /// parsing in the background.
1504 pub fn reparse(&mut self, cx: &mut Context<Self>) {
1505 if self.reparse.is_some() {
1506 return;
1507 }
1508 let language = if let Some(language) = self.language.clone() {
1509 language
1510 } else {
1511 return;
1512 };
1513
1514 let text = self.text_snapshot();
1515 let parsed_version = self.version();
1516
1517 let mut syntax_map = self.syntax_map.lock();
1518 syntax_map.interpolate(&text);
1519 let language_registry = syntax_map.language_registry();
1520 let mut syntax_snapshot = syntax_map.snapshot();
1521 drop(syntax_map);
1522
1523 let parse_task = cx.background_spawn({
1524 let language = language.clone();
1525 let language_registry = language_registry.clone();
1526 async move {
1527 syntax_snapshot.reparse(&text, language_registry, language);
1528 syntax_snapshot
1529 }
1530 });
1531
1532 self.parse_status.0.send(ParseStatus::Parsing).unwrap();
1533 match cx
1534 .background_executor()
1535 .block_with_timeout(self.sync_parse_timeout, parse_task)
1536 {
1537 Ok(new_syntax_snapshot) => {
1538 self.did_finish_parsing(new_syntax_snapshot, cx);
1539 self.reparse = None;
1540 }
1541 Err(parse_task) => {
1542 self.reparse = Some(cx.spawn(async move |this, cx| {
1543 let new_syntax_map = parse_task.await;
1544 this.update(cx, move |this, cx| {
1545 let grammar_changed =
1546 this.language.as_ref().is_none_or(|current_language| {
1547 !Arc::ptr_eq(&language, current_language)
1548 });
1549 let language_registry_changed = new_syntax_map
1550 .contains_unknown_injections()
1551 && language_registry.is_some_and(|registry| {
1552 registry.version() != new_syntax_map.language_registry_version()
1553 });
1554 let parse_again = language_registry_changed
1555 || grammar_changed
1556 || this.version.changed_since(&parsed_version);
1557 this.did_finish_parsing(new_syntax_map, cx);
1558 this.reparse = None;
1559 if parse_again {
1560 this.reparse(cx);
1561 }
1562 })
1563 .ok();
1564 }));
1565 }
1566 }
1567 }
1568
1569 fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut Context<Self>) {
1570 self.was_changed();
1571 self.non_text_state_update_count += 1;
1572 self.syntax_map.lock().did_parse(syntax_snapshot);
1573 self.request_autoindent(cx);
1574 self.parse_status.0.send(ParseStatus::Idle).unwrap();
1575 cx.emit(BufferEvent::Reparsed);
1576 cx.notify();
1577 }
1578
1579 pub fn parse_status(&self) -> watch::Receiver<ParseStatus> {
1580 self.parse_status.1.clone()
1581 }
1582
1583 /// Assign to the buffer a set of diagnostics created by a given language server.
1584 pub fn update_diagnostics(
1585 &mut self,
1586 server_id: LanguageServerId,
1587 diagnostics: DiagnosticSet,
1588 cx: &mut Context<Self>,
1589 ) {
1590 let lamport_timestamp = self.text.lamport_clock.tick();
1591 let op = Operation::UpdateDiagnostics {
1592 server_id,
1593 diagnostics: diagnostics.iter().cloned().collect(),
1594 lamport_timestamp,
1595 };
1596
1597 self.apply_diagnostic_update(server_id, diagnostics, lamport_timestamp, cx);
1598 self.send_operation(op, true, cx);
1599 }
1600
1601 pub fn buffer_diagnostics(
1602 &self,
1603 for_server: Option<LanguageServerId>,
1604 ) -> Vec<&DiagnosticEntry<Anchor>> {
1605 match for_server {
1606 Some(server_id) => match self.diagnostics.binary_search_by_key(&server_id, |v| v.0) {
1607 Ok(idx) => self.diagnostics[idx].1.iter().collect(),
1608 Err(_) => Vec::new(),
1609 },
1610 None => self
1611 .diagnostics
1612 .iter()
1613 .flat_map(|(_, diagnostic_set)| diagnostic_set.iter())
1614 .collect(),
1615 }
1616 }
1617
1618 fn request_autoindent(&mut self, cx: &mut Context<Self>) {
1619 if let Some(indent_sizes) = self.compute_autoindents() {
1620 let indent_sizes = cx.background_spawn(indent_sizes);
1621 match cx
1622 .background_executor()
1623 .block_with_timeout(Duration::from_micros(500), indent_sizes)
1624 {
1625 Ok(indent_sizes) => self.apply_autoindents(indent_sizes, cx),
1626 Err(indent_sizes) => {
1627 self.pending_autoindent = Some(cx.spawn(async move |this, cx| {
1628 let indent_sizes = indent_sizes.await;
1629 this.update(cx, |this, cx| {
1630 this.apply_autoindents(indent_sizes, cx);
1631 })
1632 .ok();
1633 }));
1634 }
1635 }
1636 } else {
1637 self.autoindent_requests.clear();
1638 for tx in self.wait_for_autoindent_txs.drain(..) {
1639 tx.send(()).ok();
1640 }
1641 }
1642 }
1643
1644 fn compute_autoindents(
1645 &self,
1646 ) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>> + use<>> {
1647 let max_rows_between_yields = 100;
1648 let snapshot = self.snapshot();
1649 if snapshot.syntax.is_empty() || self.autoindent_requests.is_empty() {
1650 return None;
1651 }
1652
1653 let autoindent_requests = self.autoindent_requests.clone();
1654 Some(async move {
1655 let mut indent_sizes = BTreeMap::<u32, (IndentSize, bool)>::new();
1656 for request in autoindent_requests {
1657 // Resolve each edited range to its row in the current buffer and in the
1658 // buffer before this batch of edits.
1659 let mut row_ranges = Vec::new();
1660 let mut old_to_new_rows = BTreeMap::new();
1661 let mut language_indent_sizes_by_new_row = Vec::new();
1662 for entry in &request.entries {
1663 let position = entry.range.start;
1664 let new_row = position.to_point(&snapshot).row;
1665 let new_end_row = entry.range.end.to_point(&snapshot).row + 1;
1666 language_indent_sizes_by_new_row.push((new_row, entry.indent_size));
1667
1668 if !entry.first_line_is_new {
1669 let old_row = position.to_point(&request.before_edit).row;
1670 old_to_new_rows.insert(old_row, new_row);
1671 }
1672 row_ranges.push((new_row..new_end_row, entry.original_indent_column));
1673 }
1674
1675 // Build a map containing the suggested indentation for each of the edited lines
1676 // with respect to the state of the buffer before these edits. This map is keyed
1677 // by the rows for these lines in the current state of the buffer.
1678 let mut old_suggestions = BTreeMap::<u32, (IndentSize, bool)>::default();
1679 let old_edited_ranges =
1680 contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
1681 let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
1682 let mut language_indent_size = IndentSize::default();
1683 for old_edited_range in old_edited_ranges {
1684 let suggestions = request
1685 .before_edit
1686 .suggest_autoindents(old_edited_range.clone())
1687 .into_iter()
1688 .flatten();
1689 for (old_row, suggestion) in old_edited_range.zip(suggestions) {
1690 if let Some(suggestion) = suggestion {
1691 let new_row = *old_to_new_rows.get(&old_row).unwrap();
1692
1693 // Find the indent size based on the language for this row.
1694 while let Some((row, size)) = language_indent_sizes.peek() {
1695 if *row > new_row {
1696 break;
1697 }
1698 language_indent_size = *size;
1699 language_indent_sizes.next();
1700 }
1701
1702 let suggested_indent = old_to_new_rows
1703 .get(&suggestion.basis_row)
1704 .and_then(|from_row| {
1705 Some(old_suggestions.get(from_row).copied()?.0)
1706 })
1707 .unwrap_or_else(|| {
1708 request
1709 .before_edit
1710 .indent_size_for_line(suggestion.basis_row)
1711 })
1712 .with_delta(suggestion.delta, language_indent_size);
1713 old_suggestions
1714 .insert(new_row, (suggested_indent, suggestion.within_error));
1715 }
1716 }
1717 yield_now().await;
1718 }
1719
1720 // Compute new suggestions for each line, but only include them in the result
1721 // if they differ from the old suggestion for that line.
1722 let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
1723 let mut language_indent_size = IndentSize::default();
1724 for (row_range, original_indent_column) in row_ranges {
1725 let new_edited_row_range = if request.is_block_mode {
1726 row_range.start..row_range.start + 1
1727 } else {
1728 row_range.clone()
1729 };
1730
1731 let suggestions = snapshot
1732 .suggest_autoindents(new_edited_row_range.clone())
1733 .into_iter()
1734 .flatten();
1735 for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
1736 if let Some(suggestion) = suggestion {
1737 // Find the indent size based on the language for this row.
1738 while let Some((row, size)) = language_indent_sizes.peek() {
1739 if *row > new_row {
1740 break;
1741 }
1742 language_indent_size = *size;
1743 language_indent_sizes.next();
1744 }
1745
1746 let suggested_indent = indent_sizes
1747 .get(&suggestion.basis_row)
1748 .copied()
1749 .map(|e| e.0)
1750 .unwrap_or_else(|| {
1751 snapshot.indent_size_for_line(suggestion.basis_row)
1752 })
1753 .with_delta(suggestion.delta, language_indent_size);
1754
1755 if old_suggestions.get(&new_row).is_none_or(
1756 |(old_indentation, was_within_error)| {
1757 suggested_indent != *old_indentation
1758 && (!suggestion.within_error || *was_within_error)
1759 },
1760 ) {
1761 indent_sizes.insert(
1762 new_row,
1763 (suggested_indent, request.ignore_empty_lines),
1764 );
1765 }
1766 }
1767 }
1768
1769 if let (true, Some(original_indent_column)) =
1770 (request.is_block_mode, original_indent_column)
1771 {
1772 let new_indent =
1773 if let Some((indent, _)) = indent_sizes.get(&row_range.start) {
1774 *indent
1775 } else {
1776 snapshot.indent_size_for_line(row_range.start)
1777 };
1778 let delta = new_indent.len as i64 - original_indent_column as i64;
1779 if delta != 0 {
1780 for row in row_range.skip(1) {
1781 indent_sizes.entry(row).or_insert_with(|| {
1782 let mut size = snapshot.indent_size_for_line(row);
1783 if size.kind == new_indent.kind {
1784 match delta.cmp(&0) {
1785 Ordering::Greater => size.len += delta as u32,
1786 Ordering::Less => {
1787 size.len = size.len.saturating_sub(-delta as u32)
1788 }
1789 Ordering::Equal => {}
1790 }
1791 }
1792 (size, request.ignore_empty_lines)
1793 });
1794 }
1795 }
1796 }
1797
1798 yield_now().await;
1799 }
1800 }
1801
1802 indent_sizes
1803 .into_iter()
1804 .filter_map(|(row, (indent, ignore_empty_lines))| {
1805 if ignore_empty_lines && snapshot.line_len(row) == 0 {
1806 None
1807 } else {
1808 Some((row, indent))
1809 }
1810 })
1811 .collect()
1812 })
1813 }
1814
1815 fn apply_autoindents(
1816 &mut self,
1817 indent_sizes: BTreeMap<u32, IndentSize>,
1818 cx: &mut Context<Self>,
1819 ) {
1820 self.autoindent_requests.clear();
1821 for tx in self.wait_for_autoindent_txs.drain(..) {
1822 tx.send(()).ok();
1823 }
1824
1825 let edits: Vec<_> = indent_sizes
1826 .into_iter()
1827 .filter_map(|(row, indent_size)| {
1828 let current_size = indent_size_for_line(self, row);
1829 Self::edit_for_indent_size_adjustment(row, current_size, indent_size)
1830 })
1831 .collect();
1832
1833 let preserve_preview = self.preserve_preview();
1834 self.edit(edits, None, cx);
1835 if preserve_preview {
1836 self.refresh_preview();
1837 }
1838 }
1839
1840 /// Create a minimal edit that will cause the given row to be indented
1841 /// with the given size. After applying this edit, the length of the line
1842 /// will always be at least `new_size.len`.
1843 pub fn edit_for_indent_size_adjustment(
1844 row: u32,
1845 current_size: IndentSize,
1846 new_size: IndentSize,
1847 ) -> Option<(Range<Point>, String)> {
1848 if new_size.kind == current_size.kind {
1849 match new_size.len.cmp(¤t_size.len) {
1850 Ordering::Greater => {
1851 let point = Point::new(row, 0);
1852 Some((
1853 point..point,
1854 iter::repeat(new_size.char())
1855 .take((new_size.len - current_size.len) as usize)
1856 .collect::<String>(),
1857 ))
1858 }
1859
1860 Ordering::Less => Some((
1861 Point::new(row, 0)..Point::new(row, current_size.len - new_size.len),
1862 String::new(),
1863 )),
1864
1865 Ordering::Equal => None,
1866 }
1867 } else {
1868 Some((
1869 Point::new(row, 0)..Point::new(row, current_size.len),
1870 iter::repeat(new_size.char())
1871 .take(new_size.len as usize)
1872 .collect::<String>(),
1873 ))
1874 }
1875 }
1876
1877 /// Spawns a background task that asynchronously computes a `Diff` between the buffer's text
1878 /// and the given new text.
1879 pub fn diff(&self, mut new_text: String, cx: &App) -> Task<Diff> {
1880 let old_text = self.as_rope().clone();
1881 let base_version = self.version();
1882 cx.background_executor()
1883 .spawn_labeled(*BUFFER_DIFF_TASK, async move {
1884 let old_text = old_text.to_string();
1885 let line_ending = LineEnding::detect(&new_text);
1886 LineEnding::normalize(&mut new_text);
1887 let edits = text_diff(&old_text, &new_text);
1888 Diff {
1889 base_version,
1890 line_ending,
1891 edits,
1892 }
1893 })
1894 }
1895
1896 /// Spawns a background task that searches the buffer for any whitespace
1897 /// at the ends of a lines, and returns a `Diff` that removes that whitespace.
1898 pub fn remove_trailing_whitespace(&self, cx: &App) -> Task<Diff> {
1899 let old_text = self.as_rope().clone();
1900 let line_ending = self.line_ending();
1901 let base_version = self.version();
1902 cx.background_spawn(async move {
1903 let ranges = trailing_whitespace_ranges(&old_text);
1904 let empty = Arc::<str>::from("");
1905 Diff {
1906 base_version,
1907 line_ending,
1908 edits: ranges
1909 .into_iter()
1910 .map(|range| (range, empty.clone()))
1911 .collect(),
1912 }
1913 })
1914 }
1915
1916 /// Ensures that the buffer ends with a single newline character, and
1917 /// no other whitespace. Skips if the buffer is empty.
1918 pub fn ensure_final_newline(&mut self, cx: &mut Context<Self>) {
1919 let len = self.len();
1920 if len == 0 {
1921 return;
1922 }
1923 let mut offset = len;
1924 for chunk in self.as_rope().reversed_chunks_in_range(0..len) {
1925 let non_whitespace_len = chunk
1926 .trim_end_matches(|c: char| c.is_ascii_whitespace())
1927 .len();
1928 offset -= chunk.len();
1929 offset += non_whitespace_len;
1930 if non_whitespace_len != 0 {
1931 if offset == len - 1 && chunk.get(non_whitespace_len..) == Some("\n") {
1932 return;
1933 }
1934 break;
1935 }
1936 }
1937 self.edit([(offset..len, "\n")], None, cx);
1938 }
1939
1940 /// Applies a diff to the buffer. If the buffer has changed since the given diff was
1941 /// calculated, then adjust the diff to account for those changes, and discard any
1942 /// parts of the diff that conflict with those changes.
1943 pub fn apply_diff(&mut self, diff: Diff, cx: &mut Context<Self>) -> Option<TransactionId> {
1944 let snapshot = self.snapshot();
1945 let mut edits_since = snapshot.edits_since::<usize>(&diff.base_version).peekable();
1946 let mut delta = 0;
1947 let adjusted_edits = diff.edits.into_iter().filter_map(|(range, new_text)| {
1948 while let Some(edit_since) = edits_since.peek() {
1949 // If the edit occurs after a diff hunk, then it does not
1950 // affect that hunk.
1951 if edit_since.old.start > range.end {
1952 break;
1953 }
1954 // If the edit precedes the diff hunk, then adjust the hunk
1955 // to reflect the edit.
1956 else if edit_since.old.end < range.start {
1957 delta += edit_since.new_len() as i64 - edit_since.old_len() as i64;
1958 edits_since.next();
1959 }
1960 // If the edit intersects a diff hunk, then discard that hunk.
1961 else {
1962 return None;
1963 }
1964 }
1965
1966 let start = (range.start as i64 + delta) as usize;
1967 let end = (range.end as i64 + delta) as usize;
1968 Some((start..end, new_text))
1969 });
1970
1971 self.start_transaction();
1972 self.text.set_line_ending(diff.line_ending);
1973 self.edit(adjusted_edits, None, cx);
1974 self.end_transaction(cx)
1975 }
1976
1977 fn has_unsaved_edits(&self) -> bool {
1978 let (last_version, has_unsaved_edits) = self.has_unsaved_edits.take();
1979
1980 if last_version == self.version {
1981 self.has_unsaved_edits
1982 .set((last_version, has_unsaved_edits));
1983 return has_unsaved_edits;
1984 }
1985
1986 let has_edits = self.has_edits_since(&self.saved_version);
1987 self.has_unsaved_edits
1988 .set((self.version.clone(), has_edits));
1989 has_edits
1990 }
1991
1992 /// Checks if the buffer has unsaved changes.
1993 pub fn is_dirty(&self) -> bool {
1994 if self.capability == Capability::ReadOnly {
1995 return false;
1996 }
1997 if self.has_conflict {
1998 return true;
1999 }
2000 match self.file.as_ref().map(|f| f.disk_state()) {
2001 Some(DiskState::New) | Some(DiskState::Deleted) => {
2002 !self.is_empty() && self.has_unsaved_edits()
2003 }
2004 _ => self.has_unsaved_edits(),
2005 }
2006 }
2007
2008 /// Checks if the buffer and its file have both changed since the buffer
2009 /// was last saved or reloaded.
2010 pub fn has_conflict(&self) -> bool {
2011 if self.has_conflict {
2012 return true;
2013 }
2014 let Some(file) = self.file.as_ref() else {
2015 return false;
2016 };
2017 match file.disk_state() {
2018 DiskState::New => false,
2019 DiskState::Present { mtime } => match self.saved_mtime {
2020 Some(saved_mtime) => {
2021 mtime.bad_is_greater_than(saved_mtime) && self.has_unsaved_edits()
2022 }
2023 None => true,
2024 },
2025 DiskState::Deleted => false,
2026 }
2027 }
2028
2029 /// Gets a [`Subscription`] that tracks all of the changes to the buffer's text.
2030 pub fn subscribe(&mut self) -> Subscription {
2031 self.text.subscribe()
2032 }
2033
2034 /// Adds a bit to the list of bits that are set when the buffer's text changes.
2035 ///
2036 /// This allows downstream code to check if the buffer's text has changed without
2037 /// waiting for an effect cycle, which would be required if using eents.
2038 pub fn record_changes(&mut self, bit: rc::Weak<Cell<bool>>) {
2039 if let Err(ix) = self
2040 .change_bits
2041 .binary_search_by_key(&rc::Weak::as_ptr(&bit), rc::Weak::as_ptr)
2042 {
2043 self.change_bits.insert(ix, bit);
2044 }
2045 }
2046
2047 fn was_changed(&mut self) {
2048 self.change_bits.retain(|change_bit| {
2049 change_bit.upgrade().is_some_and(|bit| {
2050 bit.replace(true);
2051 true
2052 })
2053 });
2054 }
2055
2056 /// Starts a transaction, if one is not already in-progress. When undoing or
2057 /// redoing edits, all of the edits performed within a transaction are undone
2058 /// or redone together.
2059 pub fn start_transaction(&mut self) -> Option<TransactionId> {
2060 self.start_transaction_at(Instant::now())
2061 }
2062
2063 /// Starts a transaction, providing the current time. Subsequent transactions
2064 /// that occur within a short period of time will be grouped together. This
2065 /// is controlled by the buffer's undo grouping duration.
2066 pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
2067 self.transaction_depth += 1;
2068 if self.was_dirty_before_starting_transaction.is_none() {
2069 self.was_dirty_before_starting_transaction = Some(self.is_dirty());
2070 }
2071 self.text.start_transaction_at(now)
2072 }
2073
2074 /// Terminates the current transaction, if this is the outermost transaction.
2075 pub fn end_transaction(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
2076 self.end_transaction_at(Instant::now(), cx)
2077 }
2078
2079 /// Terminates the current transaction, providing the current time. Subsequent transactions
2080 /// that occur within a short period of time will be grouped together. This
2081 /// is controlled by the buffer's undo grouping duration.
2082 pub fn end_transaction_at(
2083 &mut self,
2084 now: Instant,
2085 cx: &mut Context<Self>,
2086 ) -> Option<TransactionId> {
2087 assert!(self.transaction_depth > 0);
2088 self.transaction_depth -= 1;
2089 let was_dirty = if self.transaction_depth == 0 {
2090 self.was_dirty_before_starting_transaction.take().unwrap()
2091 } else {
2092 false
2093 };
2094 if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
2095 self.did_edit(&start_version, was_dirty, cx);
2096 Some(transaction_id)
2097 } else {
2098 None
2099 }
2100 }
2101
2102 /// Manually add a transaction to the buffer's undo history.
2103 pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
2104 self.text.push_transaction(transaction, now);
2105 }
2106
2107 /// Differs from `push_transaction` in that it does not clear the redo
2108 /// stack. Intended to be used to create a parent transaction to merge
2109 /// potential child transactions into.
2110 ///
2111 /// The caller is responsible for removing it from the undo history using
2112 /// `forget_transaction` if no edits are merged into it. Otherwise, if edits
2113 /// are merged into this transaction, the caller is responsible for ensuring
2114 /// the redo stack is cleared. The easiest way to ensure the redo stack is
2115 /// cleared is to create transactions with the usual `start_transaction` and
2116 /// `end_transaction` methods and merging the resulting transactions into
2117 /// the transaction created by this method
2118 pub fn push_empty_transaction(&mut self, now: Instant) -> TransactionId {
2119 self.text.push_empty_transaction(now)
2120 }
2121
2122 /// Prevent the last transaction from being grouped with any subsequent transactions,
2123 /// even if they occur with the buffer's undo grouping duration.
2124 pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
2125 self.text.finalize_last_transaction()
2126 }
2127
2128 /// Manually group all changes since a given transaction.
2129 pub fn group_until_transaction(&mut self, transaction_id: TransactionId) {
2130 self.text.group_until_transaction(transaction_id);
2131 }
2132
2133 /// Manually remove a transaction from the buffer's undo history
2134 pub fn forget_transaction(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
2135 self.text.forget_transaction(transaction_id)
2136 }
2137
2138 /// Retrieve a transaction from the buffer's undo history
2139 pub fn get_transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
2140 self.text.get_transaction(transaction_id)
2141 }
2142
2143 /// Manually merge two transactions in the buffer's undo history.
2144 pub fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) {
2145 self.text.merge_transactions(transaction, destination);
2146 }
2147
2148 /// Waits for the buffer to receive operations with the given timestamps.
2149 pub fn wait_for_edits<It: IntoIterator<Item = clock::Lamport>>(
2150 &mut self,
2151 edit_ids: It,
2152 ) -> impl Future<Output = Result<()>> + use<It> {
2153 self.text.wait_for_edits(edit_ids)
2154 }
2155
2156 /// Waits for the buffer to receive the operations necessary for resolving the given anchors.
2157 pub fn wait_for_anchors<It: IntoIterator<Item = Anchor>>(
2158 &mut self,
2159 anchors: It,
2160 ) -> impl 'static + Future<Output = Result<()>> + use<It> {
2161 self.text.wait_for_anchors(anchors)
2162 }
2163
2164 /// Waits for the buffer to receive operations up to the given version.
2165 pub fn wait_for_version(
2166 &mut self,
2167 version: clock::Global,
2168 ) -> impl Future<Output = Result<()>> + use<> {
2169 self.text.wait_for_version(version)
2170 }
2171
2172 /// Forces all futures returned by [`Buffer::wait_for_version`], [`Buffer::wait_for_edits`], or
2173 /// [`Buffer::wait_for_version`] to resolve with an error.
2174 pub fn give_up_waiting(&mut self) {
2175 self.text.give_up_waiting();
2176 }
2177
2178 pub fn wait_for_autoindent_applied(&mut self) -> Option<oneshot::Receiver<()>> {
2179 let mut rx = None;
2180 if !self.autoindent_requests.is_empty() {
2181 let channel = oneshot::channel();
2182 self.wait_for_autoindent_txs.push(channel.0);
2183 rx = Some(channel.1);
2184 }
2185 rx
2186 }
2187
2188 /// Stores a set of selections that should be broadcasted to all of the buffer's replicas.
2189 pub fn set_active_selections(
2190 &mut self,
2191 selections: Arc<[Selection<Anchor>]>,
2192 line_mode: bool,
2193 cursor_shape: CursorShape,
2194 cx: &mut Context<Self>,
2195 ) {
2196 let lamport_timestamp = self.text.lamport_clock.tick();
2197 self.remote_selections.insert(
2198 self.text.replica_id(),
2199 SelectionSet {
2200 selections: selections.clone(),
2201 lamport_timestamp,
2202 line_mode,
2203 cursor_shape,
2204 },
2205 );
2206 self.send_operation(
2207 Operation::UpdateSelections {
2208 selections,
2209 line_mode,
2210 lamport_timestamp,
2211 cursor_shape,
2212 },
2213 true,
2214 cx,
2215 );
2216 self.non_text_state_update_count += 1;
2217 cx.notify();
2218 }
2219
2220 /// Clears the selections, so that other replicas of the buffer do not see any selections for
2221 /// this replica.
2222 pub fn remove_active_selections(&mut self, cx: &mut Context<Self>) {
2223 if self
2224 .remote_selections
2225 .get(&self.text.replica_id())
2226 .is_none_or(|set| !set.selections.is_empty())
2227 {
2228 self.set_active_selections(Arc::default(), false, Default::default(), cx);
2229 }
2230 }
2231
2232 pub fn set_agent_selections(
2233 &mut self,
2234 selections: Arc<[Selection<Anchor>]>,
2235 line_mode: bool,
2236 cursor_shape: CursorShape,
2237 cx: &mut Context<Self>,
2238 ) {
2239 let lamport_timestamp = self.text.lamport_clock.tick();
2240 self.remote_selections.insert(
2241 AGENT_REPLICA_ID,
2242 SelectionSet {
2243 selections,
2244 lamport_timestamp,
2245 line_mode,
2246 cursor_shape,
2247 },
2248 );
2249 self.non_text_state_update_count += 1;
2250 cx.notify();
2251 }
2252
2253 pub fn remove_agent_selections(&mut self, cx: &mut Context<Self>) {
2254 self.set_agent_selections(Arc::default(), false, Default::default(), cx);
2255 }
2256
2257 /// Replaces the buffer's entire text.
2258 pub fn set_text<T>(&mut self, text: T, cx: &mut Context<Self>) -> Option<clock::Lamport>
2259 where
2260 T: Into<Arc<str>>,
2261 {
2262 self.autoindent_requests.clear();
2263 self.edit([(0..self.len(), text)], None, cx)
2264 }
2265
2266 /// Appends the given text to the end of the buffer.
2267 pub fn append<T>(&mut self, text: T, cx: &mut Context<Self>) -> Option<clock::Lamport>
2268 where
2269 T: Into<Arc<str>>,
2270 {
2271 self.edit([(self.len()..self.len(), text)], None, cx)
2272 }
2273
2274 /// Applies the given edits to the buffer. Each edit is specified as a range of text to
2275 /// delete, and a string of text to insert at that location.
2276 ///
2277 /// If an [`AutoindentMode`] is provided, then the buffer will enqueue an auto-indent
2278 /// request for the edited ranges, which will be processed when the buffer finishes
2279 /// parsing.
2280 ///
2281 /// Parsing takes place at the end of a transaction, and may compute synchronously
2282 /// or asynchronously, depending on the changes.
2283 pub fn edit<I, S, T>(
2284 &mut self,
2285 edits_iter: I,
2286 autoindent_mode: Option<AutoindentMode>,
2287 cx: &mut Context<Self>,
2288 ) -> Option<clock::Lamport>
2289 where
2290 I: IntoIterator<Item = (Range<S>, T)>,
2291 S: ToOffset,
2292 T: Into<Arc<str>>,
2293 {
2294 // Skip invalid edits and coalesce contiguous ones.
2295 let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
2296
2297 for (range, new_text) in edits_iter {
2298 let mut range = range.start.to_offset(self)..range.end.to_offset(self);
2299
2300 if range.start > range.end {
2301 mem::swap(&mut range.start, &mut range.end);
2302 }
2303 let new_text = new_text.into();
2304 if !new_text.is_empty() || !range.is_empty() {
2305 if let Some((prev_range, prev_text)) = edits.last_mut()
2306 && prev_range.end >= range.start
2307 {
2308 prev_range.end = cmp::max(prev_range.end, range.end);
2309 *prev_text = format!("{prev_text}{new_text}").into();
2310 } else {
2311 edits.push((range, new_text));
2312 }
2313 }
2314 }
2315 if edits.is_empty() {
2316 return None;
2317 }
2318
2319 self.start_transaction();
2320 self.pending_autoindent.take();
2321 let autoindent_request = autoindent_mode
2322 .and_then(|mode| self.language.as_ref().map(|_| (self.snapshot(), mode)));
2323
2324 let edit_operation = self.text.edit(edits.iter().cloned());
2325 let edit_id = edit_operation.timestamp();
2326
2327 if let Some((before_edit, mode)) = autoindent_request {
2328 let mut delta = 0isize;
2329 let mut previous_setting = None;
2330 let entries: Vec<_> = edits
2331 .into_iter()
2332 .enumerate()
2333 .zip(&edit_operation.as_edit().unwrap().new_text)
2334 .filter(|((_, (range, _)), _)| {
2335 let language = before_edit.language_at(range.start);
2336 let language_id = language.map(|l| l.id());
2337 if let Some((cached_language_id, auto_indent)) = previous_setting
2338 && cached_language_id == language_id
2339 {
2340 auto_indent
2341 } else {
2342 // The auto-indent setting is not present in editorconfigs, hence
2343 // we can avoid passing the file here.
2344 let auto_indent =
2345 language_settings(language.map(|l| l.name()), None, cx).auto_indent;
2346 previous_setting = Some((language_id, auto_indent));
2347 auto_indent
2348 }
2349 })
2350 .map(|((ix, (range, _)), new_text)| {
2351 let new_text_length = new_text.len();
2352 let old_start = range.start.to_point(&before_edit);
2353 let new_start = (delta + range.start as isize) as usize;
2354 let range_len = range.end - range.start;
2355 delta += new_text_length as isize - range_len as isize;
2356
2357 // Decide what range of the insertion to auto-indent, and whether
2358 // the first line of the insertion should be considered a newly-inserted line
2359 // or an edit to an existing line.
2360 let mut range_of_insertion_to_indent = 0..new_text_length;
2361 let mut first_line_is_new = true;
2362
2363 let old_line_start = before_edit.indent_size_for_line(old_start.row).len;
2364 let old_line_end = before_edit.line_len(old_start.row);
2365
2366 if old_start.column > old_line_start {
2367 first_line_is_new = false;
2368 }
2369
2370 if !new_text.contains('\n')
2371 && (old_start.column + (range_len as u32) < old_line_end
2372 || old_line_end == old_line_start)
2373 {
2374 first_line_is_new = false;
2375 }
2376
2377 // When inserting text starting with a newline, avoid auto-indenting the
2378 // previous line.
2379 if new_text.starts_with('\n') {
2380 range_of_insertion_to_indent.start += 1;
2381 first_line_is_new = true;
2382 }
2383
2384 let mut original_indent_column = None;
2385 if let AutoindentMode::Block {
2386 original_indent_columns,
2387 } = &mode
2388 {
2389 original_indent_column = Some(if new_text.starts_with('\n') {
2390 indent_size_for_text(
2391 new_text[range_of_insertion_to_indent.clone()].chars(),
2392 )
2393 .len
2394 } else {
2395 original_indent_columns
2396 .get(ix)
2397 .copied()
2398 .flatten()
2399 .unwrap_or_else(|| {
2400 indent_size_for_text(
2401 new_text[range_of_insertion_to_indent.clone()].chars(),
2402 )
2403 .len
2404 })
2405 });
2406
2407 // Avoid auto-indenting the line after the edit.
2408 if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
2409 range_of_insertion_to_indent.end -= 1;
2410 }
2411 }
2412
2413 AutoindentRequestEntry {
2414 first_line_is_new,
2415 original_indent_column,
2416 indent_size: before_edit.language_indent_size_at(range.start, cx),
2417 range: self.anchor_before(new_start + range_of_insertion_to_indent.start)
2418 ..self.anchor_after(new_start + range_of_insertion_to_indent.end),
2419 }
2420 })
2421 .collect();
2422
2423 if !entries.is_empty() {
2424 self.autoindent_requests.push(Arc::new(AutoindentRequest {
2425 before_edit,
2426 entries,
2427 is_block_mode: matches!(mode, AutoindentMode::Block { .. }),
2428 ignore_empty_lines: false,
2429 }));
2430 }
2431 }
2432
2433 self.end_transaction(cx);
2434 self.send_operation(Operation::Buffer(edit_operation), true, cx);
2435 Some(edit_id)
2436 }
2437
2438 fn did_edit(&mut self, old_version: &clock::Global, was_dirty: bool, cx: &mut Context<Self>) {
2439 self.was_changed();
2440
2441 if self.edits_since::<usize>(old_version).next().is_none() {
2442 return;
2443 }
2444
2445 self.reparse(cx);
2446 cx.emit(BufferEvent::Edited);
2447 if was_dirty != self.is_dirty() {
2448 cx.emit(BufferEvent::DirtyChanged);
2449 }
2450 cx.notify();
2451 }
2452
2453 pub fn autoindent_ranges<I, T>(&mut self, ranges: I, cx: &mut Context<Self>)
2454 where
2455 I: IntoIterator<Item = Range<T>>,
2456 T: ToOffset + Copy,
2457 {
2458 let before_edit = self.snapshot();
2459 let entries = ranges
2460 .into_iter()
2461 .map(|range| AutoindentRequestEntry {
2462 range: before_edit.anchor_before(range.start)..before_edit.anchor_after(range.end),
2463 first_line_is_new: true,
2464 indent_size: before_edit.language_indent_size_at(range.start, cx),
2465 original_indent_column: None,
2466 })
2467 .collect();
2468 self.autoindent_requests.push(Arc::new(AutoindentRequest {
2469 before_edit,
2470 entries,
2471 is_block_mode: false,
2472 ignore_empty_lines: true,
2473 }));
2474 self.request_autoindent(cx);
2475 }
2476
2477 // Inserts newlines at the given position to create an empty line, returning the start of the new line.
2478 // You can also request the insertion of empty lines above and below the line starting at the returned point.
2479 pub fn insert_empty_line(
2480 &mut self,
2481 position: impl ToPoint,
2482 space_above: bool,
2483 space_below: bool,
2484 cx: &mut Context<Self>,
2485 ) -> Point {
2486 let mut position = position.to_point(self);
2487
2488 self.start_transaction();
2489
2490 self.edit(
2491 [(position..position, "\n")],
2492 Some(AutoindentMode::EachLine),
2493 cx,
2494 );
2495
2496 if position.column > 0 {
2497 position += Point::new(1, 0);
2498 }
2499
2500 if !self.is_line_blank(position.row) {
2501 self.edit(
2502 [(position..position, "\n")],
2503 Some(AutoindentMode::EachLine),
2504 cx,
2505 );
2506 }
2507
2508 if space_above && position.row > 0 && !self.is_line_blank(position.row - 1) {
2509 self.edit(
2510 [(position..position, "\n")],
2511 Some(AutoindentMode::EachLine),
2512 cx,
2513 );
2514 position.row += 1;
2515 }
2516
2517 if space_below
2518 && (position.row == self.max_point().row || !self.is_line_blank(position.row + 1))
2519 {
2520 self.edit(
2521 [(position..position, "\n")],
2522 Some(AutoindentMode::EachLine),
2523 cx,
2524 );
2525 }
2526
2527 self.end_transaction(cx);
2528
2529 position
2530 }
2531
2532 /// Applies the given remote operations to the buffer.
2533 pub fn apply_ops<I: IntoIterator<Item = Operation>>(&mut self, ops: I, cx: &mut Context<Self>) {
2534 self.pending_autoindent.take();
2535 let was_dirty = self.is_dirty();
2536 let old_version = self.version.clone();
2537 let mut deferred_ops = Vec::new();
2538 let buffer_ops = ops
2539 .into_iter()
2540 .filter_map(|op| match op {
2541 Operation::Buffer(op) => Some(op),
2542 _ => {
2543 if self.can_apply_op(&op) {
2544 self.apply_op(op, cx);
2545 } else {
2546 deferred_ops.push(op);
2547 }
2548 None
2549 }
2550 })
2551 .collect::<Vec<_>>();
2552 for operation in buffer_ops.iter() {
2553 self.send_operation(Operation::Buffer(operation.clone()), false, cx);
2554 }
2555 self.text.apply_ops(buffer_ops);
2556 self.deferred_ops.insert(deferred_ops);
2557 self.flush_deferred_ops(cx);
2558 self.did_edit(&old_version, was_dirty, cx);
2559 // Notify independently of whether the buffer was edited as the operations could include a
2560 // selection update.
2561 cx.notify();
2562 }
2563
2564 fn flush_deferred_ops(&mut self, cx: &mut Context<Self>) {
2565 let mut deferred_ops = Vec::new();
2566 for op in self.deferred_ops.drain().iter().cloned() {
2567 if self.can_apply_op(&op) {
2568 self.apply_op(op, cx);
2569 } else {
2570 deferred_ops.push(op);
2571 }
2572 }
2573 self.deferred_ops.insert(deferred_ops);
2574 }
2575
2576 pub fn has_deferred_ops(&self) -> bool {
2577 !self.deferred_ops.is_empty() || self.text.has_deferred_ops()
2578 }
2579
2580 fn can_apply_op(&self, operation: &Operation) -> bool {
2581 match operation {
2582 Operation::Buffer(_) => {
2583 unreachable!("buffer operations should never be applied at this layer")
2584 }
2585 Operation::UpdateDiagnostics {
2586 diagnostics: diagnostic_set,
2587 ..
2588 } => diagnostic_set.iter().all(|diagnostic| {
2589 self.text.can_resolve(&diagnostic.range.start)
2590 && self.text.can_resolve(&diagnostic.range.end)
2591 }),
2592 Operation::UpdateSelections { selections, .. } => selections
2593 .iter()
2594 .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
2595 Operation::UpdateCompletionTriggers { .. } | Operation::UpdateLineEnding { .. } => true,
2596 }
2597 }
2598
2599 fn apply_op(&mut self, operation: Operation, cx: &mut Context<Self>) {
2600 match operation {
2601 Operation::Buffer(_) => {
2602 unreachable!("buffer operations should never be applied at this layer")
2603 }
2604 Operation::UpdateDiagnostics {
2605 server_id,
2606 diagnostics: diagnostic_set,
2607 lamport_timestamp,
2608 } => {
2609 let snapshot = self.snapshot();
2610 self.apply_diagnostic_update(
2611 server_id,
2612 DiagnosticSet::from_sorted_entries(diagnostic_set.iter().cloned(), &snapshot),
2613 lamport_timestamp,
2614 cx,
2615 );
2616 }
2617 Operation::UpdateSelections {
2618 selections,
2619 lamport_timestamp,
2620 line_mode,
2621 cursor_shape,
2622 } => {
2623 if let Some(set) = self.remote_selections.get(&lamport_timestamp.replica_id)
2624 && set.lamport_timestamp > lamport_timestamp
2625 {
2626 return;
2627 }
2628
2629 self.remote_selections.insert(
2630 lamport_timestamp.replica_id,
2631 SelectionSet {
2632 selections,
2633 lamport_timestamp,
2634 line_mode,
2635 cursor_shape,
2636 },
2637 );
2638 self.text.lamport_clock.observe(lamport_timestamp);
2639 self.non_text_state_update_count += 1;
2640 }
2641 Operation::UpdateCompletionTriggers {
2642 triggers,
2643 lamport_timestamp,
2644 server_id,
2645 } => {
2646 if triggers.is_empty() {
2647 self.completion_triggers_per_language_server
2648 .remove(&server_id);
2649 self.completion_triggers = self
2650 .completion_triggers_per_language_server
2651 .values()
2652 .flat_map(|triggers| triggers.iter().cloned())
2653 .collect();
2654 } else {
2655 self.completion_triggers_per_language_server
2656 .insert(server_id, triggers.iter().cloned().collect());
2657 self.completion_triggers.extend(triggers);
2658 }
2659 self.text.lamport_clock.observe(lamport_timestamp);
2660 }
2661 Operation::UpdateLineEnding {
2662 line_ending,
2663 lamport_timestamp,
2664 } => {
2665 self.text.set_line_ending(line_ending);
2666 self.text.lamport_clock.observe(lamport_timestamp);
2667 }
2668 }
2669 }
2670
2671 fn apply_diagnostic_update(
2672 &mut self,
2673 server_id: LanguageServerId,
2674 diagnostics: DiagnosticSet,
2675 lamport_timestamp: clock::Lamport,
2676 cx: &mut Context<Self>,
2677 ) {
2678 if lamport_timestamp > self.diagnostics_timestamp {
2679 let ix = self.diagnostics.binary_search_by_key(&server_id, |e| e.0);
2680 if diagnostics.is_empty() {
2681 if let Ok(ix) = ix {
2682 self.diagnostics.remove(ix);
2683 }
2684 } else {
2685 match ix {
2686 Err(ix) => self.diagnostics.insert(ix, (server_id, diagnostics)),
2687 Ok(ix) => self.diagnostics[ix].1 = diagnostics,
2688 };
2689 }
2690 self.diagnostics_timestamp = lamport_timestamp;
2691 self.non_text_state_update_count += 1;
2692 self.text.lamport_clock.observe(lamport_timestamp);
2693 cx.notify();
2694 cx.emit(BufferEvent::DiagnosticsUpdated);
2695 }
2696 }
2697
2698 fn send_operation(&mut self, operation: Operation, is_local: bool, cx: &mut Context<Self>) {
2699 self.was_changed();
2700 cx.emit(BufferEvent::Operation {
2701 operation,
2702 is_local,
2703 });
2704 }
2705
2706 /// Removes the selections for a given peer.
2707 pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut Context<Self>) {
2708 self.remote_selections.remove(&replica_id);
2709 cx.notify();
2710 }
2711
2712 /// Undoes the most recent transaction.
2713 pub fn undo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
2714 let was_dirty = self.is_dirty();
2715 let old_version = self.version.clone();
2716
2717 if let Some((transaction_id, operation)) = self.text.undo() {
2718 self.send_operation(Operation::Buffer(operation), true, cx);
2719 self.did_edit(&old_version, was_dirty, cx);
2720 Some(transaction_id)
2721 } else {
2722 None
2723 }
2724 }
2725
2726 /// Manually undoes a specific transaction in the buffer's undo history.
2727 pub fn undo_transaction(
2728 &mut self,
2729 transaction_id: TransactionId,
2730 cx: &mut Context<Self>,
2731 ) -> bool {
2732 let was_dirty = self.is_dirty();
2733 let old_version = self.version.clone();
2734 if let Some(operation) = self.text.undo_transaction(transaction_id) {
2735 self.send_operation(Operation::Buffer(operation), true, cx);
2736 self.did_edit(&old_version, was_dirty, cx);
2737 true
2738 } else {
2739 false
2740 }
2741 }
2742
2743 /// Manually undoes all changes after a given transaction in the buffer's undo history.
2744 pub fn undo_to_transaction(
2745 &mut self,
2746 transaction_id: TransactionId,
2747 cx: &mut Context<Self>,
2748 ) -> bool {
2749 let was_dirty = self.is_dirty();
2750 let old_version = self.version.clone();
2751
2752 let operations = self.text.undo_to_transaction(transaction_id);
2753 let undone = !operations.is_empty();
2754 for operation in operations {
2755 self.send_operation(Operation::Buffer(operation), true, cx);
2756 }
2757 if undone {
2758 self.did_edit(&old_version, was_dirty, cx)
2759 }
2760 undone
2761 }
2762
2763 pub fn undo_operations(&mut self, counts: HashMap<Lamport, u32>, cx: &mut Context<Buffer>) {
2764 let was_dirty = self.is_dirty();
2765 let operation = self.text.undo_operations(counts);
2766 let old_version = self.version.clone();
2767 self.send_operation(Operation::Buffer(operation), true, cx);
2768 self.did_edit(&old_version, was_dirty, cx);
2769 }
2770
2771 /// Manually redoes a specific transaction in the buffer's redo history.
2772 pub fn redo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
2773 let was_dirty = self.is_dirty();
2774 let old_version = self.version.clone();
2775
2776 if let Some((transaction_id, operation)) = self.text.redo() {
2777 self.send_operation(Operation::Buffer(operation), true, cx);
2778 self.did_edit(&old_version, was_dirty, cx);
2779 Some(transaction_id)
2780 } else {
2781 None
2782 }
2783 }
2784
2785 /// Manually undoes all changes until a given transaction in the buffer's redo history.
2786 pub fn redo_to_transaction(
2787 &mut self,
2788 transaction_id: TransactionId,
2789 cx: &mut Context<Self>,
2790 ) -> bool {
2791 let was_dirty = self.is_dirty();
2792 let old_version = self.version.clone();
2793
2794 let operations = self.text.redo_to_transaction(transaction_id);
2795 let redone = !operations.is_empty();
2796 for operation in operations {
2797 self.send_operation(Operation::Buffer(operation), true, cx);
2798 }
2799 if redone {
2800 self.did_edit(&old_version, was_dirty, cx)
2801 }
2802 redone
2803 }
2804
2805 /// Override current completion triggers with the user-provided completion triggers.
2806 pub fn set_completion_triggers(
2807 &mut self,
2808 server_id: LanguageServerId,
2809 triggers: BTreeSet<String>,
2810 cx: &mut Context<Self>,
2811 ) {
2812 self.completion_triggers_timestamp = self.text.lamport_clock.tick();
2813 if triggers.is_empty() {
2814 self.completion_triggers_per_language_server
2815 .remove(&server_id);
2816 self.completion_triggers = self
2817 .completion_triggers_per_language_server
2818 .values()
2819 .flat_map(|triggers| triggers.iter().cloned())
2820 .collect();
2821 } else {
2822 self.completion_triggers_per_language_server
2823 .insert(server_id, triggers.clone());
2824 self.completion_triggers.extend(triggers.iter().cloned());
2825 }
2826 self.send_operation(
2827 Operation::UpdateCompletionTriggers {
2828 triggers: triggers.into_iter().collect(),
2829 lamport_timestamp: self.completion_triggers_timestamp,
2830 server_id,
2831 },
2832 true,
2833 cx,
2834 );
2835 cx.notify();
2836 }
2837
2838 /// Returns a list of strings which trigger a completion menu for this language.
2839 /// Usually this is driven by LSP server which returns a list of trigger characters for completions.
2840 pub fn completion_triggers(&self) -> &BTreeSet<String> {
2841 &self.completion_triggers
2842 }
2843
2844 /// Call this directly after performing edits to prevent the preview tab
2845 /// from being dismissed by those edits. It causes `should_dismiss_preview`
2846 /// to return false until there are additional edits.
2847 pub fn refresh_preview(&mut self) {
2848 self.preview_version = self.version.clone();
2849 }
2850
2851 /// Whether we should preserve the preview status of a tab containing this buffer.
2852 pub fn preserve_preview(&self) -> bool {
2853 !self.has_edits_since(&self.preview_version)
2854 }
2855}
2856
2857#[doc(hidden)]
2858#[cfg(any(test, feature = "test-support"))]
2859impl Buffer {
2860 pub fn edit_via_marked_text(
2861 &mut self,
2862 marked_string: &str,
2863 autoindent_mode: Option<AutoindentMode>,
2864 cx: &mut Context<Self>,
2865 ) {
2866 let edits = self.edits_for_marked_text(marked_string);
2867 self.edit(edits, autoindent_mode, cx);
2868 }
2869
2870 pub fn set_group_interval(&mut self, group_interval: Duration) {
2871 self.text.set_group_interval(group_interval);
2872 }
2873
2874 pub fn randomly_edit<T>(&mut self, rng: &mut T, old_range_count: usize, cx: &mut Context<Self>)
2875 where
2876 T: rand::Rng,
2877 {
2878 let mut edits: Vec<(Range<usize>, String)> = Vec::new();
2879 let mut last_end = None;
2880 for _ in 0..old_range_count {
2881 if last_end.is_some_and(|last_end| last_end >= self.len()) {
2882 break;
2883 }
2884
2885 let new_start = last_end.map_or(0, |last_end| last_end + 1);
2886 let mut range = self.random_byte_range(new_start, rng);
2887 if rng.random_bool(0.2) {
2888 mem::swap(&mut range.start, &mut range.end);
2889 }
2890 last_end = Some(range.end);
2891
2892 let new_text_len = rng.random_range(0..10);
2893 let mut new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
2894 new_text = new_text.to_uppercase();
2895
2896 edits.push((range, new_text));
2897 }
2898 log::info!("mutating buffer {} with {:?}", self.replica_id(), edits);
2899 self.edit(edits, None, cx);
2900 }
2901
2902 pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut Context<Self>) {
2903 let was_dirty = self.is_dirty();
2904 let old_version = self.version.clone();
2905
2906 let ops = self.text.randomly_undo_redo(rng);
2907 if !ops.is_empty() {
2908 for op in ops {
2909 self.send_operation(Operation::Buffer(op), true, cx);
2910 self.did_edit(&old_version, was_dirty, cx);
2911 }
2912 }
2913 }
2914}
2915
2916impl EventEmitter<BufferEvent> for Buffer {}
2917
2918impl Deref for Buffer {
2919 type Target = TextBuffer;
2920
2921 fn deref(&self) -> &Self::Target {
2922 &self.text
2923 }
2924}
2925
2926impl BufferSnapshot {
2927 /// Returns [`IndentSize`] for a given line that respects user settings and
2928 /// language preferences.
2929 pub fn indent_size_for_line(&self, row: u32) -> IndentSize {
2930 indent_size_for_line(self, row)
2931 }
2932
2933 /// Returns [`IndentSize`] for a given position that respects user settings
2934 /// and language preferences.
2935 pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &App) -> IndentSize {
2936 let settings = language_settings(
2937 self.language_at(position).map(|l| l.name()),
2938 self.file(),
2939 cx,
2940 );
2941 if settings.hard_tabs {
2942 IndentSize::tab()
2943 } else {
2944 IndentSize::spaces(settings.tab_size.get())
2945 }
2946 }
2947
2948 /// Retrieve the suggested indent size for all of the given rows. The unit of indentation
2949 /// is passed in as `single_indent_size`.
2950 pub fn suggested_indents(
2951 &self,
2952 rows: impl Iterator<Item = u32>,
2953 single_indent_size: IndentSize,
2954 ) -> BTreeMap<u32, IndentSize> {
2955 let mut result = BTreeMap::new();
2956
2957 for row_range in contiguous_ranges(rows, 10) {
2958 let suggestions = match self.suggest_autoindents(row_range.clone()) {
2959 Some(suggestions) => suggestions,
2960 _ => break,
2961 };
2962
2963 for (row, suggestion) in row_range.zip(suggestions) {
2964 let indent_size = if let Some(suggestion) = suggestion {
2965 result
2966 .get(&suggestion.basis_row)
2967 .copied()
2968 .unwrap_or_else(|| self.indent_size_for_line(suggestion.basis_row))
2969 .with_delta(suggestion.delta, single_indent_size)
2970 } else {
2971 self.indent_size_for_line(row)
2972 };
2973
2974 result.insert(row, indent_size);
2975 }
2976 }
2977
2978 result
2979 }
2980
2981 fn suggest_autoindents(
2982 &self,
2983 row_range: Range<u32>,
2984 ) -> Option<impl Iterator<Item = Option<IndentSuggestion>> + '_> {
2985 let config = &self.language.as_ref()?.config;
2986 let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
2987
2988 #[derive(Debug, Clone)]
2989 struct StartPosition {
2990 start: Point,
2991 suffix: SharedString,
2992 }
2993
2994 // Find the suggested indentation ranges based on the syntax tree.
2995 let start = Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0);
2996 let end = Point::new(row_range.end, 0);
2997 let range = (start..end).to_offset(&self.text);
2998 let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2999 Some(&grammar.indents_config.as_ref()?.query)
3000 });
3001 let indent_configs = matches
3002 .grammars()
3003 .iter()
3004 .map(|grammar| grammar.indents_config.as_ref().unwrap())
3005 .collect::<Vec<_>>();
3006
3007 let mut indent_ranges = Vec::<Range<Point>>::new();
3008 let mut start_positions = Vec::<StartPosition>::new();
3009 let mut outdent_positions = Vec::<Point>::new();
3010 while let Some(mat) = matches.peek() {
3011 let mut start: Option<Point> = None;
3012 let mut end: Option<Point> = None;
3013
3014 let config = indent_configs[mat.grammar_index];
3015 for capture in mat.captures {
3016 if capture.index == config.indent_capture_ix {
3017 start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
3018 end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
3019 } else if Some(capture.index) == config.start_capture_ix {
3020 start = Some(Point::from_ts_point(capture.node.end_position()));
3021 } else if Some(capture.index) == config.end_capture_ix {
3022 end = Some(Point::from_ts_point(capture.node.start_position()));
3023 } else if Some(capture.index) == config.outdent_capture_ix {
3024 outdent_positions.push(Point::from_ts_point(capture.node.start_position()));
3025 } else if let Some(suffix) = config.suffixed_start_captures.get(&capture.index) {
3026 start_positions.push(StartPosition {
3027 start: Point::from_ts_point(capture.node.start_position()),
3028 suffix: suffix.clone(),
3029 });
3030 }
3031 }
3032
3033 matches.advance();
3034 if let Some((start, end)) = start.zip(end) {
3035 if start.row == end.row {
3036 continue;
3037 }
3038 let range = start..end;
3039 match indent_ranges.binary_search_by_key(&range.start, |r| r.start) {
3040 Err(ix) => indent_ranges.insert(ix, range),
3041 Ok(ix) => {
3042 let prev_range = &mut indent_ranges[ix];
3043 prev_range.end = prev_range.end.max(range.end);
3044 }
3045 }
3046 }
3047 }
3048
3049 let mut error_ranges = Vec::<Range<Point>>::new();
3050 let mut matches = self
3051 .syntax
3052 .matches(range, &self.text, |grammar| grammar.error_query.as_ref());
3053 while let Some(mat) = matches.peek() {
3054 let node = mat.captures[0].node;
3055 let start = Point::from_ts_point(node.start_position());
3056 let end = Point::from_ts_point(node.end_position());
3057 let range = start..end;
3058 let ix = match error_ranges.binary_search_by_key(&range.start, |r| r.start) {
3059 Ok(ix) | Err(ix) => ix,
3060 };
3061 let mut end_ix = ix;
3062 while let Some(existing_range) = error_ranges.get(end_ix) {
3063 if existing_range.end < end {
3064 end_ix += 1;
3065 } else {
3066 break;
3067 }
3068 }
3069 error_ranges.splice(ix..end_ix, [range]);
3070 matches.advance();
3071 }
3072
3073 outdent_positions.sort();
3074 for outdent_position in outdent_positions {
3075 // find the innermost indent range containing this outdent_position
3076 // set its end to the outdent position
3077 if let Some(range_to_truncate) = indent_ranges
3078 .iter_mut()
3079 .filter(|indent_range| indent_range.contains(&outdent_position))
3080 .next_back()
3081 {
3082 range_to_truncate.end = outdent_position;
3083 }
3084 }
3085
3086 start_positions.sort_by_key(|b| b.start);
3087
3088 // Find the suggested indentation increases and decreased based on regexes.
3089 let mut regex_outdent_map = HashMap::default();
3090 let mut last_seen_suffix: HashMap<String, Vec<Point>> = HashMap::default();
3091 let mut start_positions_iter = start_positions.iter().peekable();
3092
3093 let mut indent_change_rows = Vec::<(u32, Ordering)>::new();
3094 self.for_each_line(
3095 Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0)
3096 ..Point::new(row_range.end, 0),
3097 |row, line| {
3098 if config
3099 .decrease_indent_pattern
3100 .as_ref()
3101 .is_some_and(|regex| regex.is_match(line))
3102 {
3103 indent_change_rows.push((row, Ordering::Less));
3104 }
3105 if config
3106 .increase_indent_pattern
3107 .as_ref()
3108 .is_some_and(|regex| regex.is_match(line))
3109 {
3110 indent_change_rows.push((row + 1, Ordering::Greater));
3111 }
3112 while let Some(pos) = start_positions_iter.peek() {
3113 if pos.start.row < row {
3114 let pos = start_positions_iter.next().unwrap();
3115 last_seen_suffix
3116 .entry(pos.suffix.to_string())
3117 .or_default()
3118 .push(pos.start);
3119 } else {
3120 break;
3121 }
3122 }
3123 for rule in &config.decrease_indent_patterns {
3124 if rule.pattern.as_ref().is_some_and(|r| r.is_match(line)) {
3125 let row_start_column = self.indent_size_for_line(row).len;
3126 let basis_row = rule
3127 .valid_after
3128 .iter()
3129 .filter_map(|valid_suffix| last_seen_suffix.get(valid_suffix))
3130 .flatten()
3131 .filter(|start_point| start_point.column <= row_start_column)
3132 .max_by_key(|start_point| start_point.row);
3133 if let Some(outdent_to_row) = basis_row {
3134 regex_outdent_map.insert(row, outdent_to_row.row);
3135 }
3136 break;
3137 }
3138 }
3139 },
3140 );
3141
3142 let mut indent_changes = indent_change_rows.into_iter().peekable();
3143 let mut prev_row = if config.auto_indent_using_last_non_empty_line {
3144 prev_non_blank_row.unwrap_or(0)
3145 } else {
3146 row_range.start.saturating_sub(1)
3147 };
3148
3149 let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len);
3150 Some(row_range.map(move |row| {
3151 let row_start = Point::new(row, self.indent_size_for_line(row).len);
3152
3153 let mut indent_from_prev_row = false;
3154 let mut outdent_from_prev_row = false;
3155 let mut outdent_to_row = u32::MAX;
3156 let mut from_regex = false;
3157
3158 while let Some((indent_row, delta)) = indent_changes.peek() {
3159 match indent_row.cmp(&row) {
3160 Ordering::Equal => match delta {
3161 Ordering::Less => {
3162 from_regex = true;
3163 outdent_from_prev_row = true
3164 }
3165 Ordering::Greater => {
3166 indent_from_prev_row = true;
3167 from_regex = true
3168 }
3169 _ => {}
3170 },
3171
3172 Ordering::Greater => break,
3173 Ordering::Less => {}
3174 }
3175
3176 indent_changes.next();
3177 }
3178
3179 for range in &indent_ranges {
3180 if range.start.row >= row {
3181 break;
3182 }
3183 if range.start.row == prev_row && range.end > row_start {
3184 indent_from_prev_row = true;
3185 }
3186 if range.end > prev_row_start && range.end <= row_start {
3187 outdent_to_row = outdent_to_row.min(range.start.row);
3188 }
3189 }
3190
3191 if let Some(basis_row) = regex_outdent_map.get(&row) {
3192 indent_from_prev_row = false;
3193 outdent_to_row = *basis_row;
3194 from_regex = true;
3195 }
3196
3197 let within_error = error_ranges
3198 .iter()
3199 .any(|e| e.start.row < row && e.end > row_start);
3200
3201 let suggestion = if outdent_to_row == prev_row
3202 || (outdent_from_prev_row && indent_from_prev_row)
3203 {
3204 Some(IndentSuggestion {
3205 basis_row: prev_row,
3206 delta: Ordering::Equal,
3207 within_error: within_error && !from_regex,
3208 })
3209 } else if indent_from_prev_row {
3210 Some(IndentSuggestion {
3211 basis_row: prev_row,
3212 delta: Ordering::Greater,
3213 within_error: within_error && !from_regex,
3214 })
3215 } else if outdent_to_row < prev_row {
3216 Some(IndentSuggestion {
3217 basis_row: outdent_to_row,
3218 delta: Ordering::Equal,
3219 within_error: within_error && !from_regex,
3220 })
3221 } else if outdent_from_prev_row {
3222 Some(IndentSuggestion {
3223 basis_row: prev_row,
3224 delta: Ordering::Less,
3225 within_error: within_error && !from_regex,
3226 })
3227 } else if config.auto_indent_using_last_non_empty_line || !self.is_line_blank(prev_row)
3228 {
3229 Some(IndentSuggestion {
3230 basis_row: prev_row,
3231 delta: Ordering::Equal,
3232 within_error: within_error && !from_regex,
3233 })
3234 } else {
3235 None
3236 };
3237
3238 prev_row = row;
3239 prev_row_start = row_start;
3240 suggestion
3241 }))
3242 }
3243
3244 fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
3245 while row > 0 {
3246 row -= 1;
3247 if !self.is_line_blank(row) {
3248 return Some(row);
3249 }
3250 }
3251 None
3252 }
3253
3254 fn get_highlights(&self, range: Range<usize>) -> (SyntaxMapCaptures<'_>, Vec<HighlightMap>) {
3255 let captures = self.syntax.captures(range, &self.text, |grammar| {
3256 grammar.highlights_query.as_ref()
3257 });
3258 let highlight_maps = captures
3259 .grammars()
3260 .iter()
3261 .map(|grammar| grammar.highlight_map())
3262 .collect();
3263 (captures, highlight_maps)
3264 }
3265
3266 /// Iterates over chunks of text in the given range of the buffer. Text is chunked
3267 /// in an arbitrary way due to being stored in a [`Rope`](text::Rope). The text is also
3268 /// returned in chunks where each chunk has a single syntax highlighting style and
3269 /// diagnostic status.
3270 pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> BufferChunks<'_> {
3271 let range = range.start.to_offset(self)..range.end.to_offset(self);
3272
3273 let mut syntax = None;
3274 if language_aware {
3275 syntax = Some(self.get_highlights(range.clone()));
3276 }
3277 // We want to look at diagnostic spans only when iterating over language-annotated chunks.
3278 let diagnostics = language_aware;
3279 BufferChunks::new(self.text.as_rope(), range, syntax, diagnostics, Some(self))
3280 }
3281
3282 pub fn highlighted_text_for_range<T: ToOffset>(
3283 &self,
3284 range: Range<T>,
3285 override_style: Option<HighlightStyle>,
3286 syntax_theme: &SyntaxTheme,
3287 ) -> HighlightedText {
3288 HighlightedText::from_buffer_range(
3289 range,
3290 &self.text,
3291 &self.syntax,
3292 override_style,
3293 syntax_theme,
3294 )
3295 }
3296
3297 /// Invokes the given callback for each line of text in the given range of the buffer.
3298 /// Uses callback to avoid allocating a string for each line.
3299 fn for_each_line(&self, range: Range<Point>, mut callback: impl FnMut(u32, &str)) {
3300 let mut line = String::new();
3301 let mut row = range.start.row;
3302 for chunk in self
3303 .as_rope()
3304 .chunks_in_range(range.to_offset(self))
3305 .chain(["\n"])
3306 {
3307 for (newline_ix, text) in chunk.split('\n').enumerate() {
3308 if newline_ix > 0 {
3309 callback(row, &line);
3310 row += 1;
3311 line.clear();
3312 }
3313 line.push_str(text);
3314 }
3315 }
3316 }
3317
3318 /// Iterates over every [`SyntaxLayer`] in the buffer.
3319 pub fn syntax_layers(&self) -> impl Iterator<Item = SyntaxLayer<'_>> + '_ {
3320 self.syntax
3321 .layers_for_range(0..self.len(), &self.text, true)
3322 }
3323
3324 pub fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer<'_>> {
3325 let offset = position.to_offset(self);
3326 self.syntax
3327 .layers_for_range(offset..offset, &self.text, false)
3328 .filter(|l| l.node().end_byte() > offset)
3329 .last()
3330 }
3331
3332 pub fn smallest_syntax_layer_containing<D: ToOffset>(
3333 &self,
3334 range: Range<D>,
3335 ) -> Option<SyntaxLayer<'_>> {
3336 let range = range.to_offset(self);
3337 self.syntax
3338 .layers_for_range(range, &self.text, false)
3339 .max_by(|a, b| {
3340 if a.depth != b.depth {
3341 a.depth.cmp(&b.depth)
3342 } else if a.offset.0 != b.offset.0 {
3343 a.offset.0.cmp(&b.offset.0)
3344 } else {
3345 a.node().end_byte().cmp(&b.node().end_byte()).reverse()
3346 }
3347 })
3348 }
3349
3350 /// Returns the main [`Language`].
3351 pub fn language(&self) -> Option<&Arc<Language>> {
3352 self.language.as_ref()
3353 }
3354
3355 /// Returns the [`Language`] at the given location.
3356 pub fn language_at<D: ToOffset>(&self, position: D) -> Option<&Arc<Language>> {
3357 self.syntax_layer_at(position)
3358 .map(|info| info.language)
3359 .or(self.language.as_ref())
3360 }
3361
3362 /// Returns the settings for the language at the given location.
3363 pub fn settings_at<'a, D: ToOffset>(
3364 &'a self,
3365 position: D,
3366 cx: &'a App,
3367 ) -> Cow<'a, LanguageSettings> {
3368 language_settings(
3369 self.language_at(position).map(|l| l.name()),
3370 self.file.as_ref(),
3371 cx,
3372 )
3373 }
3374
3375 pub fn char_classifier_at<T: ToOffset>(&self, point: T) -> CharClassifier {
3376 CharClassifier::new(self.language_scope_at(point))
3377 }
3378
3379 /// Returns the [`LanguageScope`] at the given location.
3380 pub fn language_scope_at<D: ToOffset>(&self, position: D) -> Option<LanguageScope> {
3381 let offset = position.to_offset(self);
3382 let mut scope = None;
3383 let mut smallest_range_and_depth: Option<(Range<usize>, usize)> = None;
3384
3385 // Use the layer that has the smallest node intersecting the given point.
3386 for layer in self
3387 .syntax
3388 .layers_for_range(offset..offset, &self.text, false)
3389 {
3390 let mut cursor = layer.node().walk();
3391
3392 let mut range = None;
3393 loop {
3394 let child_range = cursor.node().byte_range();
3395 if !child_range.contains(&offset) {
3396 break;
3397 }
3398
3399 range = Some(child_range);
3400 if cursor.goto_first_child_for_byte(offset).is_none() {
3401 break;
3402 }
3403 }
3404
3405 if let Some(range) = range
3406 && smallest_range_and_depth.as_ref().is_none_or(
3407 |(smallest_range, smallest_range_depth)| {
3408 if layer.depth > *smallest_range_depth {
3409 true
3410 } else if layer.depth == *smallest_range_depth {
3411 range.len() < smallest_range.len()
3412 } else {
3413 false
3414 }
3415 },
3416 )
3417 {
3418 smallest_range_and_depth = Some((range, layer.depth));
3419 scope = Some(LanguageScope {
3420 language: layer.language.clone(),
3421 override_id: layer.override_id(offset, &self.text),
3422 });
3423 }
3424 }
3425
3426 scope.or_else(|| {
3427 self.language.clone().map(|language| LanguageScope {
3428 language,
3429 override_id: None,
3430 })
3431 })
3432 }
3433
3434 /// Returns a tuple of the range and character kind of the word
3435 /// surrounding the given position.
3436 pub fn surrounding_word<T: ToOffset>(
3437 &self,
3438 start: T,
3439 for_completion: bool,
3440 ) -> (Range<usize>, Option<CharKind>) {
3441 let mut start = start.to_offset(self);
3442 let mut end = start;
3443 let mut next_chars = self.chars_at(start).take(128).peekable();
3444 let mut prev_chars = self.reversed_chars_at(start).take(128).peekable();
3445
3446 let classifier = self
3447 .char_classifier_at(start)
3448 .for_completion(for_completion);
3449 let word_kind = cmp::max(
3450 prev_chars.peek().copied().map(|c| classifier.kind(c)),
3451 next_chars.peek().copied().map(|c| classifier.kind(c)),
3452 );
3453
3454 for ch in prev_chars {
3455 if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
3456 start -= ch.len_utf8();
3457 } else {
3458 break;
3459 }
3460 }
3461
3462 for ch in next_chars {
3463 if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
3464 end += ch.len_utf8();
3465 } else {
3466 break;
3467 }
3468 }
3469
3470 (start..end, word_kind)
3471 }
3472
3473 /// Moves the TreeCursor to the smallest descendant or ancestor syntax node enclosing the given
3474 /// range. When `require_larger` is true, the node found must be larger than the query range.
3475 ///
3476 /// Returns true if a node was found, and false otherwise. In the `false` case the cursor will
3477 /// be moved to the root of the tree.
3478 fn goto_node_enclosing_range(
3479 cursor: &mut tree_sitter::TreeCursor,
3480 query_range: &Range<usize>,
3481 require_larger: bool,
3482 ) -> bool {
3483 let mut ascending = false;
3484 loop {
3485 let mut range = cursor.node().byte_range();
3486 if query_range.is_empty() {
3487 // When the query range is empty and the current node starts after it, move to the
3488 // previous sibling to find the node the containing node.
3489 if range.start > query_range.start {
3490 cursor.goto_previous_sibling();
3491 range = cursor.node().byte_range();
3492 }
3493 } else {
3494 // When the query range is non-empty and the current node ends exactly at the start,
3495 // move to the next sibling to find a node that extends beyond the start.
3496 if range.end == query_range.start {
3497 cursor.goto_next_sibling();
3498 range = cursor.node().byte_range();
3499 }
3500 }
3501
3502 let encloses = range.contains_inclusive(query_range)
3503 && (!require_larger || range.len() > query_range.len());
3504 if !encloses {
3505 ascending = true;
3506 if !cursor.goto_parent() {
3507 return false;
3508 }
3509 continue;
3510 } else if ascending {
3511 return true;
3512 }
3513
3514 // Descend into the current node.
3515 if cursor
3516 .goto_first_child_for_byte(query_range.start)
3517 .is_none()
3518 {
3519 return true;
3520 }
3521 }
3522 }
3523
3524 pub fn syntax_ancestor<'a, T: ToOffset>(
3525 &'a self,
3526 range: Range<T>,
3527 ) -> Option<tree_sitter::Node<'a>> {
3528 let range = range.start.to_offset(self)..range.end.to_offset(self);
3529 let mut result: Option<tree_sitter::Node<'a>> = None;
3530 for layer in self
3531 .syntax
3532 .layers_for_range(range.clone(), &self.text, true)
3533 {
3534 let mut cursor = layer.node().walk();
3535
3536 // Find the node that both contains the range and is larger than it.
3537 if !Self::goto_node_enclosing_range(&mut cursor, &range, true) {
3538 continue;
3539 }
3540
3541 let left_node = cursor.node();
3542 let mut layer_result = left_node;
3543
3544 // For an empty range, try to find another node immediately to the right of the range.
3545 if left_node.end_byte() == range.start {
3546 let mut right_node = None;
3547 while !cursor.goto_next_sibling() {
3548 if !cursor.goto_parent() {
3549 break;
3550 }
3551 }
3552
3553 while cursor.node().start_byte() == range.start {
3554 right_node = Some(cursor.node());
3555 if !cursor.goto_first_child() {
3556 break;
3557 }
3558 }
3559
3560 // If there is a candidate node on both sides of the (empty) range, then
3561 // decide between the two by favoring a named node over an anonymous token.
3562 // If both nodes are the same in that regard, favor the right one.
3563 if let Some(right_node) = right_node
3564 && (right_node.is_named() || !left_node.is_named())
3565 {
3566 layer_result = right_node;
3567 }
3568 }
3569
3570 if let Some(previous_result) = &result
3571 && previous_result.byte_range().len() < layer_result.byte_range().len()
3572 {
3573 continue;
3574 }
3575 result = Some(layer_result);
3576 }
3577
3578 result
3579 }
3580
3581 /// Find the previous sibling syntax node at the given range.
3582 ///
3583 /// This function locates the syntax node that precedes the node containing
3584 /// the given range. It searches hierarchically by:
3585 /// 1. Finding the node that contains the given range
3586 /// 2. Looking for the previous sibling at the same tree level
3587 /// 3. If no sibling is found, moving up to parent levels and searching for siblings
3588 ///
3589 /// Returns `None` if there is no previous sibling at any ancestor level.
3590 pub fn syntax_prev_sibling<'a, T: ToOffset>(
3591 &'a self,
3592 range: Range<T>,
3593 ) -> Option<tree_sitter::Node<'a>> {
3594 let range = range.start.to_offset(self)..range.end.to_offset(self);
3595 let mut result: Option<tree_sitter::Node<'a>> = None;
3596
3597 for layer in self
3598 .syntax
3599 .layers_for_range(range.clone(), &self.text, true)
3600 {
3601 let mut cursor = layer.node().walk();
3602
3603 // Find the node that contains the range
3604 if !Self::goto_node_enclosing_range(&mut cursor, &range, false) {
3605 continue;
3606 }
3607
3608 // Look for the previous sibling, moving up ancestor levels if needed
3609 loop {
3610 if cursor.goto_previous_sibling() {
3611 let layer_result = cursor.node();
3612
3613 if let Some(previous_result) = &result {
3614 if previous_result.byte_range().end < layer_result.byte_range().end {
3615 continue;
3616 }
3617 }
3618 result = Some(layer_result);
3619 break;
3620 }
3621
3622 // No sibling found at this level, try moving up to parent
3623 if !cursor.goto_parent() {
3624 break;
3625 }
3626 }
3627 }
3628
3629 result
3630 }
3631
3632 /// Find the next sibling syntax node at the given range.
3633 ///
3634 /// This function locates the syntax node that follows the node containing
3635 /// the given range. It searches hierarchically by:
3636 /// 1. Finding the node that contains the given range
3637 /// 2. Looking for the next sibling at the same tree level
3638 /// 3. If no sibling is found, moving up to parent levels and searching for siblings
3639 ///
3640 /// Returns `None` if there is no next sibling at any ancestor level.
3641 pub fn syntax_next_sibling<'a, T: ToOffset>(
3642 &'a self,
3643 range: Range<T>,
3644 ) -> Option<tree_sitter::Node<'a>> {
3645 let range = range.start.to_offset(self)..range.end.to_offset(self);
3646 let mut result: Option<tree_sitter::Node<'a>> = None;
3647
3648 for layer in self
3649 .syntax
3650 .layers_for_range(range.clone(), &self.text, true)
3651 {
3652 let mut cursor = layer.node().walk();
3653
3654 // Find the node that contains the range
3655 if !Self::goto_node_enclosing_range(&mut cursor, &range, false) {
3656 continue;
3657 }
3658
3659 // Look for the next sibling, moving up ancestor levels if needed
3660 loop {
3661 if cursor.goto_next_sibling() {
3662 let layer_result = cursor.node();
3663
3664 if let Some(previous_result) = &result {
3665 if previous_result.byte_range().start > layer_result.byte_range().start {
3666 continue;
3667 }
3668 }
3669 result = Some(layer_result);
3670 break;
3671 }
3672
3673 // No sibling found at this level, try moving up to parent
3674 if !cursor.goto_parent() {
3675 break;
3676 }
3677 }
3678 }
3679
3680 result
3681 }
3682
3683 /// Returns the root syntax node within the given row
3684 pub fn syntax_root_ancestor(&self, position: Anchor) -> Option<tree_sitter::Node<'_>> {
3685 let start_offset = position.to_offset(self);
3686
3687 let row = self.summary_for_anchor::<text::PointUtf16>(&position).row as usize;
3688
3689 let layer = self
3690 .syntax
3691 .layers_for_range(start_offset..start_offset, &self.text, true)
3692 .next()?;
3693
3694 let mut cursor = layer.node().walk();
3695
3696 // Descend to the first leaf that touches the start of the range.
3697 while cursor.goto_first_child_for_byte(start_offset).is_some() {
3698 if cursor.node().end_byte() == start_offset {
3699 cursor.goto_next_sibling();
3700 }
3701 }
3702
3703 // Ascend to the root node within the same row.
3704 while cursor.goto_parent() {
3705 if cursor.node().start_position().row != row {
3706 break;
3707 }
3708 }
3709
3710 Some(cursor.node())
3711 }
3712
3713 /// Returns the outline for the buffer.
3714 ///
3715 /// This method allows passing an optional [`SyntaxTheme`] to
3716 /// syntax-highlight the returned symbols.
3717 pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Outline<Anchor> {
3718 Outline::new(self.outline_items_containing(0..self.len(), true, theme))
3719 }
3720
3721 /// Returns all the symbols that contain the given position.
3722 ///
3723 /// This method allows passing an optional [`SyntaxTheme`] to
3724 /// syntax-highlight the returned symbols.
3725 pub fn symbols_containing<T: ToOffset>(
3726 &self,
3727 position: T,
3728 theme: Option<&SyntaxTheme>,
3729 ) -> Vec<OutlineItem<Anchor>> {
3730 let position = position.to_offset(self);
3731 let mut items = self.outline_items_containing(
3732 position.saturating_sub(1)..self.len().min(position + 1),
3733 false,
3734 theme,
3735 );
3736 let mut prev_depth = None;
3737 items.retain(|item| {
3738 let result = prev_depth.is_none_or(|prev_depth| item.depth > prev_depth);
3739 prev_depth = Some(item.depth);
3740 result
3741 });
3742 items
3743 }
3744
3745 pub fn outline_range_containing<T: ToOffset>(&self, range: Range<T>) -> Option<Range<Point>> {
3746 let range = range.to_offset(self);
3747 let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
3748 grammar.outline_config.as_ref().map(|c| &c.query)
3749 });
3750 let configs = matches
3751 .grammars()
3752 .iter()
3753 .map(|g| g.outline_config.as_ref().unwrap())
3754 .collect::<Vec<_>>();
3755
3756 while let Some(mat) = matches.peek() {
3757 let config = &configs[mat.grammar_index];
3758 let containing_item_node = maybe!({
3759 let item_node = mat.captures.iter().find_map(|cap| {
3760 if cap.index == config.item_capture_ix {
3761 Some(cap.node)
3762 } else {
3763 None
3764 }
3765 })?;
3766
3767 let item_byte_range = item_node.byte_range();
3768 if item_byte_range.end < range.start || item_byte_range.start > range.end {
3769 None
3770 } else {
3771 Some(item_node)
3772 }
3773 });
3774
3775 if let Some(item_node) = containing_item_node {
3776 return Some(
3777 Point::from_ts_point(item_node.start_position())
3778 ..Point::from_ts_point(item_node.end_position()),
3779 );
3780 }
3781
3782 matches.advance();
3783 }
3784 None
3785 }
3786
3787 pub fn outline_items_containing<T: ToOffset>(
3788 &self,
3789 range: Range<T>,
3790 include_extra_context: bool,
3791 theme: Option<&SyntaxTheme>,
3792 ) -> Vec<OutlineItem<Anchor>> {
3793 let range = range.to_offset(self);
3794 let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
3795 grammar.outline_config.as_ref().map(|c| &c.query)
3796 });
3797
3798 let mut items = Vec::new();
3799 let mut annotation_row_ranges: Vec<Range<u32>> = Vec::new();
3800 while let Some(mat) = matches.peek() {
3801 let config = matches.grammars()[mat.grammar_index]
3802 .outline_config
3803 .as_ref()
3804 .unwrap();
3805 if let Some(item) =
3806 self.next_outline_item(config, &mat, &range, include_extra_context, theme)
3807 {
3808 items.push(item);
3809 } else if let Some(capture) = mat
3810 .captures
3811 .iter()
3812 .find(|capture| Some(capture.index) == config.annotation_capture_ix)
3813 {
3814 let capture_range = capture.node.start_position()..capture.node.end_position();
3815 let mut capture_row_range =
3816 capture_range.start.row as u32..capture_range.end.row as u32;
3817 if capture_range.end.row > capture_range.start.row && capture_range.end.column == 0
3818 {
3819 capture_row_range.end -= 1;
3820 }
3821 if let Some(last_row_range) = annotation_row_ranges.last_mut() {
3822 if last_row_range.end >= capture_row_range.start.saturating_sub(1) {
3823 last_row_range.end = capture_row_range.end;
3824 } else {
3825 annotation_row_ranges.push(capture_row_range);
3826 }
3827 } else {
3828 annotation_row_ranges.push(capture_row_range);
3829 }
3830 }
3831 matches.advance();
3832 }
3833
3834 items.sort_by_key(|item| (item.range.start, Reverse(item.range.end)));
3835
3836 // Assign depths based on containment relationships and convert to anchors.
3837 let mut item_ends_stack = Vec::<Point>::new();
3838 let mut anchor_items = Vec::new();
3839 let mut annotation_row_ranges = annotation_row_ranges.into_iter().peekable();
3840 for item in items {
3841 while let Some(last_end) = item_ends_stack.last().copied() {
3842 if last_end < item.range.end {
3843 item_ends_stack.pop();
3844 } else {
3845 break;
3846 }
3847 }
3848
3849 let mut annotation_row_range = None;
3850 while let Some(next_annotation_row_range) = annotation_row_ranges.peek() {
3851 let row_preceding_item = item.range.start.row.saturating_sub(1);
3852 if next_annotation_row_range.end < row_preceding_item {
3853 annotation_row_ranges.next();
3854 } else {
3855 if next_annotation_row_range.end == row_preceding_item {
3856 annotation_row_range = Some(next_annotation_row_range.clone());
3857 annotation_row_ranges.next();
3858 }
3859 break;
3860 }
3861 }
3862
3863 anchor_items.push(OutlineItem {
3864 depth: item_ends_stack.len(),
3865 range: self.anchor_after(item.range.start)..self.anchor_before(item.range.end),
3866 text: item.text,
3867 highlight_ranges: item.highlight_ranges,
3868 name_ranges: item.name_ranges,
3869 body_range: item.body_range.map(|body_range| {
3870 self.anchor_after(body_range.start)..self.anchor_before(body_range.end)
3871 }),
3872 annotation_range: annotation_row_range.map(|annotation_range| {
3873 self.anchor_after(Point::new(annotation_range.start, 0))
3874 ..self.anchor_before(Point::new(
3875 annotation_range.end,
3876 self.line_len(annotation_range.end),
3877 ))
3878 }),
3879 });
3880 item_ends_stack.push(item.range.end);
3881 }
3882
3883 anchor_items
3884 }
3885
3886 fn next_outline_item(
3887 &self,
3888 config: &OutlineConfig,
3889 mat: &SyntaxMapMatch,
3890 range: &Range<usize>,
3891 include_extra_context: bool,
3892 theme: Option<&SyntaxTheme>,
3893 ) -> Option<OutlineItem<Point>> {
3894 let item_node = mat.captures.iter().find_map(|cap| {
3895 if cap.index == config.item_capture_ix {
3896 Some(cap.node)
3897 } else {
3898 None
3899 }
3900 })?;
3901
3902 let item_byte_range = item_node.byte_range();
3903 if item_byte_range.end < range.start || item_byte_range.start > range.end {
3904 return None;
3905 }
3906 let item_point_range = Point::from_ts_point(item_node.start_position())
3907 ..Point::from_ts_point(item_node.end_position());
3908
3909 let mut open_point = None;
3910 let mut close_point = None;
3911 let mut buffer_ranges = Vec::new();
3912 for capture in mat.captures {
3913 let node_is_name;
3914 if capture.index == config.name_capture_ix {
3915 node_is_name = true;
3916 } else if Some(capture.index) == config.context_capture_ix
3917 || (Some(capture.index) == config.extra_context_capture_ix && include_extra_context)
3918 {
3919 node_is_name = false;
3920 } else {
3921 if Some(capture.index) == config.open_capture_ix {
3922 open_point = Some(Point::from_ts_point(capture.node.end_position()));
3923 } else if Some(capture.index) == config.close_capture_ix {
3924 close_point = Some(Point::from_ts_point(capture.node.start_position()));
3925 }
3926
3927 continue;
3928 }
3929
3930 let mut range = capture.node.start_byte()..capture.node.end_byte();
3931 let start = capture.node.start_position();
3932 if capture.node.end_position().row > start.row {
3933 range.end = range.start + self.line_len(start.row as u32) as usize - start.column;
3934 }
3935
3936 if !range.is_empty() {
3937 buffer_ranges.push((range, node_is_name));
3938 }
3939 }
3940 if buffer_ranges.is_empty() {
3941 return None;
3942 }
3943 let mut text = String::new();
3944 let mut highlight_ranges = Vec::new();
3945 let mut name_ranges = Vec::new();
3946 let mut chunks = self.chunks(
3947 buffer_ranges.first().unwrap().0.start..buffer_ranges.last().unwrap().0.end,
3948 true,
3949 );
3950 let mut last_buffer_range_end = 0;
3951
3952 for (buffer_range, is_name) in buffer_ranges {
3953 let space_added = !text.is_empty() && buffer_range.start > last_buffer_range_end;
3954 if space_added {
3955 text.push(' ');
3956 }
3957 let before_append_len = text.len();
3958 let mut offset = buffer_range.start;
3959 chunks.seek(buffer_range.clone());
3960 for mut chunk in chunks.by_ref() {
3961 if chunk.text.len() > buffer_range.end - offset {
3962 chunk.text = &chunk.text[0..(buffer_range.end - offset)];
3963 offset = buffer_range.end;
3964 } else {
3965 offset += chunk.text.len();
3966 }
3967 let style = chunk
3968 .syntax_highlight_id
3969 .zip(theme)
3970 .and_then(|(highlight, theme)| highlight.style(theme));
3971 if let Some(style) = style {
3972 let start = text.len();
3973 let end = start + chunk.text.len();
3974 highlight_ranges.push((start..end, style));
3975 }
3976 text.push_str(chunk.text);
3977 if offset >= buffer_range.end {
3978 break;
3979 }
3980 }
3981 if is_name {
3982 let after_append_len = text.len();
3983 let start = if space_added && !name_ranges.is_empty() {
3984 before_append_len - 1
3985 } else {
3986 before_append_len
3987 };
3988 name_ranges.push(start..after_append_len);
3989 }
3990 last_buffer_range_end = buffer_range.end;
3991 }
3992
3993 Some(OutlineItem {
3994 depth: 0, // We'll calculate the depth later
3995 range: item_point_range,
3996 text,
3997 highlight_ranges,
3998 name_ranges,
3999 body_range: open_point.zip(close_point).map(|(start, end)| start..end),
4000 annotation_range: None,
4001 })
4002 }
4003
4004 pub fn function_body_fold_ranges<T: ToOffset>(
4005 &self,
4006 within: Range<T>,
4007 ) -> impl Iterator<Item = Range<usize>> + '_ {
4008 self.text_object_ranges(within, TreeSitterOptions::default())
4009 .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
4010 }
4011
4012 /// For each grammar in the language, runs the provided
4013 /// [`tree_sitter::Query`] against the given range.
4014 pub fn matches(
4015 &self,
4016 range: Range<usize>,
4017 query: fn(&Grammar) -> Option<&tree_sitter::Query>,
4018 ) -> SyntaxMapMatches<'_> {
4019 self.syntax.matches(range, self, query)
4020 }
4021
4022 pub fn all_bracket_ranges(
4023 &self,
4024 range: Range<usize>,
4025 ) -> impl Iterator<Item = BracketMatch> + '_ {
4026 let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
4027 grammar.brackets_config.as_ref().map(|c| &c.query)
4028 });
4029 let configs = matches
4030 .grammars()
4031 .iter()
4032 .map(|grammar| grammar.brackets_config.as_ref().unwrap())
4033 .collect::<Vec<_>>();
4034
4035 iter::from_fn(move || {
4036 while let Some(mat) = matches.peek() {
4037 let mut open = None;
4038 let mut close = None;
4039 let config = &configs[mat.grammar_index];
4040 let pattern = &config.patterns[mat.pattern_index];
4041 for capture in mat.captures {
4042 if capture.index == config.open_capture_ix {
4043 open = Some(capture.node.byte_range());
4044 } else if capture.index == config.close_capture_ix {
4045 close = Some(capture.node.byte_range());
4046 }
4047 }
4048
4049 matches.advance();
4050
4051 let Some((open_range, close_range)) = open.zip(close) else {
4052 continue;
4053 };
4054
4055 let bracket_range = open_range.start..=close_range.end;
4056 if !bracket_range.overlaps(&range) {
4057 continue;
4058 }
4059
4060 return Some(BracketMatch {
4061 open_range,
4062 close_range,
4063 newline_only: pattern.newline_only,
4064 });
4065 }
4066 None
4067 })
4068 }
4069
4070 /// Returns bracket range pairs overlapping or adjacent to `range`
4071 pub fn bracket_ranges<T: ToOffset>(
4072 &self,
4073 range: Range<T>,
4074 ) -> impl Iterator<Item = BracketMatch> + '_ {
4075 // Find bracket pairs that *inclusively* contain the given range.
4076 let range = range.start.to_offset(self).saturating_sub(1)
4077 ..self.len().min(range.end.to_offset(self) + 1);
4078 self.all_bracket_ranges(range)
4079 .filter(|pair| !pair.newline_only)
4080 }
4081
4082 pub fn debug_variables_query<T: ToOffset>(
4083 &self,
4084 range: Range<T>,
4085 ) -> impl Iterator<Item = (Range<usize>, DebuggerTextObject)> + '_ {
4086 let range = range.start.to_offset(self).saturating_sub(1)
4087 ..self.len().min(range.end.to_offset(self) + 1);
4088
4089 let mut matches = self.syntax.matches_with_options(
4090 range.clone(),
4091 &self.text,
4092 TreeSitterOptions::default(),
4093 |grammar| grammar.debug_variables_config.as_ref().map(|c| &c.query),
4094 );
4095
4096 let configs = matches
4097 .grammars()
4098 .iter()
4099 .map(|grammar| grammar.debug_variables_config.as_ref())
4100 .collect::<Vec<_>>();
4101
4102 let mut captures = Vec::<(Range<usize>, DebuggerTextObject)>::new();
4103
4104 iter::from_fn(move || {
4105 loop {
4106 while let Some(capture) = captures.pop() {
4107 if capture.0.overlaps(&range) {
4108 return Some(capture);
4109 }
4110 }
4111
4112 let mat = matches.peek()?;
4113
4114 let Some(config) = configs[mat.grammar_index].as_ref() else {
4115 matches.advance();
4116 continue;
4117 };
4118
4119 for capture in mat.captures {
4120 let Some(ix) = config
4121 .objects_by_capture_ix
4122 .binary_search_by_key(&capture.index, |e| e.0)
4123 .ok()
4124 else {
4125 continue;
4126 };
4127 let text_object = config.objects_by_capture_ix[ix].1;
4128 let byte_range = capture.node.byte_range();
4129
4130 let mut found = false;
4131 for (range, existing) in captures.iter_mut() {
4132 if existing == &text_object {
4133 range.start = range.start.min(byte_range.start);
4134 range.end = range.end.max(byte_range.end);
4135 found = true;
4136 break;
4137 }
4138 }
4139
4140 if !found {
4141 captures.push((byte_range, text_object));
4142 }
4143 }
4144
4145 matches.advance();
4146 }
4147 })
4148 }
4149
4150 pub fn text_object_ranges<T: ToOffset>(
4151 &self,
4152 range: Range<T>,
4153 options: TreeSitterOptions,
4154 ) -> impl Iterator<Item = (Range<usize>, TextObject)> + '_ {
4155 let range = range.start.to_offset(self).saturating_sub(1)
4156 ..self.len().min(range.end.to_offset(self) + 1);
4157
4158 let mut matches =
4159 self.syntax
4160 .matches_with_options(range.clone(), &self.text, options, |grammar| {
4161 grammar.text_object_config.as_ref().map(|c| &c.query)
4162 });
4163
4164 let configs = matches
4165 .grammars()
4166 .iter()
4167 .map(|grammar| grammar.text_object_config.as_ref())
4168 .collect::<Vec<_>>();
4169
4170 let mut captures = Vec::<(Range<usize>, TextObject)>::new();
4171
4172 iter::from_fn(move || {
4173 loop {
4174 while let Some(capture) = captures.pop() {
4175 if capture.0.overlaps(&range) {
4176 return Some(capture);
4177 }
4178 }
4179
4180 let mat = matches.peek()?;
4181
4182 let Some(config) = configs[mat.grammar_index].as_ref() else {
4183 matches.advance();
4184 continue;
4185 };
4186
4187 for capture in mat.captures {
4188 let Some(ix) = config
4189 .text_objects_by_capture_ix
4190 .binary_search_by_key(&capture.index, |e| e.0)
4191 .ok()
4192 else {
4193 continue;
4194 };
4195 let text_object = config.text_objects_by_capture_ix[ix].1;
4196 let byte_range = capture.node.byte_range();
4197
4198 let mut found = false;
4199 for (range, existing) in captures.iter_mut() {
4200 if existing == &text_object {
4201 range.start = range.start.min(byte_range.start);
4202 range.end = range.end.max(byte_range.end);
4203 found = true;
4204 break;
4205 }
4206 }
4207
4208 if !found {
4209 captures.push((byte_range, text_object));
4210 }
4211 }
4212
4213 matches.advance();
4214 }
4215 })
4216 }
4217
4218 /// Returns enclosing bracket ranges containing the given range
4219 pub fn enclosing_bracket_ranges<T: ToOffset>(
4220 &self,
4221 range: Range<T>,
4222 ) -> impl Iterator<Item = BracketMatch> + '_ {
4223 let range = range.start.to_offset(self)..range.end.to_offset(self);
4224
4225 self.bracket_ranges(range.clone()).filter(move |pair| {
4226 pair.open_range.start <= range.start && pair.close_range.end >= range.end
4227 })
4228 }
4229
4230 /// Returns the smallest enclosing bracket ranges containing the given range or None if no brackets contain range
4231 ///
4232 /// Can optionally pass a range_filter to filter the ranges of brackets to consider
4233 pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
4234 &self,
4235 range: Range<T>,
4236 range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
4237 ) -> Option<(Range<usize>, Range<usize>)> {
4238 let range = range.start.to_offset(self)..range.end.to_offset(self);
4239
4240 // Get the ranges of the innermost pair of brackets.
4241 let mut result: Option<(Range<usize>, Range<usize>)> = None;
4242
4243 for pair in self.enclosing_bracket_ranges(range) {
4244 if let Some(range_filter) = range_filter
4245 && !range_filter(pair.open_range.clone(), pair.close_range.clone())
4246 {
4247 continue;
4248 }
4249
4250 let len = pair.close_range.end - pair.open_range.start;
4251
4252 if let Some((existing_open, existing_close)) = &result {
4253 let existing_len = existing_close.end - existing_open.start;
4254 if len > existing_len {
4255 continue;
4256 }
4257 }
4258
4259 result = Some((pair.open_range, pair.close_range));
4260 }
4261
4262 result
4263 }
4264
4265 /// Returns anchor ranges for any matches of the redaction query.
4266 /// The buffer can be associated with multiple languages, and the redaction query associated with each
4267 /// will be run on the relevant section of the buffer.
4268 pub fn redacted_ranges<T: ToOffset>(
4269 &self,
4270 range: Range<T>,
4271 ) -> impl Iterator<Item = Range<usize>> + '_ {
4272 let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
4273 let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
4274 grammar
4275 .redactions_config
4276 .as_ref()
4277 .map(|config| &config.query)
4278 });
4279
4280 let configs = syntax_matches
4281 .grammars()
4282 .iter()
4283 .map(|grammar| grammar.redactions_config.as_ref())
4284 .collect::<Vec<_>>();
4285
4286 iter::from_fn(move || {
4287 let redacted_range = syntax_matches
4288 .peek()
4289 .and_then(|mat| {
4290 configs[mat.grammar_index].and_then(|config| {
4291 mat.captures
4292 .iter()
4293 .find(|capture| capture.index == config.redaction_capture_ix)
4294 })
4295 })
4296 .map(|mat| mat.node.byte_range());
4297 syntax_matches.advance();
4298 redacted_range
4299 })
4300 }
4301
4302 pub fn injections_intersecting_range<T: ToOffset>(
4303 &self,
4304 range: Range<T>,
4305 ) -> impl Iterator<Item = (Range<usize>, &Arc<Language>)> + '_ {
4306 let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
4307
4308 let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
4309 grammar
4310 .injection_config
4311 .as_ref()
4312 .map(|config| &config.query)
4313 });
4314
4315 let configs = syntax_matches
4316 .grammars()
4317 .iter()
4318 .map(|grammar| grammar.injection_config.as_ref())
4319 .collect::<Vec<_>>();
4320
4321 iter::from_fn(move || {
4322 let ranges = syntax_matches.peek().and_then(|mat| {
4323 let config = &configs[mat.grammar_index]?;
4324 let content_capture_range = mat.captures.iter().find_map(|capture| {
4325 if capture.index == config.content_capture_ix {
4326 Some(capture.node.byte_range())
4327 } else {
4328 None
4329 }
4330 })?;
4331 let language = self.language_at(content_capture_range.start)?;
4332 Some((content_capture_range, language))
4333 });
4334 syntax_matches.advance();
4335 ranges
4336 })
4337 }
4338
4339 pub fn runnable_ranges(
4340 &self,
4341 offset_range: Range<usize>,
4342 ) -> impl Iterator<Item = RunnableRange> + '_ {
4343 let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
4344 grammar.runnable_config.as_ref().map(|config| &config.query)
4345 });
4346
4347 let test_configs = syntax_matches
4348 .grammars()
4349 .iter()
4350 .map(|grammar| grammar.runnable_config.as_ref())
4351 .collect::<Vec<_>>();
4352
4353 iter::from_fn(move || {
4354 loop {
4355 let mat = syntax_matches.peek()?;
4356
4357 let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
4358 let mut run_range = None;
4359 let full_range = mat.captures.iter().fold(
4360 Range {
4361 start: usize::MAX,
4362 end: 0,
4363 },
4364 |mut acc, next| {
4365 let byte_range = next.node.byte_range();
4366 if acc.start > byte_range.start {
4367 acc.start = byte_range.start;
4368 }
4369 if acc.end < byte_range.end {
4370 acc.end = byte_range.end;
4371 }
4372 acc
4373 },
4374 );
4375 if full_range.start > full_range.end {
4376 // We did not find a full spanning range of this match.
4377 return None;
4378 }
4379 let extra_captures: SmallVec<[_; 1]> =
4380 SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
4381 test_configs
4382 .extra_captures
4383 .get(capture.index as usize)
4384 .cloned()
4385 .and_then(|tag_name| match tag_name {
4386 RunnableCapture::Named(name) => {
4387 Some((capture.node.byte_range(), name))
4388 }
4389 RunnableCapture::Run => {
4390 let _ = run_range.insert(capture.node.byte_range());
4391 None
4392 }
4393 })
4394 }));
4395 let run_range = run_range?;
4396 let tags = test_configs
4397 .query
4398 .property_settings(mat.pattern_index)
4399 .iter()
4400 .filter_map(|property| {
4401 if *property.key == *"tag" {
4402 property
4403 .value
4404 .as_ref()
4405 .map(|value| RunnableTag(value.to_string().into()))
4406 } else {
4407 None
4408 }
4409 })
4410 .collect();
4411 let extra_captures = extra_captures
4412 .into_iter()
4413 .map(|(range, name)| {
4414 (
4415 name.to_string(),
4416 self.text_for_range(range).collect::<String>(),
4417 )
4418 })
4419 .collect();
4420 // All tags should have the same range.
4421 Some(RunnableRange {
4422 run_range,
4423 full_range,
4424 runnable: Runnable {
4425 tags,
4426 language: mat.language,
4427 buffer: self.remote_id(),
4428 },
4429 extra_captures,
4430 buffer_id: self.remote_id(),
4431 })
4432 });
4433
4434 syntax_matches.advance();
4435 if test_range.is_some() {
4436 // It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
4437 // had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
4438 return test_range;
4439 }
4440 }
4441 })
4442 }
4443
4444 /// Returns selections for remote peers intersecting the given range.
4445 #[allow(clippy::type_complexity)]
4446 pub fn selections_in_range(
4447 &self,
4448 range: Range<Anchor>,
4449 include_local: bool,
4450 ) -> impl Iterator<
4451 Item = (
4452 ReplicaId,
4453 bool,
4454 CursorShape,
4455 impl Iterator<Item = &Selection<Anchor>> + '_,
4456 ),
4457 > + '_ {
4458 self.remote_selections
4459 .iter()
4460 .filter(move |(replica_id, set)| {
4461 (include_local || **replica_id != self.text.replica_id())
4462 && !set.selections.is_empty()
4463 })
4464 .map(move |(replica_id, set)| {
4465 let start_ix = match set.selections.binary_search_by(|probe| {
4466 probe.end.cmp(&range.start, self).then(Ordering::Greater)
4467 }) {
4468 Ok(ix) | Err(ix) => ix,
4469 };
4470 let end_ix = match set.selections.binary_search_by(|probe| {
4471 probe.start.cmp(&range.end, self).then(Ordering::Less)
4472 }) {
4473 Ok(ix) | Err(ix) => ix,
4474 };
4475
4476 (
4477 *replica_id,
4478 set.line_mode,
4479 set.cursor_shape,
4480 set.selections[start_ix..end_ix].iter(),
4481 )
4482 })
4483 }
4484
4485 /// Returns if the buffer contains any diagnostics.
4486 pub fn has_diagnostics(&self) -> bool {
4487 !self.diagnostics.is_empty()
4488 }
4489
4490 /// Returns all the diagnostics intersecting the given range.
4491 pub fn diagnostics_in_range<'a, T, O>(
4492 &'a self,
4493 search_range: Range<T>,
4494 reversed: bool,
4495 ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
4496 where
4497 T: 'a + Clone + ToOffset,
4498 O: 'a + FromAnchor,
4499 {
4500 let mut iterators: Vec<_> = self
4501 .diagnostics
4502 .iter()
4503 .map(|(_, collection)| {
4504 collection
4505 .range::<T, text::Anchor>(search_range.clone(), self, true, reversed)
4506 .peekable()
4507 })
4508 .collect();
4509
4510 std::iter::from_fn(move || {
4511 let (next_ix, _) = iterators
4512 .iter_mut()
4513 .enumerate()
4514 .flat_map(|(ix, iter)| Some((ix, iter.peek()?)))
4515 .min_by(|(_, a), (_, b)| {
4516 let cmp = a
4517 .range
4518 .start
4519 .cmp(&b.range.start, self)
4520 // when range is equal, sort by diagnostic severity
4521 .then(a.diagnostic.severity.cmp(&b.diagnostic.severity))
4522 // and stabilize order with group_id
4523 .then(a.diagnostic.group_id.cmp(&b.diagnostic.group_id));
4524 if reversed { cmp.reverse() } else { cmp }
4525 })?;
4526 iterators[next_ix]
4527 .next()
4528 .map(|DiagnosticEntry { range, diagnostic }| DiagnosticEntry {
4529 diagnostic,
4530 range: FromAnchor::from_anchor(&range.start, self)
4531 ..FromAnchor::from_anchor(&range.end, self),
4532 })
4533 })
4534 }
4535
4536 /// Returns all the diagnostic groups associated with the given
4537 /// language server ID. If no language server ID is provided,
4538 /// all diagnostics groups are returned.
4539 pub fn diagnostic_groups(
4540 &self,
4541 language_server_id: Option<LanguageServerId>,
4542 ) -> Vec<(LanguageServerId, DiagnosticGroup<Anchor>)> {
4543 let mut groups = Vec::new();
4544
4545 if let Some(language_server_id) = language_server_id {
4546 if let Ok(ix) = self
4547 .diagnostics
4548 .binary_search_by_key(&language_server_id, |e| e.0)
4549 {
4550 self.diagnostics[ix]
4551 .1
4552 .groups(language_server_id, &mut groups, self);
4553 }
4554 } else {
4555 for (language_server_id, diagnostics) in self.diagnostics.iter() {
4556 diagnostics.groups(*language_server_id, &mut groups, self);
4557 }
4558 }
4559
4560 groups.sort_by(|(id_a, group_a), (id_b, group_b)| {
4561 let a_start = &group_a.entries[group_a.primary_ix].range.start;
4562 let b_start = &group_b.entries[group_b.primary_ix].range.start;
4563 a_start.cmp(b_start, self).then_with(|| id_a.cmp(id_b))
4564 });
4565
4566 groups
4567 }
4568
4569 /// Returns an iterator over the diagnostics for the given group.
4570 pub fn diagnostic_group<O>(
4571 &self,
4572 group_id: usize,
4573 ) -> impl Iterator<Item = DiagnosticEntry<O>> + '_
4574 where
4575 O: FromAnchor + 'static,
4576 {
4577 self.diagnostics
4578 .iter()
4579 .flat_map(move |(_, set)| set.group(group_id, self))
4580 }
4581
4582 /// An integer version number that accounts for all updates besides
4583 /// the buffer's text itself (which is versioned via a version vector).
4584 pub fn non_text_state_update_count(&self) -> usize {
4585 self.non_text_state_update_count
4586 }
4587
4588 /// An integer version that changes when the buffer's syntax changes.
4589 pub fn syntax_update_count(&self) -> usize {
4590 self.syntax.update_count()
4591 }
4592
4593 /// Returns a snapshot of underlying file.
4594 pub fn file(&self) -> Option<&Arc<dyn File>> {
4595 self.file.as_ref()
4596 }
4597
4598 /// Resolves the file path (relative to the worktree root) associated with the underlying file.
4599 pub fn resolve_file_path(&self, cx: &App, include_root: bool) -> Option<PathBuf> {
4600 if let Some(file) = self.file() {
4601 if file.path().file_name().is_none() || include_root {
4602 Some(file.full_path(cx))
4603 } else {
4604 Some(file.path().to_path_buf())
4605 }
4606 } else {
4607 None
4608 }
4609 }
4610
4611 pub fn words_in_range(&self, query: WordsQuery) -> BTreeMap<String, Range<Anchor>> {
4612 let query_str = query.fuzzy_contents;
4613 if query_str.is_some_and(|query| query.is_empty()) {
4614 return BTreeMap::default();
4615 }
4616
4617 let classifier = CharClassifier::new(self.language.clone().map(|language| LanguageScope {
4618 language,
4619 override_id: None,
4620 }));
4621
4622 let mut query_ix = 0;
4623 let query_chars = query_str.map(|query| query.chars().collect::<Vec<_>>());
4624 let query_len = query_chars.as_ref().map_or(0, |query| query.len());
4625
4626 let mut words = BTreeMap::default();
4627 let mut current_word_start_ix = None;
4628 let mut chunk_ix = query.range.start;
4629 for chunk in self.chunks(query.range, false) {
4630 for (i, c) in chunk.text.char_indices() {
4631 let ix = chunk_ix + i;
4632 if classifier.is_word(c) {
4633 if current_word_start_ix.is_none() {
4634 current_word_start_ix = Some(ix);
4635 }
4636
4637 if let Some(query_chars) = &query_chars
4638 && query_ix < query_len
4639 && c.to_lowercase().eq(query_chars[query_ix].to_lowercase())
4640 {
4641 query_ix += 1;
4642 }
4643 continue;
4644 } else if let Some(word_start) = current_word_start_ix.take()
4645 && query_ix == query_len
4646 {
4647 let word_range = self.anchor_before(word_start)..self.anchor_after(ix);
4648 let mut word_text = self.text_for_range(word_start..ix).peekable();
4649 let first_char = word_text
4650 .peek()
4651 .and_then(|first_chunk| first_chunk.chars().next());
4652 // Skip empty and "words" starting with digits as a heuristic to reduce useless completions
4653 if !query.skip_digits
4654 || first_char.is_none_or(|first_char| !first_char.is_digit(10))
4655 {
4656 words.insert(word_text.collect(), word_range);
4657 }
4658 }
4659 query_ix = 0;
4660 }
4661 chunk_ix += chunk.text.len();
4662 }
4663
4664 words
4665 }
4666}
4667
4668pub struct WordsQuery<'a> {
4669 /// Only returns words with all chars from the fuzzy string in them.
4670 pub fuzzy_contents: Option<&'a str>,
4671 /// Skips words that start with a digit.
4672 pub skip_digits: bool,
4673 /// Buffer offset range, to look for words.
4674 pub range: Range<usize>,
4675}
4676
4677fn indent_size_for_line(text: &text::BufferSnapshot, row: u32) -> IndentSize {
4678 indent_size_for_text(text.chars_at(Point::new(row, 0)))
4679}
4680
4681fn indent_size_for_text(text: impl Iterator<Item = char>) -> IndentSize {
4682 let mut result = IndentSize::spaces(0);
4683 for c in text {
4684 let kind = match c {
4685 ' ' => IndentKind::Space,
4686 '\t' => IndentKind::Tab,
4687 _ => break,
4688 };
4689 if result.len == 0 {
4690 result.kind = kind;
4691 }
4692 result.len += 1;
4693 }
4694 result
4695}
4696
4697impl Clone for BufferSnapshot {
4698 fn clone(&self) -> Self {
4699 Self {
4700 text: self.text.clone(),
4701 syntax: self.syntax.clone(),
4702 file: self.file.clone(),
4703 remote_selections: self.remote_selections.clone(),
4704 diagnostics: self.diagnostics.clone(),
4705 language: self.language.clone(),
4706 non_text_state_update_count: self.non_text_state_update_count,
4707 }
4708 }
4709}
4710
4711impl Deref for BufferSnapshot {
4712 type Target = text::BufferSnapshot;
4713
4714 fn deref(&self) -> &Self::Target {
4715 &self.text
4716 }
4717}
4718
4719unsafe impl Send for BufferChunks<'_> {}
4720
4721impl<'a> BufferChunks<'a> {
4722 pub(crate) fn new(
4723 text: &'a Rope,
4724 range: Range<usize>,
4725 syntax: Option<(SyntaxMapCaptures<'a>, Vec<HighlightMap>)>,
4726 diagnostics: bool,
4727 buffer_snapshot: Option<&'a BufferSnapshot>,
4728 ) -> Self {
4729 let mut highlights = None;
4730 if let Some((captures, highlight_maps)) = syntax {
4731 highlights = Some(BufferChunkHighlights {
4732 captures,
4733 next_capture: None,
4734 stack: Default::default(),
4735 highlight_maps,
4736 })
4737 }
4738
4739 let diagnostic_endpoints = diagnostics.then(|| Vec::new().into_iter().peekable());
4740 let chunks = text.chunks_in_range(range.clone());
4741
4742 let mut this = BufferChunks {
4743 range,
4744 buffer_snapshot,
4745 chunks,
4746 diagnostic_endpoints,
4747 error_depth: 0,
4748 warning_depth: 0,
4749 information_depth: 0,
4750 hint_depth: 0,
4751 unnecessary_depth: 0,
4752 underline: true,
4753 highlights,
4754 };
4755 this.initialize_diagnostic_endpoints();
4756 this
4757 }
4758
4759 /// Seeks to the given byte offset in the buffer.
4760 pub fn seek(&mut self, range: Range<usize>) {
4761 let old_range = std::mem::replace(&mut self.range, range.clone());
4762 self.chunks.set_range(self.range.clone());
4763 if let Some(highlights) = self.highlights.as_mut() {
4764 if old_range.start <= self.range.start && old_range.end >= self.range.end {
4765 // Reuse existing highlights stack, as the new range is a subrange of the old one.
4766 highlights
4767 .stack
4768 .retain(|(end_offset, _)| *end_offset > range.start);
4769 if let Some(capture) = &highlights.next_capture
4770 && range.start >= capture.node.start_byte()
4771 {
4772 let next_capture_end = capture.node.end_byte();
4773 if range.start < next_capture_end {
4774 highlights.stack.push((
4775 next_capture_end,
4776 highlights.highlight_maps[capture.grammar_index].get(capture.index),
4777 ));
4778 }
4779 highlights.next_capture.take();
4780 }
4781 } else if let Some(snapshot) = self.buffer_snapshot {
4782 let (captures, highlight_maps) = snapshot.get_highlights(self.range.clone());
4783 *highlights = BufferChunkHighlights {
4784 captures,
4785 next_capture: None,
4786 stack: Default::default(),
4787 highlight_maps,
4788 };
4789 } else {
4790 // We cannot obtain new highlights for a language-aware buffer iterator, as we don't have a buffer snapshot.
4791 // Seeking such BufferChunks is not supported.
4792 debug_assert!(
4793 false,
4794 "Attempted to seek on a language-aware buffer iterator without associated buffer snapshot"
4795 );
4796 }
4797
4798 highlights.captures.set_byte_range(self.range.clone());
4799 self.initialize_diagnostic_endpoints();
4800 }
4801 }
4802
4803 fn initialize_diagnostic_endpoints(&mut self) {
4804 if let Some(diagnostics) = self.diagnostic_endpoints.as_mut()
4805 && let Some(buffer) = self.buffer_snapshot
4806 {
4807 let mut diagnostic_endpoints = Vec::new();
4808 for entry in buffer.diagnostics_in_range::<_, usize>(self.range.clone(), false) {
4809 diagnostic_endpoints.push(DiagnosticEndpoint {
4810 offset: entry.range.start,
4811 is_start: true,
4812 severity: entry.diagnostic.severity,
4813 is_unnecessary: entry.diagnostic.is_unnecessary,
4814 underline: entry.diagnostic.underline,
4815 });
4816 diagnostic_endpoints.push(DiagnosticEndpoint {
4817 offset: entry.range.end,
4818 is_start: false,
4819 severity: entry.diagnostic.severity,
4820 is_unnecessary: entry.diagnostic.is_unnecessary,
4821 underline: entry.diagnostic.underline,
4822 });
4823 }
4824 diagnostic_endpoints
4825 .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
4826 *diagnostics = diagnostic_endpoints.into_iter().peekable();
4827 self.hint_depth = 0;
4828 self.error_depth = 0;
4829 self.warning_depth = 0;
4830 self.information_depth = 0;
4831 }
4832 }
4833
4834 /// The current byte offset in the buffer.
4835 pub fn offset(&self) -> usize {
4836 self.range.start
4837 }
4838
4839 pub fn range(&self) -> Range<usize> {
4840 self.range.clone()
4841 }
4842
4843 fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
4844 let depth = match endpoint.severity {
4845 DiagnosticSeverity::ERROR => &mut self.error_depth,
4846 DiagnosticSeverity::WARNING => &mut self.warning_depth,
4847 DiagnosticSeverity::INFORMATION => &mut self.information_depth,
4848 DiagnosticSeverity::HINT => &mut self.hint_depth,
4849 _ => return,
4850 };
4851 if endpoint.is_start {
4852 *depth += 1;
4853 } else {
4854 *depth -= 1;
4855 }
4856
4857 if endpoint.is_unnecessary {
4858 if endpoint.is_start {
4859 self.unnecessary_depth += 1;
4860 } else {
4861 self.unnecessary_depth -= 1;
4862 }
4863 }
4864 }
4865
4866 fn current_diagnostic_severity(&self) -> Option<DiagnosticSeverity> {
4867 if self.error_depth > 0 {
4868 Some(DiagnosticSeverity::ERROR)
4869 } else if self.warning_depth > 0 {
4870 Some(DiagnosticSeverity::WARNING)
4871 } else if self.information_depth > 0 {
4872 Some(DiagnosticSeverity::INFORMATION)
4873 } else if self.hint_depth > 0 {
4874 Some(DiagnosticSeverity::HINT)
4875 } else {
4876 None
4877 }
4878 }
4879
4880 fn current_code_is_unnecessary(&self) -> bool {
4881 self.unnecessary_depth > 0
4882 }
4883}
4884
4885impl<'a> Iterator for BufferChunks<'a> {
4886 type Item = Chunk<'a>;
4887
4888 fn next(&mut self) -> Option<Self::Item> {
4889 let mut next_capture_start = usize::MAX;
4890 let mut next_diagnostic_endpoint = usize::MAX;
4891
4892 if let Some(highlights) = self.highlights.as_mut() {
4893 while let Some((parent_capture_end, _)) = highlights.stack.last() {
4894 if *parent_capture_end <= self.range.start {
4895 highlights.stack.pop();
4896 } else {
4897 break;
4898 }
4899 }
4900
4901 if highlights.next_capture.is_none() {
4902 highlights.next_capture = highlights.captures.next();
4903 }
4904
4905 while let Some(capture) = highlights.next_capture.as_ref() {
4906 if self.range.start < capture.node.start_byte() {
4907 next_capture_start = capture.node.start_byte();
4908 break;
4909 } else {
4910 let highlight_id =
4911 highlights.highlight_maps[capture.grammar_index].get(capture.index);
4912 highlights
4913 .stack
4914 .push((capture.node.end_byte(), highlight_id));
4915 highlights.next_capture = highlights.captures.next();
4916 }
4917 }
4918 }
4919
4920 let mut diagnostic_endpoints = std::mem::take(&mut self.diagnostic_endpoints);
4921 if let Some(diagnostic_endpoints) = diagnostic_endpoints.as_mut() {
4922 while let Some(endpoint) = diagnostic_endpoints.peek().copied() {
4923 if endpoint.offset <= self.range.start {
4924 self.update_diagnostic_depths(endpoint);
4925 diagnostic_endpoints.next();
4926 self.underline = endpoint.underline;
4927 } else {
4928 next_diagnostic_endpoint = endpoint.offset;
4929 break;
4930 }
4931 }
4932 }
4933 self.diagnostic_endpoints = diagnostic_endpoints;
4934
4935 if let Some(ChunkBitmaps {
4936 text: chunk,
4937 chars: chars_map,
4938 tabs,
4939 }) = self.chunks.peek_tabs()
4940 {
4941 let chunk_start = self.range.start;
4942 let mut chunk_end = (self.chunks.offset() + chunk.len())
4943 .min(next_capture_start)
4944 .min(next_diagnostic_endpoint);
4945 let mut highlight_id = None;
4946 if let Some(highlights) = self.highlights.as_ref()
4947 && let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last()
4948 {
4949 chunk_end = chunk_end.min(*parent_capture_end);
4950 highlight_id = Some(*parent_highlight_id);
4951 }
4952
4953 let slice =
4954 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
4955 let bit_end = chunk_end - self.chunks.offset();
4956
4957 let mask = if bit_end >= 128 {
4958 u128::MAX
4959 } else {
4960 (1u128 << bit_end) - 1
4961 };
4962 let tabs = (tabs >> (chunk_start - self.chunks.offset())) & mask;
4963 let chars_map = (chars_map >> (chunk_start - self.chunks.offset())) & mask;
4964
4965 self.range.start = chunk_end;
4966 if self.range.start == self.chunks.offset() + chunk.len() {
4967 self.chunks.next().unwrap();
4968 }
4969
4970 Some(Chunk {
4971 text: slice,
4972 syntax_highlight_id: highlight_id,
4973 underline: self.underline,
4974 diagnostic_severity: self.current_diagnostic_severity(),
4975 is_unnecessary: self.current_code_is_unnecessary(),
4976 tabs,
4977 chars: chars_map,
4978 ..Chunk::default()
4979 })
4980 } else {
4981 None
4982 }
4983 }
4984}
4985
4986impl operation_queue::Operation for Operation {
4987 fn lamport_timestamp(&self) -> clock::Lamport {
4988 match self {
4989 Operation::Buffer(_) => {
4990 unreachable!("buffer operations should never be deferred at this layer")
4991 }
4992 Operation::UpdateDiagnostics {
4993 lamport_timestamp, ..
4994 }
4995 | Operation::UpdateSelections {
4996 lamport_timestamp, ..
4997 }
4998 | Operation::UpdateCompletionTriggers {
4999 lamport_timestamp, ..
5000 }
5001 | Operation::UpdateLineEnding {
5002 lamport_timestamp, ..
5003 } => *lamport_timestamp,
5004 }
5005 }
5006}
5007
5008impl Default for Diagnostic {
5009 fn default() -> Self {
5010 Self {
5011 source: Default::default(),
5012 source_kind: DiagnosticSourceKind::Other,
5013 code: None,
5014 code_description: None,
5015 severity: DiagnosticSeverity::ERROR,
5016 message: Default::default(),
5017 markdown: None,
5018 group_id: 0,
5019 is_primary: false,
5020 is_disk_based: false,
5021 is_unnecessary: false,
5022 underline: true,
5023 data: None,
5024 }
5025 }
5026}
5027
5028impl IndentSize {
5029 /// Returns an [`IndentSize`] representing the given spaces.
5030 pub fn spaces(len: u32) -> Self {
5031 Self {
5032 len,
5033 kind: IndentKind::Space,
5034 }
5035 }
5036
5037 /// Returns an [`IndentSize`] representing a tab.
5038 pub fn tab() -> Self {
5039 Self {
5040 len: 1,
5041 kind: IndentKind::Tab,
5042 }
5043 }
5044
5045 /// An iterator over the characters represented by this [`IndentSize`].
5046 pub fn chars(&self) -> impl Iterator<Item = char> {
5047 iter::repeat(self.char()).take(self.len as usize)
5048 }
5049
5050 /// The character representation of this [`IndentSize`].
5051 pub fn char(&self) -> char {
5052 match self.kind {
5053 IndentKind::Space => ' ',
5054 IndentKind::Tab => '\t',
5055 }
5056 }
5057
5058 /// Consumes the current [`IndentSize`] and returns a new one that has
5059 /// been shrunk or enlarged by the given size along the given direction.
5060 pub fn with_delta(mut self, direction: Ordering, size: IndentSize) -> Self {
5061 match direction {
5062 Ordering::Less => {
5063 if self.kind == size.kind && self.len >= size.len {
5064 self.len -= size.len;
5065 }
5066 }
5067 Ordering::Equal => {}
5068 Ordering::Greater => {
5069 if self.len == 0 {
5070 self = size;
5071 } else if self.kind == size.kind {
5072 self.len += size.len;
5073 }
5074 }
5075 }
5076 self
5077 }
5078
5079 pub fn len_with_expanded_tabs(&self, tab_size: NonZeroU32) -> usize {
5080 match self.kind {
5081 IndentKind::Space => self.len as usize,
5082 IndentKind::Tab => self.len as usize * tab_size.get() as usize,
5083 }
5084 }
5085}
5086
5087#[cfg(any(test, feature = "test-support"))]
5088pub struct TestFile {
5089 pub path: Arc<Path>,
5090 pub root_name: String,
5091 pub local_root: Option<PathBuf>,
5092}
5093
5094#[cfg(any(test, feature = "test-support"))]
5095impl File for TestFile {
5096 fn path(&self) -> &Arc<Path> {
5097 &self.path
5098 }
5099
5100 fn full_path(&self, _: &gpui::App) -> PathBuf {
5101 PathBuf::from(&self.root_name).join(self.path.as_ref())
5102 }
5103
5104 fn as_local(&self) -> Option<&dyn LocalFile> {
5105 if self.local_root.is_some() {
5106 Some(self)
5107 } else {
5108 None
5109 }
5110 }
5111
5112 fn disk_state(&self) -> DiskState {
5113 unimplemented!()
5114 }
5115
5116 fn file_name<'a>(&'a self, _: &'a gpui::App) -> &'a std::ffi::OsStr {
5117 self.path().file_name().unwrap_or(self.root_name.as_ref())
5118 }
5119
5120 fn worktree_id(&self, _: &App) -> WorktreeId {
5121 WorktreeId::from_usize(0)
5122 }
5123
5124 fn to_proto(&self, _: &App) -> rpc::proto::File {
5125 unimplemented!()
5126 }
5127
5128 fn is_private(&self) -> bool {
5129 false
5130 }
5131}
5132
5133#[cfg(any(test, feature = "test-support"))]
5134impl LocalFile for TestFile {
5135 fn abs_path(&self, _cx: &App) -> PathBuf {
5136 PathBuf::from(self.local_root.as_ref().unwrap())
5137 .join(&self.root_name)
5138 .join(self.path.as_ref())
5139 }
5140
5141 fn load(&self, _cx: &App) -> Task<Result<String>> {
5142 unimplemented!()
5143 }
5144
5145 fn load_bytes(&self, _cx: &App) -> Task<Result<Vec<u8>>> {
5146 unimplemented!()
5147 }
5148}
5149
5150pub(crate) fn contiguous_ranges(
5151 values: impl Iterator<Item = u32>,
5152 max_len: usize,
5153) -> impl Iterator<Item = Range<u32>> {
5154 let mut values = values;
5155 let mut current_range: Option<Range<u32>> = None;
5156 std::iter::from_fn(move || {
5157 loop {
5158 if let Some(value) = values.next() {
5159 if let Some(range) = &mut current_range
5160 && value == range.end
5161 && range.len() < max_len
5162 {
5163 range.end += 1;
5164 continue;
5165 }
5166
5167 let prev_range = current_range.clone();
5168 current_range = Some(value..(value + 1));
5169 if prev_range.is_some() {
5170 return prev_range;
5171 }
5172 } else {
5173 return current_range.take();
5174 }
5175 }
5176 })
5177}
5178
5179#[derive(Default, Debug)]
5180pub struct CharClassifier {
5181 scope: Option<LanguageScope>,
5182 for_completion: bool,
5183 ignore_punctuation: bool,
5184}
5185
5186impl CharClassifier {
5187 pub fn new(scope: Option<LanguageScope>) -> Self {
5188 Self {
5189 scope,
5190 for_completion: false,
5191 ignore_punctuation: false,
5192 }
5193 }
5194
5195 pub fn for_completion(self, for_completion: bool) -> Self {
5196 Self {
5197 for_completion,
5198 ..self
5199 }
5200 }
5201
5202 pub fn ignore_punctuation(self, ignore_punctuation: bool) -> Self {
5203 Self {
5204 ignore_punctuation,
5205 ..self
5206 }
5207 }
5208
5209 pub fn is_whitespace(&self, c: char) -> bool {
5210 self.kind(c) == CharKind::Whitespace
5211 }
5212
5213 pub fn is_word(&self, c: char) -> bool {
5214 self.kind(c) == CharKind::Word
5215 }
5216
5217 pub fn is_punctuation(&self, c: char) -> bool {
5218 self.kind(c) == CharKind::Punctuation
5219 }
5220
5221 pub fn kind_with(&self, c: char, ignore_punctuation: bool) -> CharKind {
5222 if c.is_alphanumeric() || c == '_' {
5223 return CharKind::Word;
5224 }
5225
5226 if let Some(scope) = &self.scope {
5227 let characters = if self.for_completion {
5228 scope.completion_query_characters()
5229 } else {
5230 scope.word_characters()
5231 };
5232 if let Some(characters) = characters
5233 && characters.contains(&c)
5234 {
5235 return CharKind::Word;
5236 }
5237 }
5238
5239 if c.is_whitespace() {
5240 return CharKind::Whitespace;
5241 }
5242
5243 if ignore_punctuation {
5244 CharKind::Word
5245 } else {
5246 CharKind::Punctuation
5247 }
5248 }
5249
5250 pub fn kind(&self, c: char) -> CharKind {
5251 self.kind_with(c, self.ignore_punctuation)
5252 }
5253}
5254
5255/// Find all of the ranges of whitespace that occur at the ends of lines
5256/// in the given rope.
5257///
5258/// This could also be done with a regex search, but this implementation
5259/// avoids copying text.
5260pub fn trailing_whitespace_ranges(rope: &Rope) -> Vec<Range<usize>> {
5261 let mut ranges = Vec::new();
5262
5263 let mut offset = 0;
5264 let mut prev_chunk_trailing_whitespace_range = 0..0;
5265 for chunk in rope.chunks() {
5266 let mut prev_line_trailing_whitespace_range = 0..0;
5267 for (i, line) in chunk.split('\n').enumerate() {
5268 let line_end_offset = offset + line.len();
5269 let trimmed_line_len = line.trim_end_matches([' ', '\t']).len();
5270 let mut trailing_whitespace_range = (offset + trimmed_line_len)..line_end_offset;
5271
5272 if i == 0 && trimmed_line_len == 0 {
5273 trailing_whitespace_range.start = prev_chunk_trailing_whitespace_range.start;
5274 }
5275 if !prev_line_trailing_whitespace_range.is_empty() {
5276 ranges.push(prev_line_trailing_whitespace_range);
5277 }
5278
5279 offset = line_end_offset + 1;
5280 prev_line_trailing_whitespace_range = trailing_whitespace_range;
5281 }
5282
5283 offset -= 1;
5284 prev_chunk_trailing_whitespace_range = prev_line_trailing_whitespace_range;
5285 }
5286
5287 if !prev_chunk_trailing_whitespace_range.is_empty() {
5288 ranges.push(prev_chunk_trailing_whitespace_range);
5289 }
5290
5291 ranges
5292}