buffer.rs

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