buffer.rs

   1pub mod row_chunk;
   2
   3use crate::{
   4    ByteContent, DebuggerTextObject, LanguageScope, ModelineSettings, Outline, OutlineConfig,
   5    PLAIN_TEXT, RunnableCapture, RunnableTag, TextObject, TreeSitterOptions, analyze_byte_content,
   6    diagnostic_set::{DiagnosticEntry, DiagnosticEntryRef, DiagnosticGroup},
   7    language_settings::{AutoIndentMode, LanguageSettings},
   8    outline::OutlineItem,
   9    row_chunk::RowChunks,
  10    syntax_map::{
  11        MAX_BYTES_TO_QUERY, 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 bytes = load_bytes_task.await?;
1583
1584            anyhow::ensure!(
1585                analyze_byte_content(&bytes) != ByteContent::Binary,
1586                "Binary files are not supported"
1587            );
1588
1589            let is_unicode = target_encoding == encoding_rs::UTF_8
1590                || target_encoding == encoding_rs::UTF_16LE
1591                || target_encoding == encoding_rs::UTF_16BE;
1592
1593            let (new_text, has_bom, encoding_used) = if force_encoding.is_some() && !is_unicode {
1594                let (cow, _had_errors) = target_encoding.decode_without_bom_handling(&bytes);
1595                (cow.into_owned(), false, target_encoding)
1596            } else {
1597                let (cow, used_enc, _had_errors) = target_encoding.decode(&bytes);
1598
1599                let actual_has_bom = if used_enc == encoding_rs::UTF_8 {
1600                    bytes.starts_with(&[0xEF, 0xBB, 0xBF])
1601                } else if used_enc == encoding_rs::UTF_16LE {
1602                    bytes.starts_with(&[0xFF, 0xFE])
1603                } else if used_enc == encoding_rs::UTF_16BE {
1604                    bytes.starts_with(&[0xFE, 0xFF])
1605                } else {
1606                    false
1607                };
1608                (cow.into_owned(), actual_has_bom, used_enc)
1609            };
1610
1611            let diff = this.update(cx, |this, cx| this.diff(new_text, cx))?.await;
1612            this.update(cx, |this, cx| {
1613                if this.version() == diff.base_version {
1614                    this.finalize_last_transaction();
1615                    let old_encoding = this.encoding;
1616                    let old_has_bom = this.has_bom;
1617                    this.apply_diff(diff, cx);
1618                    this.encoding = encoding_used;
1619                    this.has_bom = has_bom;
1620                    let transaction = this.finalize_last_transaction().cloned();
1621                    if let Some(ref txn) = transaction {
1622                        if old_encoding != encoding_used || old_has_bom != has_bom {
1623                            this.reload_with_encoding_txns
1624                                .insert(txn.id, (old_encoding, old_has_bom));
1625                        }
1626                    }
1627                    tx.send(transaction).ok();
1628                    this.has_conflict = false;
1629                    this.did_reload(this.version(), this.line_ending(), new_mtime, cx);
1630                } else {
1631                    if !diff.edits.is_empty()
1632                        || this
1633                            .edits_since::<usize>(&diff.base_version)
1634                            .next()
1635                            .is_some()
1636                    {
1637                        this.has_conflict = true;
1638                    }
1639
1640                    this.did_reload(prev_version, this.line_ending(), this.saved_mtime, cx);
1641                }
1642
1643                this.reload_task.take();
1644            })
1645        }));
1646        rx
1647    }
1648
1649    /// This method is called to signal that the buffer has been reloaded.
1650    pub fn did_reload(
1651        &mut self,
1652        version: clock::Global,
1653        line_ending: LineEnding,
1654        mtime: Option<MTime>,
1655        cx: &mut Context<Self>,
1656    ) {
1657        self.saved_version = version;
1658        self.has_unsaved_edits
1659            .set((self.saved_version.clone(), false));
1660        self.text.set_line_ending(line_ending);
1661        self.saved_mtime = mtime;
1662        cx.emit(BufferEvent::Reloaded);
1663        cx.notify();
1664    }
1665
1666    /// Updates the [`File`] backing this buffer. This should be called when
1667    /// the file has changed or has been deleted.
1668    pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut Context<Self>) {
1669        let was_dirty = self.is_dirty();
1670        let mut file_changed = false;
1671
1672        if let Some(old_file) = self.file.as_ref() {
1673            if new_file.path() != old_file.path() {
1674                file_changed = true;
1675            }
1676
1677            let old_state = old_file.disk_state();
1678            let new_state = new_file.disk_state();
1679            if old_state != new_state {
1680                file_changed = true;
1681                if !was_dirty && matches!(new_state, DiskState::Present { .. }) {
1682                    cx.emit(BufferEvent::ReloadNeeded)
1683                }
1684            }
1685        } else {
1686            file_changed = true;
1687        };
1688
1689        self.file = Some(new_file);
1690        if file_changed {
1691            self.was_changed();
1692            self.non_text_state_update_count += 1;
1693            if was_dirty != self.is_dirty() {
1694                cx.emit(BufferEvent::DirtyChanged);
1695            }
1696            cx.emit(BufferEvent::FileHandleChanged);
1697            cx.notify();
1698        }
1699    }
1700
1701    pub fn base_buffer(&self) -> Option<Entity<Self>> {
1702        Some(self.branch_state.as_ref()?.base_buffer.clone())
1703    }
1704
1705    /// Returns the primary [`Language`] assigned to this [`Buffer`].
1706    pub fn language(&self) -> Option<&Arc<Language>> {
1707        self.language.as_ref()
1708    }
1709
1710    /// Returns the [`Language`] at the given location.
1711    pub fn language_at<D: ToOffset>(&self, position: D) -> Option<Arc<Language>> {
1712        let offset = position.to_offset(self);
1713        let text: &TextBufferSnapshot = &self.text;
1714        self.syntax_map
1715            .lock()
1716            .layers_for_range(offset..offset, text, false)
1717            .filter(|layer| {
1718                layer
1719                    .included_sub_ranges
1720                    .is_none_or(|ranges| offset_in_sub_ranges(ranges, offset, text))
1721            })
1722            .last()
1723            .map(|info| info.language.clone())
1724            .or_else(|| self.language.clone())
1725    }
1726
1727    /// Returns each [`Language`] for the active syntax layers at the given location.
1728    pub fn languages_at<D: ToOffset>(&self, position: D) -> Vec<Arc<Language>> {
1729        let offset = position.to_offset(self);
1730        let text: &TextBufferSnapshot = &self.text;
1731        let mut languages: Vec<Arc<Language>> = self
1732            .syntax_map
1733            .lock()
1734            .layers_for_range(offset..offset, text, false)
1735            .filter(|layer| {
1736                // For combined injections, check if offset is within the actual sub-ranges.
1737                layer
1738                    .included_sub_ranges
1739                    .is_none_or(|ranges| offset_in_sub_ranges(ranges, offset, text))
1740            })
1741            .map(|info| info.language.clone())
1742            .collect();
1743
1744        if languages.is_empty()
1745            && let Some(buffer_language) = self.language()
1746        {
1747            languages.push(buffer_language.clone());
1748        }
1749
1750        languages
1751    }
1752
1753    /// An integer version number that accounts for all updates besides
1754    /// the buffer's text itself (which is versioned via a version vector).
1755    pub fn non_text_state_update_count(&self) -> usize {
1756        self.non_text_state_update_count
1757    }
1758
1759    /// Whether the buffer is being parsed in the background.
1760    #[cfg(any(test, feature = "test-support"))]
1761    pub fn is_parsing(&self) -> bool {
1762        self.reparse.is_some()
1763    }
1764
1765    /// Indicates whether the buffer contains any regions that may be
1766    /// written in a language that hasn't been loaded yet.
1767    pub fn contains_unknown_injections(&self) -> bool {
1768        self.syntax_map.lock().contains_unknown_injections()
1769    }
1770
1771    /// Sets the sync parse timeout for this buffer.
1772    ///
1773    /// Setting this to `None` disables sync parsing entirely.
1774    pub fn set_sync_parse_timeout(&mut self, timeout: Option<Duration>) {
1775        self.sync_parse_timeout = timeout;
1776    }
1777
1778    fn invalidate_tree_sitter_data(
1779        tree_sitter_data: &mut Arc<TreeSitterData>,
1780        snapshot: &text::BufferSnapshot,
1781    ) {
1782        match Arc::get_mut(tree_sitter_data) {
1783            Some(tree_sitter_data) => tree_sitter_data.clear(snapshot),
1784            None => {
1785                let new_tree_sitter_data = TreeSitterData::new(snapshot);
1786                *tree_sitter_data = Arc::new(new_tree_sitter_data)
1787            }
1788        }
1789    }
1790
1791    /// Called after an edit to synchronize the buffer's main parse tree with
1792    /// the buffer's new underlying state.
1793    ///
1794    /// Locks the syntax map and interpolates the edits since the last reparse
1795    /// into the foreground syntax tree.
1796    ///
1797    /// Then takes a stable snapshot of the syntax map before unlocking it.
1798    /// The snapshot with the interpolated edits is sent to a background thread,
1799    /// where we ask Tree-sitter to perform an incremental parse.
1800    ///
1801    /// Meanwhile, in the foreground if `may_block` is true, we block the main
1802    /// thread for up to 1ms waiting on the parse to complete. As soon as it
1803    /// completes, we proceed synchronously, unless a 1ms timeout elapses.
1804    ///
1805    /// If we time out waiting on the parse, we spawn a second task waiting
1806    /// until the parse does complete and return with the interpolated tree still
1807    /// in the foreground. When the background parse completes, call back into
1808    /// the main thread and assign the foreground parse state.
1809    ///
1810    /// If the buffer or grammar changed since the start of the background parse,
1811    /// initiate an additional reparse recursively. To avoid concurrent parses
1812    /// for the same buffer, we only initiate a new parse if we are not already
1813    /// parsing in the background.
1814    #[ztracing::instrument(skip_all)]
1815    pub fn reparse(&mut self, cx: &mut Context<Self>, may_block: bool) {
1816        if self.text.version() != *self.tree_sitter_data.version() {
1817            Self::invalidate_tree_sitter_data(&mut self.tree_sitter_data, self.text.snapshot());
1818        }
1819        if self.reparse.is_some() {
1820            return;
1821        }
1822        let language = if let Some(language) = self.language.clone() {
1823            language
1824        } else {
1825            return;
1826        };
1827
1828        let text = self.text_snapshot();
1829        let parsed_version = self.version();
1830
1831        let mut syntax_map = self.syntax_map.lock();
1832        syntax_map.interpolate(&text);
1833        let language_registry = syntax_map.language_registry();
1834        let mut syntax_snapshot = syntax_map.snapshot();
1835        drop(syntax_map);
1836
1837        self.parse_status.0.send(ParseStatus::Parsing).unwrap();
1838        if may_block && let Some(sync_parse_timeout) = self.sync_parse_timeout {
1839            if let Ok(()) = syntax_snapshot.reparse_with_timeout(
1840                &text,
1841                language_registry.clone(),
1842                language.clone(),
1843                sync_parse_timeout,
1844            ) {
1845                self.did_finish_parsing(syntax_snapshot, Some(Duration::from_millis(300)), cx);
1846                self.reparse = None;
1847                return;
1848            }
1849        }
1850
1851        let parse_task = cx.background_spawn({
1852            let language = language.clone();
1853            let language_registry = language_registry.clone();
1854            async move {
1855                syntax_snapshot.reparse(&text, language_registry, language);
1856                syntax_snapshot
1857            }
1858        });
1859
1860        self.reparse = Some(cx.spawn(async move |this, cx| {
1861            let new_syntax_map = parse_task.await;
1862            this.update(cx, move |this, cx| {
1863                let grammar_changed = || {
1864                    this.language
1865                        .as_ref()
1866                        .is_none_or(|current_language| !Arc::ptr_eq(&language, current_language))
1867                };
1868                let language_registry_changed = || {
1869                    new_syntax_map.contains_unknown_injections()
1870                        && language_registry.is_some_and(|registry| {
1871                            registry.version() != new_syntax_map.language_registry_version()
1872                        })
1873                };
1874                let parse_again = this.version.changed_since(&parsed_version)
1875                    || language_registry_changed()
1876                    || grammar_changed();
1877                this.did_finish_parsing(new_syntax_map, None, cx);
1878                this.reparse = None;
1879                if parse_again {
1880                    this.reparse(cx, false);
1881                }
1882            })
1883            .ok();
1884        }));
1885    }
1886
1887    fn did_finish_parsing(
1888        &mut self,
1889        syntax_snapshot: SyntaxSnapshot,
1890        block_budget: Option<Duration>,
1891        cx: &mut Context<Self>,
1892    ) {
1893        self.non_text_state_update_count += 1;
1894        self.syntax_map.lock().did_parse(syntax_snapshot);
1895        self.was_changed();
1896        self.request_autoindent(cx, block_budget);
1897        self.parse_status.0.send(ParseStatus::Idle).unwrap();
1898        Self::invalidate_tree_sitter_data(&mut self.tree_sitter_data, &self.text.snapshot());
1899        cx.emit(BufferEvent::Reparsed);
1900        cx.notify();
1901    }
1902
1903    pub fn parse_status(&self) -> watch::Receiver<ParseStatus> {
1904        self.parse_status.1.clone()
1905    }
1906
1907    /// Wait until the buffer is no longer parsing
1908    pub fn parsing_idle(&self) -> impl Future<Output = ()> + use<> {
1909        let mut parse_status = self.parse_status();
1910        async move {
1911            while *parse_status.borrow() != ParseStatus::Idle {
1912                if parse_status.changed().await.is_err() {
1913                    break;
1914                }
1915            }
1916        }
1917    }
1918
1919    /// Assign to the buffer a set of diagnostics created by a given language server.
1920    pub fn update_diagnostics(
1921        &mut self,
1922        server_id: LanguageServerId,
1923        diagnostics: DiagnosticSet,
1924        cx: &mut Context<Self>,
1925    ) {
1926        let lamport_timestamp = self.text.lamport_clock.tick();
1927        let op = Operation::UpdateDiagnostics {
1928            server_id,
1929            diagnostics: diagnostics.iter().cloned().collect(),
1930            lamport_timestamp,
1931        };
1932
1933        self.apply_diagnostic_update(server_id, diagnostics, lamport_timestamp, cx);
1934        self.send_operation(op, true, cx);
1935    }
1936
1937    pub fn buffer_diagnostics(
1938        &self,
1939        for_server: Option<LanguageServerId>,
1940    ) -> Vec<&DiagnosticEntry<Anchor>> {
1941        match for_server {
1942            Some(server_id) => self
1943                .diagnostics
1944                .get(&server_id)
1945                .map_or_else(Vec::new, |diagnostics| diagnostics.iter().collect()),
1946            None => self
1947                .diagnostics
1948                .iter()
1949                .flat_map(|(_, diagnostic_set)| diagnostic_set.iter())
1950                .collect(),
1951        }
1952    }
1953
1954    fn request_autoindent(&mut self, cx: &mut Context<Self>, block_budget: Option<Duration>) {
1955        if let Some(indent_sizes) = self.compute_autoindents() {
1956            let indent_sizes = cx.background_spawn(indent_sizes);
1957            let Some(block_budget) = block_budget else {
1958                self.pending_autoindent = Some(cx.spawn(async move |this, cx| {
1959                    let indent_sizes = indent_sizes.await;
1960                    this.update(cx, |this, cx| {
1961                        this.apply_autoindents(indent_sizes, cx);
1962                    })
1963                    .ok();
1964                }));
1965                return;
1966            };
1967            match cx
1968                .foreground_executor()
1969                .block_with_timeout(block_budget, indent_sizes)
1970            {
1971                Ok(indent_sizes) => self.apply_autoindents(indent_sizes, cx),
1972                Err(indent_sizes) => {
1973                    self.pending_autoindent = Some(cx.spawn(async move |this, cx| {
1974                        let indent_sizes = indent_sizes.await;
1975                        this.update(cx, |this, cx| {
1976                            this.apply_autoindents(indent_sizes, cx);
1977                        })
1978                        .ok();
1979                    }));
1980                }
1981            }
1982        } else {
1983            self.autoindent_requests.clear();
1984            for tx in self.wait_for_autoindent_txs.drain(..) {
1985                tx.send(()).ok();
1986            }
1987        }
1988    }
1989
1990    fn compute_autoindents(
1991        &self,
1992    ) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>> + use<>> {
1993        let max_rows_between_yields = 100;
1994        let snapshot = self.snapshot();
1995        if snapshot.syntax.is_empty() || self.autoindent_requests.is_empty() {
1996            return None;
1997        }
1998
1999        let autoindent_requests = self.autoindent_requests.clone();
2000        Some(async move {
2001            let mut indent_sizes = BTreeMap::<u32, (IndentSize, bool)>::new();
2002            for request in autoindent_requests {
2003                // Resolve each edited range to its row in the current buffer and in the
2004                // buffer before this batch of edits.
2005                let mut row_ranges = Vec::new();
2006                let mut old_to_new_rows = BTreeMap::new();
2007                let mut language_indent_sizes_by_new_row = Vec::new();
2008                for entry in &request.entries {
2009                    let position = entry.range.start;
2010                    let new_row = position.to_point(&snapshot).row;
2011                    let new_end_row = entry.range.end.to_point(&snapshot).row + 1;
2012                    language_indent_sizes_by_new_row.push((new_row, entry.indent_size));
2013
2014                    if let Some(old_row) = entry.old_row {
2015                        old_to_new_rows.insert(old_row, new_row);
2016                    }
2017                    row_ranges.push((new_row..new_end_row, entry.original_indent_column));
2018                }
2019
2020                // Build a map containing the suggested indentation for each of the edited lines
2021                // with respect to the state of the buffer before these edits. This map is keyed
2022                // by the rows for these lines in the current state of the buffer.
2023                let mut old_suggestions = BTreeMap::<u32, (IndentSize, bool)>::default();
2024                let old_edited_ranges =
2025                    contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
2026                let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
2027                let mut language_indent_size = IndentSize::default();
2028                for old_edited_range in old_edited_ranges {
2029                    let suggestions = request
2030                        .before_edit
2031                        .suggest_autoindents(old_edited_range.clone())
2032                        .into_iter()
2033                        .flatten();
2034                    for (old_row, suggestion) in old_edited_range.zip(suggestions) {
2035                        if let Some(suggestion) = suggestion {
2036                            let new_row = *old_to_new_rows.get(&old_row).unwrap();
2037
2038                            // Find the indent size based on the language for this row.
2039                            while let Some((row, size)) = language_indent_sizes.peek() {
2040                                if *row > new_row {
2041                                    break;
2042                                }
2043                                language_indent_size = *size;
2044                                language_indent_sizes.next();
2045                            }
2046
2047                            let suggested_indent = old_to_new_rows
2048                                .get(&suggestion.basis_row)
2049                                .and_then(|from_row| {
2050                                    Some(old_suggestions.get(from_row).copied()?.0)
2051                                })
2052                                .unwrap_or_else(|| {
2053                                    request
2054                                        .before_edit
2055                                        .indent_size_for_line(suggestion.basis_row)
2056                                })
2057                                .with_delta(suggestion.delta, language_indent_size);
2058                            old_suggestions
2059                                .insert(new_row, (suggested_indent, suggestion.within_error));
2060                        }
2061                    }
2062                    yield_now().await;
2063                }
2064
2065                // Compute new suggestions for each line, but only include them in the result
2066                // if they differ from the old suggestion for that line.
2067                let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
2068                let mut language_indent_size = IndentSize::default();
2069                for (row_range, original_indent_column) in row_ranges {
2070                    let new_edited_row_range = if request.is_block_mode {
2071                        row_range.start..row_range.start + 1
2072                    } else {
2073                        row_range.clone()
2074                    };
2075
2076                    let suggestions = snapshot
2077                        .suggest_autoindents(new_edited_row_range.clone())
2078                        .into_iter()
2079                        .flatten();
2080                    for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
2081                        if let Some(suggestion) = suggestion {
2082                            // Find the indent size based on the language for this row.
2083                            while let Some((row, size)) = language_indent_sizes.peek() {
2084                                if *row > new_row {
2085                                    break;
2086                                }
2087                                language_indent_size = *size;
2088                                language_indent_sizes.next();
2089                            }
2090
2091                            let suggested_indent = indent_sizes
2092                                .get(&suggestion.basis_row)
2093                                .copied()
2094                                .map(|e| e.0)
2095                                .unwrap_or_else(|| {
2096                                    snapshot.indent_size_for_line(suggestion.basis_row)
2097                                })
2098                                .with_delta(suggestion.delta, language_indent_size);
2099
2100                            if old_suggestions.get(&new_row).is_none_or(
2101                                |(old_indentation, was_within_error)| {
2102                                    suggested_indent != *old_indentation
2103                                        && (!suggestion.within_error || *was_within_error)
2104                                },
2105                            ) {
2106                                indent_sizes.insert(
2107                                    new_row,
2108                                    (suggested_indent, request.ignore_empty_lines),
2109                                );
2110                            }
2111                        }
2112                    }
2113
2114                    if let (true, Some(original_indent_column)) =
2115                        (request.is_block_mode, original_indent_column)
2116                    {
2117                        let new_indent =
2118                            if let Some((indent, _)) = indent_sizes.get(&row_range.start) {
2119                                *indent
2120                            } else {
2121                                snapshot.indent_size_for_line(row_range.start)
2122                            };
2123                        let delta = new_indent.len as i64 - original_indent_column as i64;
2124                        if delta != 0 {
2125                            for row in row_range.skip(1) {
2126                                indent_sizes.entry(row).or_insert_with(|| {
2127                                    let mut size = snapshot.indent_size_for_line(row);
2128                                    if size.kind == new_indent.kind {
2129                                        match delta.cmp(&0) {
2130                                            Ordering::Greater => size.len += delta as u32,
2131                                            Ordering::Less => {
2132                                                size.len = size.len.saturating_sub(-delta as u32)
2133                                            }
2134                                            Ordering::Equal => {}
2135                                        }
2136                                    }
2137                                    (size, request.ignore_empty_lines)
2138                                });
2139                            }
2140                        }
2141                    }
2142
2143                    yield_now().await;
2144                }
2145            }
2146
2147            indent_sizes
2148                .into_iter()
2149                .filter_map(|(row, (indent, ignore_empty_lines))| {
2150                    if ignore_empty_lines && snapshot.line_len(row) == 0 {
2151                        None
2152                    } else {
2153                        Some((row, indent))
2154                    }
2155                })
2156                .collect()
2157        })
2158    }
2159
2160    fn apply_autoindents(
2161        &mut self,
2162        indent_sizes: BTreeMap<u32, IndentSize>,
2163        cx: &mut Context<Self>,
2164    ) {
2165        self.autoindent_requests.clear();
2166        for tx in self.wait_for_autoindent_txs.drain(..) {
2167            tx.send(()).ok();
2168        }
2169
2170        let edits: Vec<_> = indent_sizes
2171            .into_iter()
2172            .filter_map(|(row, indent_size)| {
2173                let current_size = indent_size_for_line(self, row);
2174                Self::edit_for_indent_size_adjustment(row, current_size, indent_size)
2175            })
2176            .collect();
2177
2178        let preserve_preview = self.preserve_preview();
2179        self.edit(edits, None, cx);
2180        if preserve_preview {
2181            self.refresh_preview();
2182        }
2183    }
2184
2185    /// Create a minimal edit that will cause the given row to be indented
2186    /// with the given size. After applying this edit, the length of the line
2187    /// will always be at least `new_size.len`.
2188    pub fn edit_for_indent_size_adjustment(
2189        row: u32,
2190        current_size: IndentSize,
2191        new_size: IndentSize,
2192    ) -> Option<(Range<Point>, String)> {
2193        if new_size.kind == current_size.kind {
2194            match new_size.len.cmp(&current_size.len) {
2195                Ordering::Greater => {
2196                    let point = Point::new(row, 0);
2197                    Some((
2198                        point..point,
2199                        iter::repeat(new_size.char())
2200                            .take((new_size.len - current_size.len) as usize)
2201                            .collect::<String>(),
2202                    ))
2203                }
2204
2205                Ordering::Less => Some((
2206                    Point::new(row, 0)..Point::new(row, current_size.len - new_size.len),
2207                    String::new(),
2208                )),
2209
2210                Ordering::Equal => None,
2211            }
2212        } else {
2213            Some((
2214                Point::new(row, 0)..Point::new(row, current_size.len),
2215                iter::repeat(new_size.char())
2216                    .take(new_size.len as usize)
2217                    .collect::<String>(),
2218            ))
2219        }
2220    }
2221
2222    /// Spawns a background task that asynchronously computes a `Diff` between the buffer's text
2223    /// and the given new text.
2224    pub fn diff<T>(&self, new_text: T, cx: &App) -> Task<Diff>
2225    where
2226        T: AsRef<str> + Send + 'static,
2227    {
2228        let old_text = self.as_rope().clone();
2229        let base_version = self.version();
2230        cx.background_spawn(async move {
2231            let old_text = old_text.to_string();
2232            let mut new_text = new_text.as_ref().to_owned();
2233            let line_ending = LineEnding::detect(&new_text);
2234            LineEnding::normalize(&mut new_text);
2235            let edits = text_diff(&old_text, &new_text);
2236            Diff {
2237                base_version,
2238                line_ending,
2239                edits,
2240            }
2241        })
2242    }
2243
2244    /// Spawns a background task that searches the buffer for any whitespace
2245    /// at the ends of a lines, and returns a `Diff` that removes that whitespace.
2246    pub fn remove_trailing_whitespace(&self, cx: &App) -> Task<Diff> {
2247        let old_text = self.as_rope().clone();
2248        let line_ending = self.line_ending();
2249        let base_version = self.version();
2250        cx.background_spawn(async move {
2251            let ranges = trailing_whitespace_ranges(&old_text);
2252            let empty = Arc::<str>::from("");
2253            Diff {
2254                base_version,
2255                line_ending,
2256                edits: ranges
2257                    .into_iter()
2258                    .map(|range| (range, empty.clone()))
2259                    .collect(),
2260            }
2261        })
2262    }
2263
2264    /// Ensures that the buffer ends with a single newline character, and
2265    /// no other whitespace. Skips if the buffer is empty.
2266    pub fn ensure_final_newline(&mut self, cx: &mut Context<Self>) {
2267        let len = self.len();
2268        if len == 0 {
2269            return;
2270        }
2271        let mut offset = len;
2272        for chunk in self.as_rope().reversed_chunks_in_range(0..len) {
2273            let non_whitespace_len = chunk
2274                .trim_end_matches(|c: char| c.is_ascii_whitespace())
2275                .len();
2276            offset -= chunk.len();
2277            offset += non_whitespace_len;
2278            if non_whitespace_len != 0 {
2279                if offset == len - 1 && chunk.get(non_whitespace_len..) == Some("\n") {
2280                    return;
2281                }
2282                break;
2283            }
2284        }
2285        self.edit([(offset..len, "\n")], None, cx);
2286    }
2287
2288    /// Applies a diff to the buffer. If the buffer has changed since the given diff was
2289    /// calculated, then adjust the diff to account for those changes, and discard any
2290    /// parts of the diff that conflict with those changes.
2291    pub fn apply_diff(&mut self, diff: Diff, cx: &mut Context<Self>) -> Option<TransactionId> {
2292        let snapshot = self.snapshot();
2293        let mut edits_since = snapshot.edits_since::<usize>(&diff.base_version).peekable();
2294        let mut delta = 0;
2295        let adjusted_edits = diff.edits.into_iter().filter_map(|(range, new_text)| {
2296            while let Some(edit_since) = edits_since.peek() {
2297                // If the edit occurs after a diff hunk, then it does not
2298                // affect that hunk.
2299                if edit_since.old.start > range.end {
2300                    break;
2301                }
2302                // If the edit precedes the diff hunk, then adjust the hunk
2303                // to reflect the edit.
2304                else if edit_since.old.end < range.start {
2305                    delta += edit_since.new_len() as i64 - edit_since.old_len() as i64;
2306                    edits_since.next();
2307                }
2308                // If the edit intersects a diff hunk, then discard that hunk.
2309                else {
2310                    return None;
2311                }
2312            }
2313
2314            let start = (range.start as i64 + delta) as usize;
2315            let end = (range.end as i64 + delta) as usize;
2316            Some((start..end, new_text))
2317        });
2318
2319        self.start_transaction();
2320        self.text.set_line_ending(diff.line_ending);
2321        self.edit(adjusted_edits, None, cx);
2322        self.end_transaction(cx)
2323    }
2324
2325    pub fn has_unsaved_edits(&self) -> bool {
2326        let (last_version, has_unsaved_edits) = self.has_unsaved_edits.take();
2327
2328        if last_version == self.version {
2329            self.has_unsaved_edits
2330                .set((last_version, has_unsaved_edits));
2331            return has_unsaved_edits;
2332        }
2333
2334        let has_edits = self.has_edits_since(&self.saved_version);
2335        self.has_unsaved_edits
2336            .set((self.version.clone(), has_edits));
2337        has_edits
2338    }
2339
2340    /// Checks if the buffer has unsaved changes.
2341    pub fn is_dirty(&self) -> bool {
2342        if self.capability == Capability::ReadOnly {
2343            return false;
2344        }
2345        if self.has_conflict {
2346            return true;
2347        }
2348        match self.file.as_ref().map(|f| f.disk_state()) {
2349            Some(DiskState::New) | Some(DiskState::Deleted) => {
2350                !self.is_empty() && self.has_unsaved_edits()
2351            }
2352            _ => self.has_unsaved_edits(),
2353        }
2354    }
2355
2356    /// Marks the buffer as having a conflict regardless of current buffer state.
2357    pub fn set_conflict(&mut self) {
2358        self.has_conflict = true;
2359    }
2360
2361    /// Checks if the buffer and its file have both changed since the buffer
2362    /// was last saved or reloaded.
2363    pub fn has_conflict(&self) -> bool {
2364        if self.has_conflict {
2365            return true;
2366        }
2367        let Some(file) = self.file.as_ref() else {
2368            return false;
2369        };
2370        match file.disk_state() {
2371            DiskState::New => false,
2372            DiskState::Present { mtime, .. } => match self.saved_mtime {
2373                Some(saved_mtime) => {
2374                    mtime.bad_is_greater_than(saved_mtime) && self.has_unsaved_edits()
2375                }
2376                None => true,
2377            },
2378            DiskState::Deleted => false,
2379            DiskState::Historic { .. } => false,
2380        }
2381    }
2382
2383    /// Gets a [`Subscription`] that tracks all of the changes to the buffer's text.
2384    pub fn subscribe(&mut self) -> Subscription<usize> {
2385        self.text.subscribe()
2386    }
2387
2388    /// Adds a bit to the list of bits that are set when the buffer's text changes.
2389    ///
2390    /// This allows downstream code to check if the buffer's text has changed without
2391    /// waiting for an effect cycle, which would be required if using eents.
2392    pub fn record_changes(&mut self, bit: rc::Weak<Cell<bool>>) {
2393        if let Err(ix) = self
2394            .change_bits
2395            .binary_search_by_key(&rc::Weak::as_ptr(&bit), rc::Weak::as_ptr)
2396        {
2397            self.change_bits.insert(ix, bit);
2398        }
2399    }
2400
2401    /// Set the change bit for all "listeners".
2402    fn was_changed(&mut self) {
2403        self.change_bits.retain(|change_bit| {
2404            change_bit
2405                .upgrade()
2406                .inspect(|bit| {
2407                    _ = bit.replace(true);
2408                })
2409                .is_some()
2410        });
2411    }
2412
2413    /// Starts a transaction, if one is not already in-progress. When undoing or
2414    /// redoing edits, all of the edits performed within a transaction are undone
2415    /// or redone together.
2416    pub fn start_transaction(&mut self) -> Option<TransactionId> {
2417        self.start_transaction_at(Instant::now())
2418    }
2419
2420    /// Starts a transaction, providing the current time. Subsequent transactions
2421    /// that occur within a short period of time will be grouped together. This
2422    /// is controlled by the buffer's undo grouping duration.
2423    pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
2424        self.transaction_depth += 1;
2425        if self.was_dirty_before_starting_transaction.is_none() {
2426            self.was_dirty_before_starting_transaction = Some(self.is_dirty());
2427        }
2428        self.text.start_transaction_at(now)
2429    }
2430
2431    /// Terminates the current transaction, if this is the outermost transaction.
2432    pub fn end_transaction(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
2433        self.end_transaction_at(Instant::now(), cx)
2434    }
2435
2436    /// Terminates the current transaction, providing the current time. Subsequent transactions
2437    /// that occur within a short period of time will be grouped together. This
2438    /// is controlled by the buffer's undo grouping duration.
2439    pub fn end_transaction_at(
2440        &mut self,
2441        now: Instant,
2442        cx: &mut Context<Self>,
2443    ) -> Option<TransactionId> {
2444        assert!(self.transaction_depth > 0);
2445        self.transaction_depth -= 1;
2446        let was_dirty = if self.transaction_depth == 0 {
2447            self.was_dirty_before_starting_transaction.take().unwrap()
2448        } else {
2449            false
2450        };
2451        if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
2452            self.did_edit(&start_version, was_dirty, true, cx);
2453            Some(transaction_id)
2454        } else {
2455            None
2456        }
2457    }
2458
2459    /// Manually add a transaction to the buffer's undo history.
2460    pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
2461        self.text.push_transaction(transaction, now);
2462    }
2463
2464    /// Differs from `push_transaction` in that it does not clear the redo
2465    /// stack. Intended to be used to create a parent transaction to merge
2466    /// potential child transactions into.
2467    ///
2468    /// The caller is responsible for removing it from the undo history using
2469    /// `forget_transaction` if no edits are merged into it. Otherwise, if edits
2470    /// are merged into this transaction, the caller is responsible for ensuring
2471    /// the redo stack is cleared. The easiest way to ensure the redo stack is
2472    /// cleared is to create transactions with the usual `start_transaction` and
2473    /// `end_transaction` methods and merging the resulting transactions into
2474    /// the transaction created by this method
2475    pub fn push_empty_transaction(&mut self, now: Instant) -> TransactionId {
2476        self.text.push_empty_transaction(now)
2477    }
2478
2479    /// Prevent the last transaction from being grouped with any subsequent transactions,
2480    /// even if they occur with the buffer's undo grouping duration.
2481    pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
2482        self.text.finalize_last_transaction()
2483    }
2484
2485    /// Manually group all changes since a given transaction.
2486    pub fn group_until_transaction(&mut self, transaction_id: TransactionId) {
2487        self.text.group_until_transaction(transaction_id);
2488    }
2489
2490    /// Manually remove a transaction from the buffer's undo history
2491    pub fn forget_transaction(&mut self, transaction_id: TransactionId) -> Option<Transaction> {
2492        self.text.forget_transaction(transaction_id)
2493    }
2494
2495    /// Retrieve a transaction from the buffer's undo history
2496    pub fn get_transaction(&self, transaction_id: TransactionId) -> Option<&Transaction> {
2497        self.text.get_transaction(transaction_id)
2498    }
2499
2500    /// Manually merge two transactions in the buffer's undo history.
2501    pub fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) {
2502        self.text.merge_transactions(transaction, destination);
2503    }
2504
2505    /// Waits for the buffer to receive operations with the given timestamps.
2506    pub fn wait_for_edits<It: IntoIterator<Item = clock::Lamport>>(
2507        &mut self,
2508        edit_ids: It,
2509    ) -> impl Future<Output = Result<()>> + use<It> {
2510        self.text.wait_for_edits(edit_ids)
2511    }
2512
2513    /// Waits for the buffer to receive the operations necessary for resolving the given anchors.
2514    pub fn wait_for_anchors<It: IntoIterator<Item = Anchor>>(
2515        &mut self,
2516        anchors: It,
2517    ) -> impl 'static + Future<Output = Result<()>> + use<It> {
2518        self.text.wait_for_anchors(anchors)
2519    }
2520
2521    /// Waits for the buffer to receive operations up to the given version.
2522    pub fn wait_for_version(
2523        &mut self,
2524        version: clock::Global,
2525    ) -> impl Future<Output = Result<()>> + use<> {
2526        self.text.wait_for_version(version)
2527    }
2528
2529    /// Forces all futures returned by [`Buffer::wait_for_version`], [`Buffer::wait_for_edits`], or
2530    /// [`Buffer::wait_for_version`] to resolve with an error.
2531    pub fn give_up_waiting(&mut self) {
2532        self.text.give_up_waiting();
2533    }
2534
2535    pub fn wait_for_autoindent_applied(&mut self) -> Option<oneshot::Receiver<()>> {
2536        let mut rx = None;
2537        if !self.autoindent_requests.is_empty() {
2538            let channel = oneshot::channel();
2539            self.wait_for_autoindent_txs.push(channel.0);
2540            rx = Some(channel.1);
2541        }
2542        rx
2543    }
2544
2545    /// Stores a set of selections that should be broadcasted to all of the buffer's replicas.
2546    pub fn set_active_selections(
2547        &mut self,
2548        selections: Arc<[Selection<Anchor>]>,
2549        line_mode: bool,
2550        cursor_shape: CursorShape,
2551        cx: &mut Context<Self>,
2552    ) {
2553        let lamport_timestamp = self.text.lamport_clock.tick();
2554        self.remote_selections.insert(
2555            self.text.replica_id(),
2556            SelectionSet {
2557                selections: selections.clone(),
2558                lamport_timestamp,
2559                line_mode,
2560                cursor_shape,
2561            },
2562        );
2563        self.send_operation(
2564            Operation::UpdateSelections {
2565                selections,
2566                line_mode,
2567                lamport_timestamp,
2568                cursor_shape,
2569            },
2570            true,
2571            cx,
2572        );
2573        self.non_text_state_update_count += 1;
2574        cx.notify();
2575    }
2576
2577    /// Clears the selections, so that other replicas of the buffer do not see any selections for
2578    /// this replica.
2579    pub fn remove_active_selections(&mut self, cx: &mut Context<Self>) {
2580        if self
2581            .remote_selections
2582            .get(&self.text.replica_id())
2583            .is_none_or(|set| !set.selections.is_empty())
2584        {
2585            self.set_active_selections(Arc::default(), false, Default::default(), cx);
2586        }
2587    }
2588
2589    pub fn set_agent_selections(
2590        &mut self,
2591        selections: Arc<[Selection<Anchor>]>,
2592        line_mode: bool,
2593        cursor_shape: CursorShape,
2594        cx: &mut Context<Self>,
2595    ) {
2596        let lamport_timestamp = self.text.lamport_clock.tick();
2597        self.remote_selections.insert(
2598            ReplicaId::AGENT,
2599            SelectionSet {
2600                selections,
2601                lamport_timestamp,
2602                line_mode,
2603                cursor_shape,
2604            },
2605        );
2606        self.non_text_state_update_count += 1;
2607        cx.notify();
2608    }
2609
2610    pub fn remove_agent_selections(&mut self, cx: &mut Context<Self>) {
2611        self.set_agent_selections(Arc::default(), false, Default::default(), cx);
2612    }
2613
2614    /// Replaces the buffer's entire text.
2615    pub fn set_text<T>(&mut self, text: T, cx: &mut Context<Self>) -> Option<clock::Lamport>
2616    where
2617        T: Into<Arc<str>>,
2618    {
2619        self.autoindent_requests.clear();
2620        self.edit([(0..self.len(), text)], None, cx)
2621    }
2622
2623    /// Appends the given text to the end of the buffer.
2624    pub fn append<T>(&mut self, text: T, cx: &mut Context<Self>) -> Option<clock::Lamport>
2625    where
2626        T: Into<Arc<str>>,
2627    {
2628        self.edit([(self.len()..self.len(), text)], None, cx)
2629    }
2630
2631    /// Applies the given edits to the buffer. Each edit is specified as a range of text to
2632    /// delete, and a string of text to insert at that location. Adjacent edits are coalesced.
2633    ///
2634    /// If an [`AutoindentMode`] is provided, then the buffer will enqueue an auto-indent
2635    /// request for the edited ranges, which will be processed when the buffer finishes
2636    /// parsing.
2637    ///
2638    /// Parsing takes place at the end of a transaction, and may compute synchronously
2639    /// or asynchronously, depending on the changes.
2640    pub fn edit<I, S, T>(
2641        &mut self,
2642        edits_iter: I,
2643        autoindent_mode: Option<AutoindentMode>,
2644        cx: &mut Context<Self>,
2645    ) -> Option<clock::Lamport>
2646    where
2647        I: IntoIterator<Item = (Range<S>, T)>,
2648        S: ToOffset,
2649        T: Into<Arc<str>>,
2650    {
2651        self.edit_internal(edits_iter, autoindent_mode, true, cx)
2652    }
2653
2654    /// Like [`edit`](Self::edit), but does not coalesce adjacent edits.
2655    pub fn edit_non_coalesce<I, S, T>(
2656        &mut self,
2657        edits_iter: I,
2658        autoindent_mode: Option<AutoindentMode>,
2659        cx: &mut Context<Self>,
2660    ) -> Option<clock::Lamport>
2661    where
2662        I: IntoIterator<Item = (Range<S>, T)>,
2663        S: ToOffset,
2664        T: Into<Arc<str>>,
2665    {
2666        self.edit_internal(edits_iter, autoindent_mode, false, cx)
2667    }
2668
2669    fn edit_internal<I, S, T>(
2670        &mut self,
2671        edits_iter: I,
2672        autoindent_mode: Option<AutoindentMode>,
2673        coalesce_adjacent: bool,
2674        cx: &mut Context<Self>,
2675    ) -> Option<clock::Lamport>
2676    where
2677        I: IntoIterator<Item = (Range<S>, T)>,
2678        S: ToOffset,
2679        T: Into<Arc<str>>,
2680    {
2681        // Skip invalid edits and coalesce contiguous ones.
2682        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
2683
2684        for (range, new_text) in edits_iter {
2685            let mut range = range.start.to_offset(self)..range.end.to_offset(self);
2686
2687            if range.start > range.end {
2688                mem::swap(&mut range.start, &mut range.end);
2689            }
2690            let new_text = new_text.into();
2691            if !new_text.is_empty() || !range.is_empty() {
2692                let prev_edit = edits.last_mut();
2693                let should_coalesce = prev_edit.as_ref().is_some_and(|(prev_range, _)| {
2694                    if coalesce_adjacent {
2695                        prev_range.end >= range.start
2696                    } else {
2697                        prev_range.end > range.start
2698                    }
2699                });
2700
2701                if let Some((prev_range, prev_text)) = prev_edit
2702                    && should_coalesce
2703                {
2704                    prev_range.end = cmp::max(prev_range.end, range.end);
2705                    *prev_text = format!("{prev_text}{new_text}").into();
2706                } else {
2707                    edits.push((range, new_text));
2708                }
2709            }
2710        }
2711        if edits.is_empty() {
2712            return None;
2713        }
2714
2715        self.start_transaction();
2716        self.pending_autoindent.take();
2717        let autoindent_request = autoindent_mode
2718            .and_then(|mode| self.language.as_ref().map(|_| (self.snapshot(), mode)));
2719
2720        let edit_operation = self.text.edit(edits.iter().cloned());
2721        let edit_id = edit_operation.timestamp();
2722
2723        if let Some((before_edit, mode)) = autoindent_request {
2724            let mut delta = 0isize;
2725            let mut previous_setting = None;
2726            let entries: Vec<_> = edits
2727                .into_iter()
2728                .enumerate()
2729                .zip(&edit_operation.as_edit().unwrap().new_text)
2730                .filter(|((_, (range, _)), _)| {
2731                    let language = before_edit.language_at(range.start);
2732                    let language_id = language.map(|l| l.id());
2733                    if let Some((cached_language_id, apply_syntax_indent)) = previous_setting
2734                        && cached_language_id == language_id
2735                    {
2736                        apply_syntax_indent
2737                    } else {
2738                        // The auto-indent setting is not present in editorconfigs, hence
2739                        // we can avoid passing the file here.
2740                        let auto_indent_mode = LanguageSettings::resolve(
2741                            None,
2742                            language.map(|l| l.name()).as_ref(),
2743                            cx,
2744                        )
2745                        .auto_indent;
2746                        let apply_syntax_indent = auto_indent_mode == AutoIndentMode::SyntaxAware;
2747                        previous_setting = Some((language_id, apply_syntax_indent));
2748                        apply_syntax_indent
2749                    }
2750                })
2751                .map(|((ix, (range, _)), new_text)| {
2752                    let new_text_length = new_text.len();
2753                    let old_start = range.start.to_point(&before_edit);
2754                    let new_start = (delta + range.start as isize) as usize;
2755                    let range_len = range.end - range.start;
2756                    delta += new_text_length as isize - range_len as isize;
2757
2758                    // Decide what range of the insertion to auto-indent, and whether
2759                    // the first line of the insertion should be considered a newly-inserted line
2760                    // or an edit to an existing line.
2761                    let mut range_of_insertion_to_indent = 0..new_text_length;
2762                    let mut first_line_is_new = true;
2763
2764                    let old_line_start = before_edit.indent_size_for_line(old_start.row).len;
2765                    let old_line_end = before_edit.line_len(old_start.row);
2766
2767                    if old_start.column > old_line_start {
2768                        first_line_is_new = false;
2769                    }
2770
2771                    if !new_text.contains('\n')
2772                        && (old_start.column + (range_len as u32) < old_line_end
2773                            || old_line_end == old_line_start)
2774                    {
2775                        first_line_is_new = false;
2776                    }
2777
2778                    // When inserting text starting with a newline, avoid auto-indenting the
2779                    // previous line.
2780                    if new_text.starts_with('\n') {
2781                        range_of_insertion_to_indent.start += 1;
2782                        first_line_is_new = true;
2783                    }
2784
2785                    let mut original_indent_column = None;
2786                    if let AutoindentMode::Block {
2787                        original_indent_columns,
2788                    } = &mode
2789                    {
2790                        original_indent_column = Some(if new_text.starts_with('\n') {
2791                            indent_size_for_text(
2792                                new_text[range_of_insertion_to_indent.clone()].chars(),
2793                            )
2794                            .len
2795                        } else {
2796                            original_indent_columns
2797                                .get(ix)
2798                                .copied()
2799                                .flatten()
2800                                .unwrap_or_else(|| {
2801                                    indent_size_for_text(
2802                                        new_text[range_of_insertion_to_indent.clone()].chars(),
2803                                    )
2804                                    .len
2805                                })
2806                        });
2807
2808                        // Avoid auto-indenting the line after the edit.
2809                        if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
2810                            range_of_insertion_to_indent.end -= 1;
2811                        }
2812                    }
2813
2814                    AutoindentRequestEntry {
2815                        original_indent_column,
2816                        old_row: if first_line_is_new {
2817                            None
2818                        } else {
2819                            Some(old_start.row)
2820                        },
2821                        indent_size: before_edit.language_indent_size_at(range.start, cx),
2822                        range: self.anchor_before(new_start + range_of_insertion_to_indent.start)
2823                            ..self.anchor_after(new_start + range_of_insertion_to_indent.end),
2824                    }
2825                })
2826                .collect();
2827
2828            if !entries.is_empty() {
2829                self.autoindent_requests.push(Arc::new(AutoindentRequest {
2830                    before_edit,
2831                    entries,
2832                    is_block_mode: matches!(mode, AutoindentMode::Block { .. }),
2833                    ignore_empty_lines: false,
2834                }));
2835            }
2836        }
2837
2838        self.end_transaction(cx);
2839        self.send_operation(Operation::Buffer(edit_operation), true, cx);
2840        Some(edit_id)
2841    }
2842
2843    fn did_edit(
2844        &mut self,
2845        old_version: &clock::Global,
2846        was_dirty: bool,
2847        is_local: bool,
2848        cx: &mut Context<Self>,
2849    ) {
2850        self.was_changed();
2851
2852        if self.edits_since::<usize>(old_version).next().is_none() {
2853            return;
2854        }
2855
2856        self.reparse(cx, true);
2857        cx.emit(BufferEvent::Edited { is_local });
2858        let is_dirty = self.is_dirty();
2859        if was_dirty != is_dirty {
2860            cx.emit(BufferEvent::DirtyChanged);
2861        }
2862        if was_dirty && !is_dirty {
2863            if let Some(file) = self.file.as_ref() {
2864                if matches!(file.disk_state(), DiskState::Present { .. })
2865                    && file.disk_state().mtime() != self.saved_mtime
2866                {
2867                    cx.emit(BufferEvent::ReloadNeeded);
2868                }
2869            }
2870        }
2871        cx.notify();
2872    }
2873
2874    pub fn autoindent_ranges<I, T>(&mut self, ranges: I, cx: &mut Context<Self>)
2875    where
2876        I: IntoIterator<Item = Range<T>>,
2877        T: ToOffset + Copy,
2878    {
2879        let before_edit = self.snapshot();
2880        let entries = ranges
2881            .into_iter()
2882            .map(|range| AutoindentRequestEntry {
2883                range: before_edit.anchor_before(range.start)..before_edit.anchor_after(range.end),
2884                old_row: None,
2885                indent_size: before_edit.language_indent_size_at(range.start, cx),
2886                original_indent_column: None,
2887            })
2888            .collect();
2889        self.autoindent_requests.push(Arc::new(AutoindentRequest {
2890            before_edit,
2891            entries,
2892            is_block_mode: false,
2893            ignore_empty_lines: true,
2894        }));
2895        self.request_autoindent(cx, Some(Duration::from_micros(300)));
2896    }
2897
2898    // Inserts newlines at the given position to create an empty line, returning the start of the new line.
2899    // You can also request the insertion of empty lines above and below the line starting at the returned point.
2900    pub fn insert_empty_line(
2901        &mut self,
2902        position: impl ToPoint,
2903        space_above: bool,
2904        space_below: bool,
2905        cx: &mut Context<Self>,
2906    ) -> Point {
2907        let mut position = position.to_point(self);
2908
2909        self.start_transaction();
2910
2911        self.edit(
2912            [(position..position, "\n")],
2913            Some(AutoindentMode::EachLine),
2914            cx,
2915        );
2916
2917        if position.column > 0 {
2918            position += Point::new(1, 0);
2919        }
2920
2921        if !self.is_line_blank(position.row) {
2922            self.edit(
2923                [(position..position, "\n")],
2924                Some(AutoindentMode::EachLine),
2925                cx,
2926            );
2927        }
2928
2929        if space_above && position.row > 0 && !self.is_line_blank(position.row - 1) {
2930            self.edit(
2931                [(position..position, "\n")],
2932                Some(AutoindentMode::EachLine),
2933                cx,
2934            );
2935            position.row += 1;
2936        }
2937
2938        if space_below
2939            && (position.row == self.max_point().row || !self.is_line_blank(position.row + 1))
2940        {
2941            self.edit(
2942                [(position..position, "\n")],
2943                Some(AutoindentMode::EachLine),
2944                cx,
2945            );
2946        }
2947
2948        self.end_transaction(cx);
2949
2950        position
2951    }
2952
2953    /// Applies the given remote operations to the buffer.
2954    pub fn apply_ops<I: IntoIterator<Item = Operation>>(&mut self, ops: I, cx: &mut Context<Self>) {
2955        self.pending_autoindent.take();
2956        let was_dirty = self.is_dirty();
2957        let old_version = self.version.clone();
2958        let mut deferred_ops = Vec::new();
2959        let buffer_ops = ops
2960            .into_iter()
2961            .filter_map(|op| match op {
2962                Operation::Buffer(op) => Some(op),
2963                _ => {
2964                    if self.can_apply_op(&op) {
2965                        self.apply_op(op, cx);
2966                    } else {
2967                        deferred_ops.push(op);
2968                    }
2969                    None
2970                }
2971            })
2972            .collect::<Vec<_>>();
2973        for operation in buffer_ops.iter() {
2974            self.send_operation(Operation::Buffer(operation.clone()), false, cx);
2975        }
2976        self.text.apply_ops(buffer_ops);
2977        self.deferred_ops.insert(deferred_ops);
2978        self.flush_deferred_ops(cx);
2979        self.did_edit(&old_version, was_dirty, false, cx);
2980        // Notify independently of whether the buffer was edited as the operations could include a
2981        // selection update.
2982        cx.notify();
2983    }
2984
2985    fn flush_deferred_ops(&mut self, cx: &mut Context<Self>) {
2986        let mut deferred_ops = Vec::new();
2987        for op in self.deferred_ops.drain().iter().cloned() {
2988            if self.can_apply_op(&op) {
2989                self.apply_op(op, cx);
2990            } else {
2991                deferred_ops.push(op);
2992            }
2993        }
2994        self.deferred_ops.insert(deferred_ops);
2995    }
2996
2997    pub fn has_deferred_ops(&self) -> bool {
2998        !self.deferred_ops.is_empty() || self.text.has_deferred_ops()
2999    }
3000
3001    fn can_apply_op(&self, operation: &Operation) -> bool {
3002        match operation {
3003            Operation::Buffer(_) => {
3004                unreachable!("buffer operations should never be applied at this layer")
3005            }
3006            Operation::UpdateDiagnostics {
3007                diagnostics: diagnostic_set,
3008                ..
3009            } => diagnostic_set.iter().all(|diagnostic| {
3010                self.text.can_resolve(&diagnostic.range.start)
3011                    && self.text.can_resolve(&diagnostic.range.end)
3012            }),
3013            Operation::UpdateSelections { selections, .. } => selections
3014                .iter()
3015                .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
3016            Operation::UpdateCompletionTriggers { .. } | Operation::UpdateLineEnding { .. } => true,
3017        }
3018    }
3019
3020    fn apply_op(&mut self, operation: Operation, cx: &mut Context<Self>) {
3021        match operation {
3022            Operation::Buffer(_) => {
3023                unreachable!("buffer operations should never be applied at this layer")
3024            }
3025            Operation::UpdateDiagnostics {
3026                server_id,
3027                diagnostics: diagnostic_set,
3028                lamport_timestamp,
3029            } => {
3030                let snapshot = self.snapshot();
3031                self.apply_diagnostic_update(
3032                    server_id,
3033                    DiagnosticSet::from_sorted_entries(diagnostic_set.iter().cloned(), &snapshot),
3034                    lamport_timestamp,
3035                    cx,
3036                );
3037            }
3038            Operation::UpdateSelections {
3039                selections,
3040                lamport_timestamp,
3041                line_mode,
3042                cursor_shape,
3043            } => {
3044                if let Some(set) = self.remote_selections.get(&lamport_timestamp.replica_id)
3045                    && set.lamport_timestamp > lamport_timestamp
3046                {
3047                    return;
3048                }
3049
3050                self.remote_selections.insert(
3051                    lamport_timestamp.replica_id,
3052                    SelectionSet {
3053                        selections,
3054                        lamport_timestamp,
3055                        line_mode,
3056                        cursor_shape,
3057                    },
3058                );
3059                self.text.lamport_clock.observe(lamport_timestamp);
3060                self.non_text_state_update_count += 1;
3061            }
3062            Operation::UpdateCompletionTriggers {
3063                triggers,
3064                lamport_timestamp,
3065                server_id,
3066            } => {
3067                if triggers.is_empty() {
3068                    self.completion_triggers_per_language_server
3069                        .remove(&server_id);
3070                    self.completion_triggers = self
3071                        .completion_triggers_per_language_server
3072                        .values()
3073                        .flat_map(|triggers| triggers.iter().cloned())
3074                        .collect();
3075                } else {
3076                    self.completion_triggers_per_language_server
3077                        .insert(server_id, triggers.iter().cloned().collect());
3078                    self.completion_triggers.extend(triggers);
3079                }
3080                self.text.lamport_clock.observe(lamport_timestamp);
3081            }
3082            Operation::UpdateLineEnding {
3083                line_ending,
3084                lamport_timestamp,
3085            } => {
3086                self.text.set_line_ending(line_ending);
3087                self.text.lamport_clock.observe(lamport_timestamp);
3088            }
3089        }
3090    }
3091
3092    fn apply_diagnostic_update(
3093        &mut self,
3094        server_id: LanguageServerId,
3095        diagnostics: DiagnosticSet,
3096        lamport_timestamp: clock::Lamport,
3097        cx: &mut Context<Self>,
3098    ) {
3099        if lamport_timestamp > self.diagnostics_timestamp {
3100            if diagnostics.is_empty() {
3101                self.diagnostics.remove(&server_id);
3102            } else {
3103                self.diagnostics.insert(server_id, diagnostics);
3104            }
3105            self.diagnostics_timestamp = lamport_timestamp;
3106            self.non_text_state_update_count += 1;
3107            self.text.lamport_clock.observe(lamport_timestamp);
3108            cx.notify();
3109            cx.emit(BufferEvent::DiagnosticsUpdated);
3110        }
3111    }
3112
3113    fn send_operation(&mut self, operation: Operation, is_local: bool, cx: &mut Context<Self>) {
3114        self.was_changed();
3115        cx.emit(BufferEvent::Operation {
3116            operation,
3117            is_local,
3118        });
3119    }
3120
3121    /// Removes the selections for a given peer.
3122    pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut Context<Self>) {
3123        self.remote_selections.remove(&replica_id);
3124        cx.notify();
3125    }
3126
3127    /// Undoes the most recent transaction.
3128    pub fn undo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
3129        let was_dirty = self.is_dirty();
3130        let old_version = self.version.clone();
3131
3132        if let Some((transaction_id, operation)) = self.text.undo() {
3133            self.send_operation(Operation::Buffer(operation), true, cx);
3134            self.did_edit(&old_version, was_dirty, true, cx);
3135            self.restore_encoding_for_transaction(transaction_id, was_dirty);
3136            Some(transaction_id)
3137        } else {
3138            None
3139        }
3140    }
3141
3142    /// Manually undoes a specific transaction in the buffer's undo history.
3143    pub fn undo_transaction(
3144        &mut self,
3145        transaction_id: TransactionId,
3146        cx: &mut Context<Self>,
3147    ) -> bool {
3148        let was_dirty = self.is_dirty();
3149        let old_version = self.version.clone();
3150        if let Some(operation) = self.text.undo_transaction(transaction_id) {
3151            self.send_operation(Operation::Buffer(operation), true, cx);
3152            self.did_edit(&old_version, was_dirty, true, cx);
3153            true
3154        } else {
3155            false
3156        }
3157    }
3158
3159    /// Manually undoes all changes after a given transaction in the buffer's undo history.
3160    pub fn undo_to_transaction(
3161        &mut self,
3162        transaction_id: TransactionId,
3163        cx: &mut Context<Self>,
3164    ) -> bool {
3165        let was_dirty = self.is_dirty();
3166        let old_version = self.version.clone();
3167
3168        let operations = self.text.undo_to_transaction(transaction_id);
3169        let undone = !operations.is_empty();
3170        for operation in operations {
3171            self.send_operation(Operation::Buffer(operation), true, cx);
3172        }
3173        if undone {
3174            self.did_edit(&old_version, was_dirty, true, cx)
3175        }
3176        undone
3177    }
3178
3179    pub fn undo_operations(&mut self, counts: HashMap<Lamport, u32>, cx: &mut Context<Buffer>) {
3180        let was_dirty = self.is_dirty();
3181        let operation = self.text.undo_operations(counts);
3182        let old_version = self.version.clone();
3183        self.send_operation(Operation::Buffer(operation), true, cx);
3184        self.did_edit(&old_version, was_dirty, true, cx);
3185    }
3186
3187    /// Manually redoes a specific transaction in the buffer's redo history.
3188    pub fn redo(&mut self, cx: &mut Context<Self>) -> Option<TransactionId> {
3189        let was_dirty = self.is_dirty();
3190        let old_version = self.version.clone();
3191
3192        if let Some((transaction_id, operation)) = self.text.redo() {
3193            self.send_operation(Operation::Buffer(operation), true, cx);
3194            self.did_edit(&old_version, was_dirty, true, cx);
3195            self.restore_encoding_for_transaction(transaction_id, was_dirty);
3196            Some(transaction_id)
3197        } else {
3198            None
3199        }
3200    }
3201
3202    fn restore_encoding_for_transaction(&mut self, transaction_id: TransactionId, was_dirty: bool) {
3203        if let Some((old_encoding, old_has_bom)) =
3204            self.reload_with_encoding_txns.get(&transaction_id)
3205        {
3206            let current_encoding = self.encoding;
3207            let current_has_bom = self.has_bom;
3208            self.encoding = *old_encoding;
3209            self.has_bom = *old_has_bom;
3210            if !was_dirty {
3211                self.saved_version = self.version.clone();
3212                self.has_unsaved_edits
3213                    .set((self.saved_version.clone(), false));
3214            }
3215            self.reload_with_encoding_txns
3216                .insert(transaction_id, (current_encoding, current_has_bom));
3217        }
3218    }
3219
3220    /// Manually undoes all changes until a given transaction in the buffer's redo history.
3221    pub fn redo_to_transaction(
3222        &mut self,
3223        transaction_id: TransactionId,
3224        cx: &mut Context<Self>,
3225    ) -> bool {
3226        let was_dirty = self.is_dirty();
3227        let old_version = self.version.clone();
3228
3229        let operations = self.text.redo_to_transaction(transaction_id);
3230        let redone = !operations.is_empty();
3231        for operation in operations {
3232            self.send_operation(Operation::Buffer(operation), true, cx);
3233        }
3234        if redone {
3235            self.did_edit(&old_version, was_dirty, true, cx)
3236        }
3237        redone
3238    }
3239
3240    /// Override current completion triggers with the user-provided completion triggers.
3241    pub fn set_completion_triggers(
3242        &mut self,
3243        server_id: LanguageServerId,
3244        triggers: BTreeSet<String>,
3245        cx: &mut Context<Self>,
3246    ) {
3247        self.completion_triggers_timestamp = self.text.lamport_clock.tick();
3248        if triggers.is_empty() {
3249            self.completion_triggers_per_language_server
3250                .remove(&server_id);
3251            self.completion_triggers = self
3252                .completion_triggers_per_language_server
3253                .values()
3254                .flat_map(|triggers| triggers.iter().cloned())
3255                .collect();
3256        } else {
3257            self.completion_triggers_per_language_server
3258                .insert(server_id, triggers.clone());
3259            self.completion_triggers.extend(triggers.iter().cloned());
3260        }
3261        self.send_operation(
3262            Operation::UpdateCompletionTriggers {
3263                triggers: triggers.into_iter().collect(),
3264                lamport_timestamp: self.completion_triggers_timestamp,
3265                server_id,
3266            },
3267            true,
3268            cx,
3269        );
3270        cx.notify();
3271    }
3272
3273    /// Returns a list of strings which trigger a completion menu for this language.
3274    /// Usually this is driven by LSP server which returns a list of trigger characters for completions.
3275    pub fn completion_triggers(&self) -> &BTreeSet<String> {
3276        &self.completion_triggers
3277    }
3278
3279    /// Call this directly after performing edits to prevent the preview tab
3280    /// from being dismissed by those edits. It causes `should_dismiss_preview`
3281    /// to return false until there are additional edits.
3282    pub fn refresh_preview(&mut self) {
3283        self.preview_version = self.version.clone();
3284    }
3285
3286    /// Whether we should preserve the preview status of a tab containing this buffer.
3287    pub fn preserve_preview(&self) -> bool {
3288        !self.has_edits_since(&self.preview_version)
3289    }
3290
3291    pub fn set_group_interval(&mut self, group_interval: Duration) {
3292        self.text.set_group_interval(group_interval);
3293    }
3294}
3295
3296#[doc(hidden)]
3297#[cfg(any(test, feature = "test-support"))]
3298impl Buffer {
3299    pub fn edit_via_marked_text(
3300        &mut self,
3301        marked_string: &str,
3302        autoindent_mode: Option<AutoindentMode>,
3303        cx: &mut Context<Self>,
3304    ) {
3305        let edits = self.edits_for_marked_text(marked_string);
3306        self.edit(edits, autoindent_mode, cx);
3307    }
3308
3309    pub fn randomly_edit<T>(&mut self, rng: &mut T, old_range_count: usize, cx: &mut Context<Self>)
3310    where
3311        T: rand::Rng,
3312    {
3313        let mut edits: Vec<(Range<usize>, String)> = Vec::new();
3314        let mut last_end = None;
3315        for _ in 0..old_range_count {
3316            if last_end.is_some_and(|last_end| last_end >= self.len()) {
3317                break;
3318            }
3319
3320            let new_start = last_end.map_or(0, |last_end| last_end + 1);
3321            let mut range = self.random_byte_range(new_start, rng);
3322            if rng.random_bool(0.2) {
3323                mem::swap(&mut range.start, &mut range.end);
3324            }
3325            last_end = Some(range.end);
3326
3327            let new_text_len = rng.random_range(0..10);
3328            let mut new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
3329            new_text = new_text.to_uppercase();
3330
3331            edits.push((range, new_text));
3332        }
3333        log::info!("mutating buffer {:?} with {:?}", self.replica_id(), edits);
3334        self.edit(edits, None, cx);
3335    }
3336
3337    pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut Context<Self>) {
3338        let was_dirty = self.is_dirty();
3339        let old_version = self.version.clone();
3340
3341        let ops = self.text.randomly_undo_redo(rng);
3342        if !ops.is_empty() {
3343            for op in ops {
3344                self.send_operation(Operation::Buffer(op), true, cx);
3345                self.did_edit(&old_version, was_dirty, true, cx);
3346            }
3347        }
3348    }
3349}
3350
3351impl EventEmitter<BufferEvent> for Buffer {}
3352
3353fn offset_in_sub_ranges(
3354    sub_ranges: &[Range<Anchor>],
3355    offset: usize,
3356    snapshot: &TextBufferSnapshot,
3357) -> bool {
3358    let start_anchor = snapshot.anchor_before(offset);
3359    let end_anchor = snapshot.anchor_after(offset);
3360
3361    sub_ranges.iter().any(|sub_range| {
3362        let is_before_start = sub_range.end.cmp(&start_anchor, snapshot).is_lt();
3363        let is_after_end = sub_range.start.cmp(&end_anchor, snapshot).is_gt();
3364        !is_before_start && !is_after_end
3365    })
3366}
3367
3368impl Deref for Buffer {
3369    type Target = TextBuffer;
3370
3371    fn deref(&self) -> &Self::Target {
3372        &self.text
3373    }
3374}
3375
3376impl BufferSnapshot {
3377    /// Returns [`IndentSize`] for a given line that respects user settings and
3378    /// language preferences.
3379    pub fn indent_size_for_line(&self, row: u32) -> IndentSize {
3380        indent_size_for_line(self, row)
3381    }
3382
3383    /// Returns [`IndentSize`] for a given position that respects user settings
3384    /// and language preferences.
3385    pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &App) -> IndentSize {
3386        let settings = self.settings_at(position, cx);
3387        if settings.hard_tabs {
3388            IndentSize::tab()
3389        } else {
3390            IndentSize::spaces(settings.tab_size.get())
3391        }
3392    }
3393
3394    /// Retrieve the suggested indent size for all of the given rows. The unit of indentation
3395    /// is passed in as `single_indent_size`.
3396    pub fn suggested_indents(
3397        &self,
3398        rows: impl Iterator<Item = u32>,
3399        single_indent_size: IndentSize,
3400    ) -> BTreeMap<u32, IndentSize> {
3401        let mut result = BTreeMap::new();
3402
3403        for row_range in contiguous_ranges(rows, 10) {
3404            let suggestions = match self.suggest_autoindents(row_range.clone()) {
3405                Some(suggestions) => suggestions,
3406                _ => break,
3407            };
3408
3409            for (row, suggestion) in row_range.zip(suggestions) {
3410                let indent_size = if let Some(suggestion) = suggestion {
3411                    result
3412                        .get(&suggestion.basis_row)
3413                        .copied()
3414                        .unwrap_or_else(|| self.indent_size_for_line(suggestion.basis_row))
3415                        .with_delta(suggestion.delta, single_indent_size)
3416                } else {
3417                    self.indent_size_for_line(row)
3418                };
3419
3420                result.insert(row, indent_size);
3421            }
3422        }
3423
3424        result
3425    }
3426
3427    fn suggest_autoindents(
3428        &self,
3429        row_range: Range<u32>,
3430    ) -> Option<impl Iterator<Item = Option<IndentSuggestion>> + '_> {
3431        let config = &self.language.as_ref()?.config;
3432        let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
3433
3434        #[derive(Debug, Clone)]
3435        struct StartPosition {
3436            start: Point,
3437            suffix: SharedString,
3438            language: Arc<Language>,
3439        }
3440
3441        // Find the suggested indentation ranges based on the syntax tree.
3442        let start = Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0);
3443        let end = Point::new(row_range.end, 0);
3444        let range = (start..end).to_offset(&self.text);
3445        let mut matches = self.syntax.matches_with_options(
3446            range.clone(),
3447            &self.text,
3448            TreeSitterOptions {
3449                max_bytes_to_query: Some(MAX_BYTES_TO_QUERY),
3450                max_start_depth: None,
3451            },
3452            |grammar| Some(&grammar.indents_config.as_ref()?.query),
3453        );
3454        let indent_configs = matches
3455            .grammars()
3456            .iter()
3457            .map(|grammar| grammar.indents_config.as_ref().unwrap())
3458            .collect::<Vec<_>>();
3459
3460        let mut indent_ranges = Vec::<Range<Point>>::new();
3461        let mut start_positions = Vec::<StartPosition>::new();
3462        let mut outdent_positions = Vec::<Point>::new();
3463        while let Some(mat) = matches.peek() {
3464            let mut start: Option<Point> = None;
3465            let mut end: Option<Point> = None;
3466
3467            let config = indent_configs[mat.grammar_index];
3468            for capture in mat.captures {
3469                if capture.index == config.indent_capture_ix {
3470                    start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
3471                    end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
3472                } else if Some(capture.index) == config.start_capture_ix {
3473                    start = Some(Point::from_ts_point(capture.node.end_position()));
3474                } else if Some(capture.index) == config.end_capture_ix {
3475                    end = Some(Point::from_ts_point(capture.node.start_position()));
3476                } else if Some(capture.index) == config.outdent_capture_ix {
3477                    outdent_positions.push(Point::from_ts_point(capture.node.start_position()));
3478                } else if let Some(suffix) = config.suffixed_start_captures.get(&capture.index) {
3479                    start_positions.push(StartPosition {
3480                        start: Point::from_ts_point(capture.node.start_position()),
3481                        suffix: suffix.clone(),
3482                        language: mat.language.clone(),
3483                    });
3484                }
3485            }
3486
3487            matches.advance();
3488            if let Some((start, end)) = start.zip(end) {
3489                if start.row == end.row {
3490                    continue;
3491                }
3492                let range = start..end;
3493                match indent_ranges.binary_search_by_key(&range.start, |r| r.start) {
3494                    Err(ix) => indent_ranges.insert(ix, range),
3495                    Ok(ix) => {
3496                        let prev_range = &mut indent_ranges[ix];
3497                        prev_range.end = prev_range.end.max(range.end);
3498                    }
3499                }
3500            }
3501        }
3502
3503        let mut error_ranges = Vec::<Range<Point>>::new();
3504        let mut matches = self
3505            .syntax
3506            .matches(range, &self.text, |grammar| grammar.error_query.as_ref());
3507        while let Some(mat) = matches.peek() {
3508            let node = mat.captures[0].node;
3509            let start = Point::from_ts_point(node.start_position());
3510            let end = Point::from_ts_point(node.end_position());
3511            let range = start..end;
3512            let ix = match error_ranges.binary_search_by_key(&range.start, |r| r.start) {
3513                Ok(ix) | Err(ix) => ix,
3514            };
3515            let mut end_ix = ix;
3516            while let Some(existing_range) = error_ranges.get(end_ix) {
3517                if existing_range.end < end {
3518                    end_ix += 1;
3519                } else {
3520                    break;
3521                }
3522            }
3523            error_ranges.splice(ix..end_ix, [range]);
3524            matches.advance();
3525        }
3526
3527        outdent_positions.sort();
3528        for outdent_position in outdent_positions {
3529            // find the innermost indent range containing this outdent_position
3530            // set its end to the outdent position
3531            if let Some(range_to_truncate) = indent_ranges
3532                .iter_mut()
3533                .rfind(|indent_range| indent_range.contains(&outdent_position))
3534            {
3535                range_to_truncate.end = outdent_position;
3536            }
3537        }
3538
3539        start_positions.sort_by_key(|b| b.start);
3540
3541        // Find the suggested indentation increases and decreased based on regexes.
3542        let mut regex_outdent_map = HashMap::default();
3543        let mut last_seen_suffix: HashMap<String, Vec<StartPosition>> = HashMap::default();
3544        let mut start_positions_iter = start_positions.iter().peekable();
3545
3546        let mut indent_change_rows = Vec::<(u32, Ordering)>::new();
3547        self.for_each_line(
3548            Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0)
3549                ..Point::new(row_range.end, 0),
3550            |row, line| {
3551                let indent_len = self.indent_size_for_line(row).len;
3552                let row_language = self.language_at(Point::new(row, indent_len)).cloned();
3553                let row_language_config = row_language
3554                    .as_ref()
3555                    .map(|lang| lang.config())
3556                    .unwrap_or(config);
3557
3558                if row_language_config
3559                    .decrease_indent_pattern
3560                    .as_ref()
3561                    .is_some_and(|regex| regex.is_match(line))
3562                {
3563                    indent_change_rows.push((row, Ordering::Less));
3564                }
3565                if row_language_config
3566                    .increase_indent_pattern
3567                    .as_ref()
3568                    .is_some_and(|regex| regex.is_match(line))
3569                {
3570                    indent_change_rows.push((row + 1, Ordering::Greater));
3571                }
3572                while let Some(pos) = start_positions_iter.peek() {
3573                    if pos.start.row < row {
3574                        let pos = start_positions_iter.next().unwrap().clone();
3575                        last_seen_suffix
3576                            .entry(pos.suffix.to_string())
3577                            .or_default()
3578                            .push(pos);
3579                    } else {
3580                        break;
3581                    }
3582                }
3583                for rule in &row_language_config.decrease_indent_patterns {
3584                    if rule.pattern.as_ref().is_some_and(|r| r.is_match(line)) {
3585                        let row_start_column = self.indent_size_for_line(row).len;
3586                        let basis_row = rule
3587                            .valid_after
3588                            .iter()
3589                            .filter_map(|valid_suffix| last_seen_suffix.get(valid_suffix))
3590                            .flatten()
3591                            .filter(|pos| {
3592                                row_language
3593                                    .as_ref()
3594                                    .or(self.language.as_ref())
3595                                    .is_some_and(|lang| Arc::ptr_eq(lang, &pos.language))
3596                            })
3597                            .filter(|pos| pos.start.column <= row_start_column)
3598                            .max_by_key(|pos| pos.start.row);
3599                        if let Some(outdent_to) = basis_row {
3600                            regex_outdent_map.insert(row, outdent_to.start.row);
3601                        }
3602                        break;
3603                    }
3604                }
3605            },
3606        );
3607
3608        let mut indent_changes = indent_change_rows.into_iter().peekable();
3609        let mut prev_row = if config.auto_indent_using_last_non_empty_line {
3610            prev_non_blank_row.unwrap_or(0)
3611        } else {
3612            row_range.start.saturating_sub(1)
3613        };
3614
3615        let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len);
3616        Some(row_range.map(move |row| {
3617            let row_start = Point::new(row, self.indent_size_for_line(row).len);
3618
3619            let mut indent_from_prev_row = false;
3620            let mut outdent_from_prev_row = false;
3621            let mut outdent_to_row = u32::MAX;
3622            let mut from_regex = false;
3623
3624            while let Some((indent_row, delta)) = indent_changes.peek() {
3625                match indent_row.cmp(&row) {
3626                    Ordering::Equal => match delta {
3627                        Ordering::Less => {
3628                            from_regex = true;
3629                            outdent_from_prev_row = true
3630                        }
3631                        Ordering::Greater => {
3632                            indent_from_prev_row = true;
3633                            from_regex = true
3634                        }
3635                        _ => {}
3636                    },
3637
3638                    Ordering::Greater => break,
3639                    Ordering::Less => {}
3640                }
3641
3642                indent_changes.next();
3643            }
3644
3645            for range in &indent_ranges {
3646                if range.start.row >= row {
3647                    break;
3648                }
3649                if range.start.row == prev_row && range.end > row_start {
3650                    indent_from_prev_row = true;
3651                }
3652                if range.end > prev_row_start && range.end <= row_start {
3653                    outdent_to_row = outdent_to_row.min(range.start.row);
3654                }
3655            }
3656
3657            if let Some(basis_row) = regex_outdent_map.get(&row) {
3658                indent_from_prev_row = false;
3659                outdent_to_row = *basis_row;
3660                from_regex = true;
3661            }
3662
3663            let within_error = error_ranges
3664                .iter()
3665                .any(|e| e.start.row < row && e.end > row_start);
3666
3667            let suggestion = if outdent_to_row == prev_row
3668                || (outdent_from_prev_row && indent_from_prev_row)
3669            {
3670                Some(IndentSuggestion {
3671                    basis_row: prev_row,
3672                    delta: Ordering::Equal,
3673                    within_error: within_error && !from_regex,
3674                })
3675            } else if indent_from_prev_row {
3676                Some(IndentSuggestion {
3677                    basis_row: prev_row,
3678                    delta: Ordering::Greater,
3679                    within_error: within_error && !from_regex,
3680                })
3681            } else if outdent_to_row < prev_row {
3682                Some(IndentSuggestion {
3683                    basis_row: outdent_to_row,
3684                    delta: Ordering::Equal,
3685                    within_error: within_error && !from_regex,
3686                })
3687            } else if outdent_from_prev_row {
3688                Some(IndentSuggestion {
3689                    basis_row: prev_row,
3690                    delta: Ordering::Less,
3691                    within_error: within_error && !from_regex,
3692                })
3693            } else if config.auto_indent_using_last_non_empty_line || !self.is_line_blank(prev_row)
3694            {
3695                Some(IndentSuggestion {
3696                    basis_row: prev_row,
3697                    delta: Ordering::Equal,
3698                    within_error: within_error && !from_regex,
3699                })
3700            } else {
3701                None
3702            };
3703
3704            prev_row = row;
3705            prev_row_start = row_start;
3706            suggestion
3707        }))
3708    }
3709
3710    fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
3711        while row > 0 {
3712            row -= 1;
3713            if !self.is_line_blank(row) {
3714                return Some(row);
3715            }
3716        }
3717        None
3718    }
3719
3720    pub fn captures(
3721        &self,
3722        range: Range<usize>,
3723        query: fn(&Grammar) -> Option<&tree_sitter::Query>,
3724    ) -> SyntaxMapCaptures<'_> {
3725        self.syntax.captures(range, &self.text, query)
3726    }
3727
3728    #[ztracing::instrument(skip_all)]
3729    fn get_highlights(&self, range: Range<usize>) -> (SyntaxMapCaptures<'_>, Vec<HighlightMap>) {
3730        let captures = self.syntax.captures(range, &self.text, |grammar| {
3731            grammar
3732                .highlights_config
3733                .as_ref()
3734                .map(|config| &config.query)
3735        });
3736        let highlight_maps = captures
3737            .grammars()
3738            .iter()
3739            .map(|grammar| grammar.highlight_map())
3740            .collect();
3741        (captures, highlight_maps)
3742    }
3743
3744    /// Iterates over chunks of text in the given range of the buffer. Text is chunked
3745    /// in an arbitrary way due to being stored in a [`Rope`](text::Rope). The text is also
3746    /// returned in chunks where each chunk has a single syntax highlighting style and
3747    /// diagnostic status.
3748    #[ztracing::instrument(skip_all)]
3749    pub fn chunks<T: ToOffset>(
3750        &self,
3751        range: Range<T>,
3752        language_aware: LanguageAwareStyling,
3753    ) -> BufferChunks<'_> {
3754        let range = range.start.to_offset(self)..range.end.to_offset(self);
3755
3756        let mut syntax = None;
3757        if language_aware.tree_sitter {
3758            syntax = Some(self.get_highlights(range.clone()));
3759        }
3760        BufferChunks::new(
3761            self.text.as_rope(),
3762            range,
3763            syntax,
3764            language_aware.diagnostics,
3765            Some(self),
3766        )
3767    }
3768
3769    pub fn highlighted_text_for_range<T: ToOffset>(
3770        &self,
3771        range: Range<T>,
3772        override_style: Option<HighlightStyle>,
3773        syntax_theme: &SyntaxTheme,
3774    ) -> HighlightedText {
3775        HighlightedText::from_buffer_range(
3776            range,
3777            &self.text,
3778            &self.syntax,
3779            override_style,
3780            syntax_theme,
3781        )
3782    }
3783
3784    /// Invokes the given callback for each line of text in the given range of the buffer.
3785    /// Uses callback to avoid allocating a string for each line.
3786    fn for_each_line(&self, range: Range<Point>, mut callback: impl FnMut(u32, &str)) {
3787        let mut line = String::new();
3788        let mut row = range.start.row;
3789        for chunk in self
3790            .as_rope()
3791            .chunks_in_range(range.to_offset(self))
3792            .chain(["\n"])
3793        {
3794            for (newline_ix, text) in chunk.split('\n').enumerate() {
3795                if newline_ix > 0 {
3796                    callback(row, &line);
3797                    row += 1;
3798                    line.clear();
3799                }
3800                line.push_str(text);
3801            }
3802        }
3803    }
3804
3805    /// Iterates over every [`SyntaxLayer`] in the buffer.
3806    pub fn syntax_layers(&self) -> impl Iterator<Item = SyntaxLayer<'_>> + '_ {
3807        self.syntax_layers_for_range(0..self.len(), true)
3808    }
3809
3810    pub fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer<'_>> {
3811        let offset = position.to_offset(self);
3812        self.syntax_layers_for_range(offset..offset, false)
3813            .filter(|l| {
3814                if let Some(ranges) = l.included_sub_ranges {
3815                    ranges.iter().any(|range| {
3816                        let start = range.start.to_offset(self);
3817                        start <= offset && {
3818                            let end = range.end.to_offset(self);
3819                            offset < end
3820                        }
3821                    })
3822                } else {
3823                    l.node().start_byte() <= offset && l.node().end_byte() > offset
3824                }
3825            })
3826            .last()
3827    }
3828
3829    pub fn syntax_layers_for_range<D: ToOffset>(
3830        &self,
3831        range: Range<D>,
3832        include_hidden: bool,
3833    ) -> impl Iterator<Item = SyntaxLayer<'_>> + '_ {
3834        self.syntax
3835            .layers_for_range(range, &self.text, include_hidden)
3836    }
3837
3838    pub fn syntax_layers_languages(&self) -> impl Iterator<Item = &Arc<Language>> {
3839        self.syntax.languages(&self, true)
3840    }
3841
3842    pub fn smallest_syntax_layer_containing<D: ToOffset>(
3843        &self,
3844        range: Range<D>,
3845    ) -> Option<SyntaxLayer<'_>> {
3846        let range = range.to_offset(self);
3847        self.syntax
3848            .layers_for_range(range, &self.text, false)
3849            .max_by(|a, b| {
3850                if a.depth != b.depth {
3851                    a.depth.cmp(&b.depth)
3852                } else if a.offset.0 != b.offset.0 {
3853                    a.offset.0.cmp(&b.offset.0)
3854                } else {
3855                    a.node().end_byte().cmp(&b.node().end_byte()).reverse()
3856                }
3857            })
3858    }
3859
3860    /// Returns the [`ModelineSettings`].
3861    pub fn modeline(&self) -> Option<&Arc<ModelineSettings>> {
3862        self.modeline.as_ref()
3863    }
3864
3865    /// Returns the main [`Language`].
3866    pub fn language(&self) -> Option<&Arc<Language>> {
3867        self.language.as_ref()
3868    }
3869
3870    /// Returns the [`Language`] at the given location.
3871    pub fn language_at<D: ToOffset>(&self, position: D) -> Option<&Arc<Language>> {
3872        self.syntax_layer_at(position)
3873            .map(|info| info.language)
3874            .or(self.language.as_ref())
3875    }
3876
3877    /// Returns the settings for the language at the given location.
3878    pub fn settings_at<'a, D: ToOffset>(
3879        &'a self,
3880        position: D,
3881        cx: &'a App,
3882    ) -> Cow<'a, LanguageSettings> {
3883        LanguageSettings::for_buffer_snapshot(self, Some(position.to_offset(self)), cx)
3884    }
3885
3886    pub fn char_classifier_at<T: ToOffset>(&self, point: T) -> CharClassifier {
3887        CharClassifier::new(self.language_scope_at(point))
3888    }
3889
3890    /// Returns the [`LanguageScope`] at the given location.
3891    pub fn language_scope_at<D: ToOffset>(&self, position: D) -> Option<LanguageScope> {
3892        let offset = position.to_offset(self);
3893        let mut scope = None;
3894        let mut smallest_range_and_depth: Option<(Range<usize>, usize)> = None;
3895        let text: &TextBufferSnapshot = self;
3896
3897        // Use the layer that has the smallest node intersecting the given point.
3898        for layer in self
3899            .syntax
3900            .layers_for_range(offset..offset, &self.text, false)
3901        {
3902            if let Some(ranges) = layer.included_sub_ranges
3903                && !offset_in_sub_ranges(ranges, offset, text)
3904            {
3905                continue;
3906            }
3907
3908            let mut cursor = layer.node().walk();
3909
3910            let mut range = None;
3911            loop {
3912                let child_range = cursor.node().byte_range();
3913                if !child_range.contains(&offset) {
3914                    break;
3915                }
3916
3917                range = Some(child_range);
3918                if cursor.goto_first_child_for_byte(offset).is_none() {
3919                    break;
3920                }
3921            }
3922
3923            if let Some(range) = range
3924                && smallest_range_and_depth.as_ref().is_none_or(
3925                    |(smallest_range, smallest_range_depth)| {
3926                        if layer.depth > *smallest_range_depth {
3927                            true
3928                        } else if layer.depth == *smallest_range_depth {
3929                            range.len() < smallest_range.len()
3930                        } else {
3931                            false
3932                        }
3933                    },
3934                )
3935            {
3936                smallest_range_and_depth = Some((range, layer.depth));
3937                scope = Some(LanguageScope {
3938                    language: layer.language.clone(),
3939                    override_id: layer.override_id(offset, &self.text),
3940                });
3941            }
3942        }
3943
3944        scope.or_else(|| {
3945            self.language.clone().map(|language| LanguageScope {
3946                language,
3947                override_id: None,
3948            })
3949        })
3950    }
3951
3952    /// Returns a tuple of the range and character kind of the word
3953    /// surrounding the given position.
3954    pub fn surrounding_word<T: ToOffset>(
3955        &self,
3956        start: T,
3957        scope_context: Option<CharScopeContext>,
3958    ) -> (Range<usize>, Option<CharKind>) {
3959        let mut start = start.to_offset(self);
3960        let mut end = start;
3961        let mut next_chars = self.chars_at(start).take(128).peekable();
3962        let mut prev_chars = self.reversed_chars_at(start).take(128).peekable();
3963
3964        let classifier = self.char_classifier_at(start).scope_context(scope_context);
3965        let word_kind = cmp::max(
3966            prev_chars.peek().copied().map(|c| classifier.kind(c)),
3967            next_chars.peek().copied().map(|c| classifier.kind(c)),
3968        );
3969
3970        for ch in prev_chars {
3971            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
3972                start -= ch.len_utf8();
3973            } else {
3974                break;
3975            }
3976        }
3977
3978        for ch in next_chars {
3979            if Some(classifier.kind(ch)) == word_kind && ch != '\n' {
3980                end += ch.len_utf8();
3981            } else {
3982                break;
3983            }
3984        }
3985
3986        (start..end, word_kind)
3987    }
3988
3989    /// Moves the TreeCursor to the smallest descendant or ancestor syntax node enclosing the given
3990    /// range. When `require_larger` is true, the node found must be larger than the query range.
3991    ///
3992    /// Returns true if a node was found, and false otherwise. In the `false` case the cursor will
3993    /// be moved to the root of the tree.
3994    fn goto_node_enclosing_range(
3995        cursor: &mut tree_sitter::TreeCursor,
3996        query_range: &Range<usize>,
3997        require_larger: bool,
3998    ) -> bool {
3999        let mut ascending = false;
4000        loop {
4001            let mut range = cursor.node().byte_range();
4002            if query_range.is_empty() {
4003                // When the query range is empty and the current node starts after it, move to the
4004                // previous sibling to find the node the containing node.
4005                if range.start > query_range.start {
4006                    cursor.goto_previous_sibling();
4007                    range = cursor.node().byte_range();
4008                }
4009            } else {
4010                // When the query range is non-empty and the current node ends exactly at the start,
4011                // move to the next sibling to find a node that extends beyond the start.
4012                if range.end == query_range.start {
4013                    cursor.goto_next_sibling();
4014                    range = cursor.node().byte_range();
4015                }
4016            }
4017
4018            let encloses = range.contains_inclusive(query_range)
4019                && (!require_larger || range.len() > query_range.len());
4020            if !encloses {
4021                ascending = true;
4022                if !cursor.goto_parent() {
4023                    return false;
4024                }
4025                continue;
4026            } else if ascending {
4027                return true;
4028            }
4029
4030            // Descend into the current node.
4031            if cursor
4032                .goto_first_child_for_byte(query_range.start)
4033                .is_none()
4034            {
4035                return true;
4036            }
4037        }
4038    }
4039
4040    pub fn syntax_ancestor<'a, T: ToOffset>(
4041        &'a self,
4042        range: Range<T>,
4043    ) -> Option<tree_sitter::Node<'a>> {
4044        let range = range.start.to_offset(self)..range.end.to_offset(self);
4045        let mut result: Option<tree_sitter::Node<'a>> = None;
4046        for layer in self
4047            .syntax
4048            .layers_for_range(range.clone(), &self.text, true)
4049        {
4050            let mut cursor = layer.node().walk();
4051
4052            // Find the node that both contains the range and is larger than it.
4053            if !Self::goto_node_enclosing_range(&mut cursor, &range, true) {
4054                continue;
4055            }
4056
4057            let left_node = cursor.node();
4058            let mut layer_result = left_node;
4059
4060            // For an empty range, try to find another node immediately to the right of the range.
4061            if left_node.end_byte() == range.start {
4062                let mut right_node = None;
4063                while !cursor.goto_next_sibling() {
4064                    if !cursor.goto_parent() {
4065                        break;
4066                    }
4067                }
4068
4069                while cursor.node().start_byte() == range.start {
4070                    right_node = Some(cursor.node());
4071                    if !cursor.goto_first_child() {
4072                        break;
4073                    }
4074                }
4075
4076                // If there is a candidate node on both sides of the (empty) range, then
4077                // decide between the two by favoring a named node over an anonymous token.
4078                // If both nodes are the same in that regard, favor the right one.
4079                if let Some(right_node) = right_node
4080                    && (right_node.is_named() || !left_node.is_named())
4081                {
4082                    layer_result = right_node;
4083                }
4084            }
4085
4086            if let Some(previous_result) = &result
4087                && previous_result.byte_range().len() < layer_result.byte_range().len()
4088            {
4089                continue;
4090            }
4091            result = Some(layer_result);
4092        }
4093
4094        result
4095    }
4096
4097    /// Find the previous sibling syntax node at the given range.
4098    ///
4099    /// This function locates the syntax node that precedes the node containing
4100    /// the given range. It searches hierarchically by:
4101    /// 1. Finding the node that contains the given range
4102    /// 2. Looking for the previous sibling at the same tree level
4103    /// 3. If no sibling is found, moving up to parent levels and searching for siblings
4104    ///
4105    /// Returns `None` if there is no previous sibling at any ancestor level.
4106    pub fn syntax_prev_sibling<'a, T: ToOffset>(
4107        &'a self,
4108        range: Range<T>,
4109    ) -> Option<tree_sitter::Node<'a>> {
4110        let range = range.start.to_offset(self)..range.end.to_offset(self);
4111        let mut result: Option<tree_sitter::Node<'a>> = None;
4112
4113        for layer in self
4114            .syntax
4115            .layers_for_range(range.clone(), &self.text, true)
4116        {
4117            let mut cursor = layer.node().walk();
4118
4119            // Find the node that contains the range
4120            if !Self::goto_node_enclosing_range(&mut cursor, &range, false) {
4121                continue;
4122            }
4123
4124            // Look for the previous sibling, moving up ancestor levels if needed
4125            loop {
4126                if cursor.goto_previous_sibling() {
4127                    let layer_result = cursor.node();
4128
4129                    if let Some(previous_result) = &result {
4130                        if previous_result.byte_range().end < layer_result.byte_range().end {
4131                            continue;
4132                        }
4133                    }
4134                    result = Some(layer_result);
4135                    break;
4136                }
4137
4138                // No sibling found at this level, try moving up to parent
4139                if !cursor.goto_parent() {
4140                    break;
4141                }
4142            }
4143        }
4144
4145        result
4146    }
4147
4148    /// Find the next sibling syntax node at the given range.
4149    ///
4150    /// This function locates the syntax node that follows the node containing
4151    /// the given range. It searches hierarchically by:
4152    /// 1. Finding the node that contains the given range
4153    /// 2. Looking for the next sibling at the same tree level
4154    /// 3. If no sibling is found, moving up to parent levels and searching for siblings
4155    ///
4156    /// Returns `None` if there is no next sibling at any ancestor level.
4157    pub fn syntax_next_sibling<'a, T: ToOffset>(
4158        &'a self,
4159        range: Range<T>,
4160    ) -> Option<tree_sitter::Node<'a>> {
4161        let range = range.start.to_offset(self)..range.end.to_offset(self);
4162        let mut result: Option<tree_sitter::Node<'a>> = None;
4163
4164        for layer in self
4165            .syntax
4166            .layers_for_range(range.clone(), &self.text, true)
4167        {
4168            let mut cursor = layer.node().walk();
4169
4170            // Find the node that contains the range
4171            if !Self::goto_node_enclosing_range(&mut cursor, &range, false) {
4172                continue;
4173            }
4174
4175            // Look for the next sibling, moving up ancestor levels if needed
4176            loop {
4177                if cursor.goto_next_sibling() {
4178                    let layer_result = cursor.node();
4179
4180                    if let Some(previous_result) = &result {
4181                        if previous_result.byte_range().start > layer_result.byte_range().start {
4182                            continue;
4183                        }
4184                    }
4185                    result = Some(layer_result);
4186                    break;
4187                }
4188
4189                // No sibling found at this level, try moving up to parent
4190                if !cursor.goto_parent() {
4191                    break;
4192                }
4193            }
4194        }
4195
4196        result
4197    }
4198
4199    /// Returns the root syntax node within the given row
4200    pub fn syntax_root_ancestor(&self, position: Anchor) -> Option<tree_sitter::Node<'_>> {
4201        let start_offset = position.to_offset(self);
4202
4203        let row = self.summary_for_anchor::<text::PointUtf16>(&position).row as usize;
4204
4205        let layer = self
4206            .syntax
4207            .layers_for_range(start_offset..start_offset, &self.text, true)
4208            .next()?;
4209
4210        let mut cursor = layer.node().walk();
4211
4212        // Descend to the first leaf that touches the start of the range.
4213        while cursor.goto_first_child_for_byte(start_offset).is_some() {
4214            if cursor.node().end_byte() == start_offset {
4215                cursor.goto_next_sibling();
4216            }
4217        }
4218
4219        // Ascend to the root node within the same row.
4220        while cursor.goto_parent() {
4221            if cursor.node().start_position().row != row {
4222                break;
4223            }
4224        }
4225
4226        Some(cursor.node())
4227    }
4228
4229    /// Returns the outline for the buffer.
4230    ///
4231    /// This method allows passing an optional [`SyntaxTheme`] to
4232    /// syntax-highlight the returned symbols.
4233    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Outline<Anchor> {
4234        Outline::new(self.outline_items_containing(0..self.len(), true, theme))
4235    }
4236
4237    /// Returns all the symbols that contain the given position.
4238    ///
4239    /// This method allows passing an optional [`SyntaxTheme`] to
4240    /// syntax-highlight the returned symbols.
4241    pub fn symbols_containing<T: ToOffset>(
4242        &self,
4243        position: T,
4244        theme: Option<&SyntaxTheme>,
4245    ) -> Vec<OutlineItem<Anchor>> {
4246        let position = position.to_offset(self);
4247        let start = self.clip_offset(position.saturating_sub(1), Bias::Left);
4248        let end = self.clip_offset(position + 1, Bias::Right);
4249        let mut items = self.outline_items_containing(start..end, false, theme);
4250        let mut prev_depth = None;
4251        items.retain(|item| {
4252            let result = prev_depth.is_none_or(|prev_depth| item.depth > prev_depth);
4253            prev_depth = Some(item.depth);
4254            result
4255        });
4256        items
4257    }
4258
4259    pub fn outline_ranges_containing<T: ToOffset>(
4260        &self,
4261        range: Range<T>,
4262    ) -> impl Iterator<Item = Range<Point>> + '_ {
4263        let range = range.to_offset(self);
4264        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
4265            grammar.outline_config.as_ref().map(|c| &c.query)
4266        });
4267        let configs = matches
4268            .grammars()
4269            .iter()
4270            .map(|g| g.outline_config.as_ref().unwrap())
4271            .collect::<Vec<_>>();
4272
4273        std::iter::from_fn(move || {
4274            while let Some(mat) = matches.peek() {
4275                let config = &configs[mat.grammar_index];
4276                let containing_item_node = maybe!({
4277                    let item_node = mat.captures.iter().find_map(|cap| {
4278                        if cap.index == config.item_capture_ix {
4279                            Some(cap.node)
4280                        } else {
4281                            None
4282                        }
4283                    })?;
4284
4285                    let item_byte_range = item_node.byte_range();
4286                    if item_byte_range.end < range.start || item_byte_range.start > range.end {
4287                        None
4288                    } else {
4289                        Some(item_node)
4290                    }
4291                });
4292
4293                let range = containing_item_node.as_ref().map(|item_node| {
4294                    Point::from_ts_point(item_node.start_position())
4295                        ..Point::from_ts_point(item_node.end_position())
4296                });
4297                matches.advance();
4298                if range.is_some() {
4299                    return range;
4300                }
4301            }
4302            None
4303        })
4304    }
4305
4306    pub fn outline_range_containing<T: ToOffset>(&self, range: Range<T>) -> Option<Range<Point>> {
4307        self.outline_ranges_containing(range).next()
4308    }
4309
4310    pub fn outline_items_containing<T: ToOffset>(
4311        &self,
4312        range: Range<T>,
4313        include_extra_context: bool,
4314        theme: Option<&SyntaxTheme>,
4315    ) -> Vec<OutlineItem<Anchor>> {
4316        self.outline_items_containing_internal(
4317            range,
4318            include_extra_context,
4319            theme,
4320            |this, range| this.anchor_after(range.start)..this.anchor_before(range.end),
4321        )
4322    }
4323
4324    pub fn outline_items_as_points_containing<T: ToOffset>(
4325        &self,
4326        range: Range<T>,
4327        include_extra_context: bool,
4328        theme: Option<&SyntaxTheme>,
4329    ) -> Vec<OutlineItem<Point>> {
4330        self.outline_items_containing_internal(range, include_extra_context, theme, |_, range| {
4331            range
4332        })
4333    }
4334
4335    pub fn outline_items_as_offsets_containing<T: ToOffset>(
4336        &self,
4337        range: Range<T>,
4338        include_extra_context: bool,
4339        theme: Option<&SyntaxTheme>,
4340    ) -> Vec<OutlineItem<usize>> {
4341        self.outline_items_containing_internal(
4342            range,
4343            include_extra_context,
4344            theme,
4345            |buffer, range| range.to_offset(buffer),
4346        )
4347    }
4348
4349    fn outline_items_containing_internal<T: ToOffset, U>(
4350        &self,
4351        range: Range<T>,
4352        include_extra_context: bool,
4353        theme: Option<&SyntaxTheme>,
4354        range_callback: fn(&Self, Range<Point>) -> Range<U>,
4355    ) -> Vec<OutlineItem<U>> {
4356        let range = range.to_offset(self);
4357        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
4358            grammar.outline_config.as_ref().map(|c| &c.query)
4359        });
4360
4361        let mut items = Vec::new();
4362        let mut annotation_row_ranges: Vec<Range<u32>> = Vec::new();
4363        while let Some(mat) = matches.peek() {
4364            let config = matches.grammars()[mat.grammar_index]
4365                .outline_config
4366                .as_ref()
4367                .unwrap();
4368            if let Some(item) =
4369                self.next_outline_item(config, &mat, &range, include_extra_context, theme)
4370            {
4371                items.push(item);
4372            } else if let Some(capture) = mat
4373                .captures
4374                .iter()
4375                .find(|capture| Some(capture.index) == config.annotation_capture_ix)
4376            {
4377                let capture_range = capture.node.start_position()..capture.node.end_position();
4378                let mut capture_row_range =
4379                    capture_range.start.row as u32..capture_range.end.row as u32;
4380                if capture_range.end.row > capture_range.start.row && capture_range.end.column == 0
4381                {
4382                    capture_row_range.end -= 1;
4383                }
4384                if let Some(last_row_range) = annotation_row_ranges.last_mut() {
4385                    if last_row_range.end >= capture_row_range.start.saturating_sub(1) {
4386                        last_row_range.end = capture_row_range.end;
4387                    } else {
4388                        annotation_row_ranges.push(capture_row_range);
4389                    }
4390                } else {
4391                    annotation_row_ranges.push(capture_row_range);
4392                }
4393            }
4394            matches.advance();
4395        }
4396
4397        items.sort_by_key(|item| (item.range.start, Reverse(item.range.end)));
4398
4399        // Assign depths based on containment relationships and convert to anchors.
4400        let mut item_ends_stack = Vec::<Point>::new();
4401        let mut anchor_items = Vec::new();
4402        let mut annotation_row_ranges = annotation_row_ranges.into_iter().peekable();
4403        for item in items {
4404            while let Some(last_end) = item_ends_stack.last().copied() {
4405                if last_end < item.range.end {
4406                    item_ends_stack.pop();
4407                } else {
4408                    break;
4409                }
4410            }
4411
4412            let mut annotation_row_range = None;
4413            while let Some(next_annotation_row_range) = annotation_row_ranges.peek() {
4414                let row_preceding_item = item.range.start.row.saturating_sub(1);
4415                if next_annotation_row_range.end < row_preceding_item {
4416                    annotation_row_ranges.next();
4417                } else {
4418                    if next_annotation_row_range.end == row_preceding_item {
4419                        annotation_row_range = Some(next_annotation_row_range.clone());
4420                        annotation_row_ranges.next();
4421                    }
4422                    break;
4423                }
4424            }
4425
4426            anchor_items.push(OutlineItem {
4427                depth: item_ends_stack.len(),
4428                range: range_callback(self, item.range.clone()),
4429                source_range_for_text: range_callback(self, item.source_range_for_text.clone()),
4430                text: item.text,
4431                highlight_ranges: item.highlight_ranges,
4432                name_ranges: item.name_ranges,
4433                body_range: item.body_range.map(|r| range_callback(self, r)),
4434                annotation_range: annotation_row_range.map(|annotation_range| {
4435                    let point_range = Point::new(annotation_range.start, 0)
4436                        ..Point::new(annotation_range.end, self.line_len(annotation_range.end));
4437                    range_callback(self, point_range)
4438                }),
4439            });
4440            item_ends_stack.push(item.range.end);
4441        }
4442
4443        anchor_items
4444    }
4445
4446    fn next_outline_item(
4447        &self,
4448        config: &OutlineConfig,
4449        mat: &SyntaxMapMatch,
4450        range: &Range<usize>,
4451        include_extra_context: bool,
4452        theme: Option<&SyntaxTheme>,
4453    ) -> Option<OutlineItem<Point>> {
4454        let item_node = mat.captures.iter().find_map(|cap| {
4455            if cap.index == config.item_capture_ix {
4456                Some(cap.node)
4457            } else {
4458                None
4459            }
4460        })?;
4461
4462        let item_byte_range = item_node.byte_range();
4463        if item_byte_range.end < range.start || item_byte_range.start > range.end {
4464            return None;
4465        }
4466        let item_point_range = Point::from_ts_point(item_node.start_position())
4467            ..Point::from_ts_point(item_node.end_position());
4468
4469        let mut open_point = None;
4470        let mut close_point = None;
4471
4472        let mut buffer_ranges = Vec::new();
4473        let mut add_to_buffer_ranges = |node: tree_sitter::Node, node_is_name| {
4474            let mut range = node.start_byte()..node.end_byte();
4475            let start = node.start_position();
4476            if node.end_position().row > start.row {
4477                range.end = range.start + self.line_len(start.row as u32) as usize - start.column;
4478            }
4479
4480            if !range.is_empty() {
4481                buffer_ranges.push((range, node_is_name));
4482            }
4483        };
4484
4485        for capture in mat.captures {
4486            if capture.index == config.name_capture_ix {
4487                add_to_buffer_ranges(capture.node, true);
4488            } else if Some(capture.index) == config.context_capture_ix
4489                || (Some(capture.index) == config.extra_context_capture_ix && include_extra_context)
4490            {
4491                add_to_buffer_ranges(capture.node, false);
4492            } else {
4493                if Some(capture.index) == config.open_capture_ix {
4494                    open_point = Some(Point::from_ts_point(capture.node.end_position()));
4495                } else if Some(capture.index) == config.close_capture_ix {
4496                    close_point = Some(Point::from_ts_point(capture.node.start_position()));
4497                }
4498            }
4499        }
4500
4501        if buffer_ranges.is_empty() {
4502            return None;
4503        }
4504        let source_range_for_text =
4505            buffer_ranges.first().unwrap().0.start..buffer_ranges.last().unwrap().0.end;
4506
4507        let mut text = String::new();
4508        let mut highlight_ranges = Vec::new();
4509        let mut name_ranges = Vec::new();
4510        let mut chunks = self.chunks(
4511            source_range_for_text.clone(),
4512            LanguageAwareStyling {
4513                tree_sitter: true,
4514                diagnostics: true,
4515            },
4516        );
4517        let mut last_buffer_range_end = 0;
4518        for (buffer_range, is_name) in buffer_ranges {
4519            let space_added = !text.is_empty() && buffer_range.start > last_buffer_range_end;
4520            if space_added {
4521                text.push(' ');
4522            }
4523            let before_append_len = text.len();
4524            let mut offset = buffer_range.start;
4525            chunks.seek(buffer_range.clone());
4526            for mut chunk in chunks.by_ref() {
4527                if chunk.text.len() > buffer_range.end - offset {
4528                    chunk.text = &chunk.text[0..(buffer_range.end - offset)];
4529                    offset = buffer_range.end;
4530                } else {
4531                    offset += chunk.text.len();
4532                }
4533                let style = chunk
4534                    .syntax_highlight_id
4535                    .zip(theme)
4536                    .and_then(|(highlight, theme)| theme.get(highlight).cloned());
4537
4538                if let Some(style) = style {
4539                    let start = text.len();
4540                    let end = start + chunk.text.len();
4541                    highlight_ranges.push((start..end, style));
4542                }
4543                text.push_str(chunk.text);
4544                if offset >= buffer_range.end {
4545                    break;
4546                }
4547            }
4548            if is_name {
4549                let after_append_len = text.len();
4550                let start = if space_added && !name_ranges.is_empty() {
4551                    before_append_len - 1
4552                } else {
4553                    before_append_len
4554                };
4555                name_ranges.push(start..after_append_len);
4556            }
4557            last_buffer_range_end = buffer_range.end;
4558        }
4559
4560        Some(OutlineItem {
4561            depth: 0, // We'll calculate the depth later
4562            range: item_point_range,
4563            source_range_for_text: source_range_for_text.to_point(self),
4564            text,
4565            highlight_ranges,
4566            name_ranges,
4567            body_range: open_point.zip(close_point).map(|(start, end)| start..end),
4568            annotation_range: None,
4569        })
4570    }
4571
4572    pub fn function_body_fold_ranges<T: ToOffset>(
4573        &self,
4574        within: Range<T>,
4575    ) -> impl Iterator<Item = Range<usize>> + '_ {
4576        self.text_object_ranges(within, TreeSitterOptions::default())
4577            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
4578    }
4579
4580    /// For each grammar in the language, runs the provided
4581    /// [`tree_sitter::Query`] against the given range.
4582    pub fn matches(
4583        &self,
4584        range: Range<usize>,
4585        query: fn(&Grammar) -> Option<&tree_sitter::Query>,
4586    ) -> SyntaxMapMatches<'_> {
4587        self.syntax.matches(range, self, query)
4588    }
4589
4590    /// Finds all [`RowChunks`] applicable to the given range, then returns all bracket pairs that intersect with those chunks.
4591    /// Hence, may return more bracket pairs than the range contains.
4592    ///
4593    /// Will omit known chunks.
4594    /// The resulting bracket match collections are not ordered.
4595    pub fn fetch_bracket_ranges(
4596        &self,
4597        range: Range<usize>,
4598        known_chunks: Option<&HashSet<Range<BufferRow>>>,
4599    ) -> HashMap<Range<BufferRow>, Vec<BracketMatch<usize>>> {
4600        let mut all_bracket_matches = HashMap::default();
4601
4602        for chunk in self
4603            .tree_sitter_data
4604            .chunks
4605            .applicable_chunks(&[range.to_point(self)])
4606        {
4607            if known_chunks.is_some_and(|chunks| chunks.contains(&chunk.row_range())) {
4608                continue;
4609            }
4610            let chunk_range = chunk.anchor_range();
4611            let chunk_range = chunk_range.to_offset(&self);
4612
4613            if let Some(cached_brackets) =
4614                &self.tree_sitter_data.brackets_by_chunks.lock()[chunk.id]
4615            {
4616                all_bracket_matches.insert(chunk.row_range(), cached_brackets.clone());
4617                continue;
4618            }
4619
4620            let mut all_brackets: Vec<(BracketMatch<usize>, usize, bool)> = Vec::new();
4621            let mut opens = Vec::new();
4622            let mut color_pairs = Vec::new();
4623
4624            let mut matches = self.syntax.matches_with_options(
4625                chunk_range.clone(),
4626                &self.text,
4627                TreeSitterOptions {
4628                    max_bytes_to_query: Some(MAX_BYTES_TO_QUERY),
4629                    max_start_depth: None,
4630                },
4631                |grammar| grammar.brackets_config.as_ref().map(|c| &c.query),
4632            );
4633            let configs = matches
4634                .grammars()
4635                .iter()
4636                .map(|grammar| grammar.brackets_config.as_ref().unwrap())
4637                .collect::<Vec<_>>();
4638
4639            // Group matches by open range so we can either trust grammar output
4640            // or repair it by picking a single closest close per open.
4641            let mut open_to_close_ranges = BTreeMap::new();
4642            while let Some(mat) = matches.peek() {
4643                let mut open = None;
4644                let mut close = None;
4645                let syntax_layer_depth = mat.depth;
4646                let pattern_index = mat.pattern_index;
4647                let config = configs[mat.grammar_index];
4648                let pattern = &config.patterns[pattern_index];
4649                for capture in mat.captures {
4650                    if capture.index == config.open_capture_ix {
4651                        open = Some(capture.node.byte_range());
4652                    } else if capture.index == config.close_capture_ix {
4653                        close = Some(capture.node.byte_range());
4654                    }
4655                }
4656
4657                matches.advance();
4658
4659                let Some((open_range, close_range)) = open.zip(close) else {
4660                    continue;
4661                };
4662
4663                let bracket_range = open_range.start..=close_range.end;
4664                if !bracket_range.overlaps(&chunk_range) {
4665                    continue;
4666                }
4667
4668                open_to_close_ranges
4669                    .entry((open_range.start, open_range.end, pattern_index))
4670                    .or_insert_with(BTreeMap::new)
4671                    .insert(
4672                        (close_range.start, close_range.end),
4673                        BracketMatch {
4674                            open_range: open_range.clone(),
4675                            close_range: close_range.clone(),
4676                            syntax_layer_depth,
4677                            newline_only: pattern.newline_only,
4678                            color_index: None,
4679                        },
4680                    );
4681
4682                all_brackets.push((
4683                    BracketMatch {
4684                        open_range,
4685                        close_range,
4686                        syntax_layer_depth,
4687                        newline_only: pattern.newline_only,
4688                        color_index: None,
4689                    },
4690                    pattern_index,
4691                    pattern.rainbow_exclude,
4692                ));
4693            }
4694
4695            let has_bogus_matches = open_to_close_ranges
4696                .iter()
4697                .any(|(_, end_ranges)| end_ranges.len() > 1);
4698            if has_bogus_matches {
4699                // Grammar is producing bogus matches where one open is paired with multiple
4700                // closes. Build a valid stack by walking through positions in order.
4701                // For each close, we know the expected open_len from tree-sitter matches.
4702
4703                // Map each close to its expected open length (for inferring opens)
4704                let close_to_open_len: HashMap<(usize, usize, usize), usize> = all_brackets
4705                    .iter()
4706                    .map(|(bracket_match, pattern_index, _)| {
4707                        (
4708                            (
4709                                bracket_match.close_range.start,
4710                                bracket_match.close_range.end,
4711                                *pattern_index,
4712                            ),
4713                            bracket_match.open_range.len(),
4714                        )
4715                    })
4716                    .collect();
4717
4718                // Collect unique opens and closes within this chunk
4719                let mut unique_opens: HashSet<(usize, usize, usize)> = all_brackets
4720                    .iter()
4721                    .map(|(bracket_match, pattern_index, _)| {
4722                        (
4723                            bracket_match.open_range.start,
4724                            bracket_match.open_range.end,
4725                            *pattern_index,
4726                        )
4727                    })
4728                    .filter(|(start, _, _)| chunk_range.contains(start))
4729                    .collect();
4730
4731                let mut unique_closes: Vec<(usize, usize, usize)> = all_brackets
4732                    .iter()
4733                    .map(|(bracket_match, pattern_index, _)| {
4734                        (
4735                            bracket_match.close_range.start,
4736                            bracket_match.close_range.end,
4737                            *pattern_index,
4738                        )
4739                    })
4740                    .filter(|(start, _, _)| chunk_range.contains(start))
4741                    .collect();
4742                unique_closes.sort();
4743                unique_closes.dedup();
4744
4745                // Build valid pairs by walking through closes in order
4746                let mut unique_opens_vec: Vec<_> = unique_opens.iter().copied().collect();
4747                unique_opens_vec.sort();
4748
4749                let mut valid_pairs: HashSet<((usize, usize, usize), (usize, usize, usize))> =
4750                    HashSet::default();
4751                let mut open_stacks: HashMap<usize, Vec<(usize, usize)>> = HashMap::default();
4752                let mut open_idx = 0;
4753
4754                for close in &unique_closes {
4755                    // Push all opens before this close onto stack
4756                    while open_idx < unique_opens_vec.len()
4757                        && unique_opens_vec[open_idx].0 < close.0
4758                    {
4759                        let (start, end, pattern_index) = unique_opens_vec[open_idx];
4760                        open_stacks
4761                            .entry(pattern_index)
4762                            .or_default()
4763                            .push((start, end));
4764                        open_idx += 1;
4765                    }
4766
4767                    // Try to match with most recent open
4768                    let (close_start, close_end, pattern_index) = *close;
4769                    if let Some(open) = open_stacks
4770                        .get_mut(&pattern_index)
4771                        .and_then(|open_stack| open_stack.pop())
4772                    {
4773                        valid_pairs.insert(((open.0, open.1, pattern_index), *close));
4774                    } else if let Some(&open_len) = close_to_open_len.get(close) {
4775                        // No open on stack - infer one based on expected open_len
4776                        if close_start >= open_len {
4777                            let inferred = (close_start - open_len, close_start, pattern_index);
4778                            unique_opens.insert(inferred);
4779                            valid_pairs.insert((inferred, *close));
4780                            all_brackets.push((
4781                                BracketMatch {
4782                                    open_range: inferred.0..inferred.1,
4783                                    close_range: close_start..close_end,
4784                                    newline_only: false,
4785                                    syntax_layer_depth: 0,
4786                                    color_index: None,
4787                                },
4788                                pattern_index,
4789                                false,
4790                            ));
4791                        }
4792                    }
4793                }
4794
4795                all_brackets.retain(|(bracket_match, pattern_index, _)| {
4796                    let open = (
4797                        bracket_match.open_range.start,
4798                        bracket_match.open_range.end,
4799                        *pattern_index,
4800                    );
4801                    let close = (
4802                        bracket_match.close_range.start,
4803                        bracket_match.close_range.end,
4804                        *pattern_index,
4805                    );
4806                    valid_pairs.contains(&(open, close))
4807                });
4808            }
4809
4810            let mut all_brackets = all_brackets
4811                .into_iter()
4812                .enumerate()
4813                .map(|(index, (bracket_match, _, rainbow_exclude))| {
4814                    // Certain languages have "brackets" that are not brackets, e.g. tags. and such
4815                    // bracket will match the entire tag with all text inside.
4816                    // For now, avoid highlighting any pair that has more than single char in each bracket.
4817                    // We need to  colorize `<Element/>` bracket pairs, so cannot make this check stricter.
4818                    let should_color = !rainbow_exclude
4819                        && (bracket_match.open_range.len() == 1
4820                            || bracket_match.close_range.len() == 1);
4821                    if should_color {
4822                        opens.push(bracket_match.open_range.clone());
4823                        color_pairs.push((
4824                            bracket_match.open_range.clone(),
4825                            bracket_match.close_range.clone(),
4826                            index,
4827                        ));
4828                    }
4829                    bracket_match
4830                })
4831                .collect::<Vec<_>>();
4832
4833            opens.sort_by_key(|r| (r.start, r.end));
4834            opens.dedup_by(|a, b| a.start == b.start && a.end == b.end);
4835            color_pairs.sort_by_key(|(_, close, _)| close.end);
4836
4837            let mut open_stack = Vec::new();
4838            let mut open_index = 0;
4839            for (open, close, index) in color_pairs {
4840                while open_index < opens.len() && opens[open_index].start < close.start {
4841                    open_stack.push(opens[open_index].clone());
4842                    open_index += 1;
4843                }
4844
4845                if open_stack.last() == Some(&open) {
4846                    let depth_index = open_stack.len() - 1;
4847                    all_brackets[index].color_index = Some(depth_index);
4848                    open_stack.pop();
4849                }
4850            }
4851
4852            all_brackets.sort_by_key(|bracket_match| {
4853                (bracket_match.open_range.start, bracket_match.open_range.end)
4854            });
4855
4856            if let empty_slot @ None =
4857                &mut self.tree_sitter_data.brackets_by_chunks.lock()[chunk.id]
4858            {
4859                *empty_slot = Some(all_brackets.clone());
4860            }
4861            all_bracket_matches.insert(chunk.row_range(), all_brackets);
4862        }
4863
4864        all_bracket_matches
4865    }
4866
4867    pub fn all_bracket_ranges(
4868        &self,
4869        range: Range<usize>,
4870    ) -> impl Iterator<Item = BracketMatch<usize>> {
4871        self.fetch_bracket_ranges(range.clone(), None)
4872            .into_values()
4873            .flatten()
4874            .filter(move |bracket_match| {
4875                let bracket_range = bracket_match.open_range.start..bracket_match.close_range.end;
4876                bracket_range.overlaps(&range)
4877            })
4878    }
4879
4880    /// Returns bracket range pairs overlapping or adjacent to `range`
4881    pub fn bracket_ranges<T: ToOffset>(
4882        &self,
4883        range: Range<T>,
4884    ) -> impl Iterator<Item = BracketMatch<usize>> + '_ {
4885        // Find bracket pairs that *inclusively* contain the given range.
4886        let range = range.start.to_previous_offset(self)..range.end.to_next_offset(self);
4887        self.all_bracket_ranges(range)
4888            .filter(|pair| !pair.newline_only)
4889    }
4890
4891    pub fn debug_variables_query<T: ToOffset>(
4892        &self,
4893        range: Range<T>,
4894    ) -> impl Iterator<Item = (Range<usize>, DebuggerTextObject)> + '_ {
4895        let range = range.start.to_previous_offset(self)..range.end.to_next_offset(self);
4896
4897        let mut matches = self.syntax.matches_with_options(
4898            range.clone(),
4899            &self.text,
4900            TreeSitterOptions::default(),
4901            |grammar| grammar.debug_variables_config.as_ref().map(|c| &c.query),
4902        );
4903
4904        let configs = matches
4905            .grammars()
4906            .iter()
4907            .map(|grammar| grammar.debug_variables_config.as_ref())
4908            .collect::<Vec<_>>();
4909
4910        let mut captures = Vec::<(Range<usize>, DebuggerTextObject)>::new();
4911
4912        iter::from_fn(move || {
4913            loop {
4914                while let Some(capture) = captures.pop() {
4915                    if capture.0.overlaps(&range) {
4916                        return Some(capture);
4917                    }
4918                }
4919
4920                let mat = matches.peek()?;
4921
4922                let Some(config) = configs[mat.grammar_index].as_ref() else {
4923                    matches.advance();
4924                    continue;
4925                };
4926
4927                for capture in mat.captures {
4928                    let Some(ix) = config
4929                        .objects_by_capture_ix
4930                        .binary_search_by_key(&capture.index, |e| e.0)
4931                        .ok()
4932                    else {
4933                        continue;
4934                    };
4935                    let text_object = config.objects_by_capture_ix[ix].1;
4936                    let byte_range = capture.node.byte_range();
4937
4938                    let mut found = false;
4939                    for (range, existing) in captures.iter_mut() {
4940                        if existing == &text_object {
4941                            range.start = range.start.min(byte_range.start);
4942                            range.end = range.end.max(byte_range.end);
4943                            found = true;
4944                            break;
4945                        }
4946                    }
4947
4948                    if !found {
4949                        captures.push((byte_range, text_object));
4950                    }
4951                }
4952
4953                matches.advance();
4954            }
4955        })
4956    }
4957
4958    pub fn text_object_ranges<T: ToOffset>(
4959        &self,
4960        range: Range<T>,
4961        options: TreeSitterOptions,
4962    ) -> impl Iterator<Item = (Range<usize>, TextObject)> + '_ {
4963        let range =
4964            range.start.to_previous_offset(self)..self.len().min(range.end.to_next_offset(self));
4965
4966        let mut matches =
4967            self.syntax
4968                .matches_with_options(range.clone(), &self.text, options, |grammar| {
4969                    grammar.text_object_config.as_ref().map(|c| &c.query)
4970                });
4971
4972        let configs = matches
4973            .grammars()
4974            .iter()
4975            .map(|grammar| grammar.text_object_config.as_ref())
4976            .collect::<Vec<_>>();
4977
4978        let mut captures = Vec::<(Range<usize>, TextObject)>::new();
4979
4980        iter::from_fn(move || {
4981            loop {
4982                while let Some(capture) = captures.pop() {
4983                    if capture.0.overlaps(&range) {
4984                        return Some(capture);
4985                    }
4986                }
4987
4988                let mat = matches.peek()?;
4989
4990                let Some(config) = configs[mat.grammar_index].as_ref() else {
4991                    matches.advance();
4992                    continue;
4993                };
4994
4995                for capture in mat.captures {
4996                    let Some(ix) = config
4997                        .text_objects_by_capture_ix
4998                        .binary_search_by_key(&capture.index, |e| e.0)
4999                        .ok()
5000                    else {
5001                        continue;
5002                    };
5003                    let text_object = config.text_objects_by_capture_ix[ix].1;
5004                    let byte_range = capture.node.byte_range();
5005
5006                    let mut found = false;
5007                    for (range, existing) in captures.iter_mut() {
5008                        if existing == &text_object {
5009                            range.start = range.start.min(byte_range.start);
5010                            range.end = range.end.max(byte_range.end);
5011                            found = true;
5012                            break;
5013                        }
5014                    }
5015
5016                    if !found {
5017                        captures.push((byte_range, text_object));
5018                    }
5019                }
5020
5021                matches.advance();
5022            }
5023        })
5024    }
5025
5026    /// Returns enclosing bracket ranges containing the given range
5027    pub fn enclosing_bracket_ranges<T: ToOffset>(
5028        &self,
5029        range: Range<T>,
5030    ) -> impl Iterator<Item = BracketMatch<usize>> + '_ {
5031        let range = range.start.to_offset(self)..range.end.to_offset(self);
5032
5033        let result: Vec<_> = self.bracket_ranges(range.clone()).collect();
5034        let max_depth = result
5035            .iter()
5036            .map(|mat| mat.syntax_layer_depth)
5037            .max()
5038            .unwrap_or(0);
5039        result.into_iter().filter(move |pair| {
5040            pair.open_range.start <= range.start
5041                && pair.close_range.end >= range.end
5042                && pair.syntax_layer_depth == max_depth
5043        })
5044    }
5045
5046    /// Returns the smallest enclosing bracket ranges containing the given range or None if no brackets contain range
5047    ///
5048    /// Can optionally pass a range_filter to filter the ranges of brackets to consider
5049    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
5050        &self,
5051        range: Range<T>,
5052        range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
5053    ) -> Option<(Range<usize>, Range<usize>)> {
5054        let range = range.start.to_offset(self)..range.end.to_offset(self);
5055
5056        // Get the ranges of the innermost pair of brackets.
5057        let mut result: Option<(Range<usize>, Range<usize>)> = None;
5058
5059        for pair in self.enclosing_bracket_ranges(range) {
5060            if let Some(range_filter) = range_filter
5061                && !range_filter(pair.open_range.clone(), pair.close_range.clone())
5062            {
5063                continue;
5064            }
5065
5066            let len = pair.close_range.end - pair.open_range.start;
5067
5068            if let Some((existing_open, existing_close)) = &result {
5069                let existing_len = existing_close.end - existing_open.start;
5070                if len > existing_len {
5071                    continue;
5072                }
5073            }
5074
5075            result = Some((pair.open_range, pair.close_range));
5076        }
5077
5078        result
5079    }
5080
5081    /// Returns anchor ranges for any matches of the redaction query.
5082    /// The buffer can be associated with multiple languages, and the redaction query associated with each
5083    /// will be run on the relevant section of the buffer.
5084    pub fn redacted_ranges<T: ToOffset>(
5085        &self,
5086        range: Range<T>,
5087    ) -> impl Iterator<Item = Range<usize>> + '_ {
5088        let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
5089        let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
5090            grammar
5091                .redactions_config
5092                .as_ref()
5093                .map(|config| &config.query)
5094        });
5095
5096        let configs = syntax_matches
5097            .grammars()
5098            .iter()
5099            .map(|grammar| grammar.redactions_config.as_ref())
5100            .collect::<Vec<_>>();
5101
5102        iter::from_fn(move || {
5103            let redacted_range = syntax_matches
5104                .peek()
5105                .and_then(|mat| {
5106                    configs[mat.grammar_index].and_then(|config| {
5107                        mat.captures
5108                            .iter()
5109                            .find(|capture| capture.index == config.redaction_capture_ix)
5110                    })
5111                })
5112                .map(|mat| mat.node.byte_range());
5113            syntax_matches.advance();
5114            redacted_range
5115        })
5116    }
5117
5118    pub fn injections_intersecting_range<T: ToOffset>(
5119        &self,
5120        range: Range<T>,
5121    ) -> impl Iterator<Item = (Range<usize>, &Arc<Language>)> + '_ {
5122        let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
5123
5124        let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
5125            grammar
5126                .injection_config
5127                .as_ref()
5128                .map(|config| &config.query)
5129        });
5130
5131        let configs = syntax_matches
5132            .grammars()
5133            .iter()
5134            .map(|grammar| grammar.injection_config.as_ref())
5135            .collect::<Vec<_>>();
5136
5137        iter::from_fn(move || {
5138            let ranges = syntax_matches.peek().and_then(|mat| {
5139                let config = &configs[mat.grammar_index]?;
5140                let content_capture_range = mat.captures.iter().find_map(|capture| {
5141                    if capture.index == config.content_capture_ix {
5142                        Some(capture.node.byte_range())
5143                    } else {
5144                        None
5145                    }
5146                })?;
5147                let language = self.language_at(content_capture_range.start)?;
5148                Some((content_capture_range, language))
5149            });
5150            syntax_matches.advance();
5151            ranges
5152        })
5153    }
5154
5155    pub fn runnable_ranges(
5156        &self,
5157        offset_range: Range<usize>,
5158    ) -> impl Iterator<Item = RunnableRange> + '_ {
5159        let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
5160            grammar.runnable_config.as_ref().map(|config| &config.query)
5161        });
5162
5163        let test_configs = syntax_matches
5164            .grammars()
5165            .iter()
5166            .map(|grammar| grammar.runnable_config.as_ref())
5167            .collect::<Vec<_>>();
5168
5169        iter::from_fn(move || {
5170            loop {
5171                let mat = syntax_matches.peek()?;
5172
5173                let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
5174                    let mut run_range = None;
5175                    let full_range = mat.captures.iter().fold(
5176                        Range {
5177                            start: usize::MAX,
5178                            end: 0,
5179                        },
5180                        |mut acc, next| {
5181                            let byte_range = next.node.byte_range();
5182                            if acc.start > byte_range.start {
5183                                acc.start = byte_range.start;
5184                            }
5185                            if acc.end < byte_range.end {
5186                                acc.end = byte_range.end;
5187                            }
5188                            acc
5189                        },
5190                    );
5191                    if full_range.start > full_range.end {
5192                        // We did not find a full spanning range of this match.
5193                        return None;
5194                    }
5195                    let extra_captures: SmallVec<[_; 1]> =
5196                        SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
5197                            test_configs
5198                                .extra_captures
5199                                .get(capture.index as usize)
5200                                .cloned()
5201                                .and_then(|tag_name| match tag_name {
5202                                    RunnableCapture::Named(name) => {
5203                                        Some((capture.node.byte_range(), name))
5204                                    }
5205                                    RunnableCapture::Run => {
5206                                        let _ = run_range.insert(capture.node.byte_range());
5207                                        None
5208                                    }
5209                                })
5210                        }));
5211                    let run_range = run_range?;
5212                    let tags = test_configs
5213                        .query
5214                        .property_settings(mat.pattern_index)
5215                        .iter()
5216                        .filter_map(|property| {
5217                            if *property.key == *"tag" {
5218                                property
5219                                    .value
5220                                    .as_ref()
5221                                    .map(|value| RunnableTag(value.to_string().into()))
5222                            } else {
5223                                None
5224                            }
5225                        })
5226                        .collect();
5227                    let extra_captures = extra_captures
5228                        .into_iter()
5229                        .map(|(range, name)| {
5230                            (
5231                                name.to_string(),
5232                                self.text_for_range(range).collect::<String>(),
5233                            )
5234                        })
5235                        .collect();
5236                    // All tags should have the same range.
5237                    Some(RunnableRange {
5238                        run_range,
5239                        full_range,
5240                        runnable: Runnable {
5241                            tags,
5242                            language: mat.language,
5243                            buffer: self.remote_id(),
5244                        },
5245                        extra_captures,
5246                        buffer_id: self.remote_id(),
5247                    })
5248                });
5249
5250                syntax_matches.advance();
5251                if test_range.is_some() {
5252                    // It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
5253                    // had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
5254                    return test_range;
5255                }
5256            }
5257        })
5258    }
5259
5260    /// Returns selections for remote peers intersecting the given range.
5261    #[allow(clippy::type_complexity)]
5262    pub fn selections_in_range(
5263        &self,
5264        range: Range<Anchor>,
5265        include_local: bool,
5266    ) -> impl Iterator<
5267        Item = (
5268            ReplicaId,
5269            bool,
5270            CursorShape,
5271            impl Iterator<Item = &Selection<Anchor>> + '_,
5272        ),
5273    > + '_ {
5274        self.remote_selections
5275            .iter()
5276            .filter(move |(replica_id, set)| {
5277                (include_local || **replica_id != self.text.replica_id())
5278                    && !set.selections.is_empty()
5279            })
5280            .map(move |(replica_id, set)| {
5281                let start_ix = match set.selections.binary_search_by(|probe| {
5282                    probe.end.cmp(&range.start, self).then(Ordering::Greater)
5283                }) {
5284                    Ok(ix) | Err(ix) => ix,
5285                };
5286                let end_ix = match set.selections.binary_search_by(|probe| {
5287                    probe.start.cmp(&range.end, self).then(Ordering::Less)
5288                }) {
5289                    Ok(ix) | Err(ix) => ix,
5290                };
5291
5292                (
5293                    *replica_id,
5294                    set.line_mode,
5295                    set.cursor_shape,
5296                    set.selections[start_ix..end_ix].iter(),
5297                )
5298            })
5299    }
5300
5301    /// Returns if the buffer contains any diagnostics.
5302    pub fn has_diagnostics(&self) -> bool {
5303        !self.diagnostics.is_empty()
5304    }
5305
5306    /// Returns all the diagnostics intersecting the given range.
5307    pub fn diagnostics_in_range<'a, T, O>(
5308        &'a self,
5309        search_range: Range<T>,
5310        reversed: bool,
5311    ) -> impl 'a + Iterator<Item = DiagnosticEntryRef<'a, O>>
5312    where
5313        T: 'a + Clone + ToOffset,
5314        O: 'a + FromAnchor,
5315    {
5316        let mut iterators: Vec<_> = self
5317            .diagnostics
5318            .iter()
5319            .map(|(_, collection)| {
5320                collection
5321                    .range::<T, text::Anchor>(search_range.clone(), self, true, reversed)
5322                    .peekable()
5323            })
5324            .collect();
5325
5326        std::iter::from_fn(move || {
5327            let (next_ix, _) = iterators
5328                .iter_mut()
5329                .enumerate()
5330                .flat_map(|(ix, iter)| Some((ix, iter.peek()?)))
5331                .min_by(|(_, a), (_, b)| {
5332                    let cmp = a
5333                        .range
5334                        .start
5335                        .cmp(&b.range.start, self)
5336                        // when range is equal, sort by diagnostic severity
5337                        .then(a.diagnostic.severity.cmp(&b.diagnostic.severity))
5338                        // and stabilize order with group_id
5339                        .then(a.diagnostic.group_id.cmp(&b.diagnostic.group_id));
5340                    if reversed { cmp.reverse() } else { cmp }
5341                })?;
5342            iterators[next_ix]
5343                .next()
5344                .map(
5345                    |DiagnosticEntryRef { range, diagnostic }| DiagnosticEntryRef {
5346                        diagnostic,
5347                        range: FromAnchor::from_anchor(&range.start, self)
5348                            ..FromAnchor::from_anchor(&range.end, self),
5349                    },
5350                )
5351        })
5352    }
5353
5354    /// Returns all the diagnostic groups associated with the given
5355    /// language server ID. If no language server ID is provided,
5356    /// all diagnostics groups are returned.
5357    pub fn diagnostic_groups(
5358        &self,
5359        language_server_id: Option<LanguageServerId>,
5360    ) -> Vec<(LanguageServerId, DiagnosticGroup<'_, Anchor>)> {
5361        let mut groups = Vec::new();
5362
5363        if let Some(language_server_id) = language_server_id {
5364            if let Some(set) = self.diagnostics.get(&language_server_id) {
5365                set.groups(language_server_id, &mut groups, self);
5366            }
5367        } else {
5368            for (language_server_id, diagnostics) in self.diagnostics.iter() {
5369                diagnostics.groups(*language_server_id, &mut groups, self);
5370            }
5371        }
5372
5373        groups.sort_by(|(id_a, group_a), (id_b, group_b)| {
5374            let a_start = &group_a.entries[group_a.primary_ix].range.start;
5375            let b_start = &group_b.entries[group_b.primary_ix].range.start;
5376            a_start.cmp(b_start, self).then_with(|| id_a.cmp(id_b))
5377        });
5378
5379        groups
5380    }
5381
5382    /// Returns an iterator over the diagnostics for the given group.
5383    pub fn diagnostic_group<O>(
5384        &self,
5385        group_id: usize,
5386    ) -> impl Iterator<Item = DiagnosticEntryRef<'_, O>> + use<'_, O>
5387    where
5388        O: FromAnchor + 'static,
5389    {
5390        self.diagnostics
5391            .iter()
5392            .flat_map(move |(_, set)| set.group(group_id, self))
5393    }
5394
5395    /// An integer version number that accounts for all updates besides
5396    /// the buffer's text itself (which is versioned via a version vector).
5397    pub fn non_text_state_update_count(&self) -> usize {
5398        self.non_text_state_update_count
5399    }
5400
5401    /// An integer version that changes when the buffer's syntax changes.
5402    pub fn syntax_update_count(&self) -> usize {
5403        self.syntax.update_count()
5404    }
5405
5406    /// Returns a snapshot of underlying file.
5407    pub fn file(&self) -> Option<&Arc<dyn File>> {
5408        self.file.as_ref()
5409    }
5410
5411    pub fn resolve_file_path(&self, include_root: bool, cx: &App) -> Option<String> {
5412        if let Some(file) = self.file() {
5413            if file.path().file_name().is_none() || include_root {
5414                Some(file.full_path(cx).to_string_lossy().into_owned())
5415            } else {
5416                Some(file.path().display(file.path_style(cx)).to_string())
5417            }
5418        } else {
5419            None
5420        }
5421    }
5422
5423    pub fn words_in_range(&self, query: WordsQuery) -> BTreeMap<String, Range<Anchor>> {
5424        let query_str = query.fuzzy_contents;
5425        if query_str.is_some_and(|query| query.is_empty()) {
5426            return BTreeMap::default();
5427        }
5428
5429        let classifier = CharClassifier::new(self.language.clone().map(|language| LanguageScope {
5430            language,
5431            override_id: None,
5432        }));
5433
5434        let mut query_ix = 0;
5435        let query_chars = query_str.map(|query| query.chars().collect::<Vec<_>>());
5436        let query_len = query_chars.as_ref().map_or(0, |query| query.len());
5437
5438        let mut words = BTreeMap::default();
5439        let mut current_word_start_ix = None;
5440        let mut chunk_ix = query.range.start;
5441        for chunk in self.chunks(
5442            query.range,
5443            LanguageAwareStyling {
5444                tree_sitter: false,
5445                diagnostics: false,
5446            },
5447        ) {
5448            for (i, c) in chunk.text.char_indices() {
5449                let ix = chunk_ix + i;
5450                if classifier.is_word(c) {
5451                    if current_word_start_ix.is_none() {
5452                        current_word_start_ix = Some(ix);
5453                    }
5454
5455                    if let Some(query_chars) = &query_chars
5456                        && query_ix < query_len
5457                        && c.to_lowercase().eq(query_chars[query_ix].to_lowercase())
5458                    {
5459                        query_ix += 1;
5460                    }
5461                    continue;
5462                } else if let Some(word_start) = current_word_start_ix.take()
5463                    && query_ix == query_len
5464                {
5465                    let word_range = self.anchor_before(word_start)..self.anchor_after(ix);
5466                    let mut word_text = self.text_for_range(word_start..ix).peekable();
5467                    let first_char = word_text
5468                        .peek()
5469                        .and_then(|first_chunk| first_chunk.chars().next());
5470                    // Skip empty and "words" starting with digits as a heuristic to reduce useless completions
5471                    if !query.skip_digits
5472                        || first_char.is_none_or(|first_char| !first_char.is_digit(10))
5473                    {
5474                        words.insert(word_text.collect(), word_range);
5475                    }
5476                }
5477                query_ix = 0;
5478            }
5479            chunk_ix += chunk.text.len();
5480        }
5481
5482        words
5483    }
5484}
5485
5486/// A configuration to use when producing styled text chunks.
5487#[derive(Clone, Copy)]
5488pub struct LanguageAwareStyling {
5489    /// Whether to highlight text chunks using tree-sitter.
5490    pub tree_sitter: bool,
5491    /// Whether to highlight text chunks based on the diagnostics data.
5492    pub diagnostics: bool,
5493}
5494
5495pub struct WordsQuery<'a> {
5496    /// Only returns words with all chars from the fuzzy string in them.
5497    pub fuzzy_contents: Option<&'a str>,
5498    /// Skips words that start with a digit.
5499    pub skip_digits: bool,
5500    /// Buffer offset range, to look for words.
5501    pub range: Range<usize>,
5502}
5503
5504fn indent_size_for_line(text: &text::BufferSnapshot, row: u32) -> IndentSize {
5505    indent_size_for_text(text.chars_at(Point::new(row, 0)))
5506}
5507
5508fn indent_size_for_text(text: impl Iterator<Item = char>) -> IndentSize {
5509    let mut result = IndentSize::spaces(0);
5510    for c in text {
5511        let kind = match c {
5512            ' ' => IndentKind::Space,
5513            '\t' => IndentKind::Tab,
5514            _ => break,
5515        };
5516        if result.len == 0 {
5517            result.kind = kind;
5518        }
5519        result.len += 1;
5520    }
5521    result
5522}
5523
5524impl Clone for BufferSnapshot {
5525    fn clone(&self) -> Self {
5526        Self {
5527            text: self.text.clone(),
5528            syntax: self.syntax.clone(),
5529            file: self.file.clone(),
5530            remote_selections: self.remote_selections.clone(),
5531            diagnostics: self.diagnostics.clone(),
5532            language: self.language.clone(),
5533            tree_sitter_data: self.tree_sitter_data.clone(),
5534            non_text_state_update_count: self.non_text_state_update_count,
5535            capability: self.capability,
5536            modeline: self.modeline.clone(),
5537        }
5538    }
5539}
5540
5541impl Deref for BufferSnapshot {
5542    type Target = text::BufferSnapshot;
5543
5544    fn deref(&self) -> &Self::Target {
5545        &self.text
5546    }
5547}
5548
5549unsafe impl Send for BufferChunks<'_> {}
5550
5551impl<'a> BufferChunks<'a> {
5552    pub(crate) fn new(
5553        text: &'a Rope,
5554        range: Range<usize>,
5555        syntax: Option<(SyntaxMapCaptures<'a>, Vec<HighlightMap>)>,
5556        diagnostics: bool,
5557        buffer_snapshot: Option<&'a BufferSnapshot>,
5558    ) -> Self {
5559        let mut highlights = None;
5560        if let Some((captures, highlight_maps)) = syntax {
5561            highlights = Some(BufferChunkHighlights {
5562                captures,
5563                next_capture: None,
5564                stack: Default::default(),
5565                highlight_maps,
5566            })
5567        }
5568
5569        let diagnostic_endpoints = diagnostics.then(|| Vec::new().into_iter().peekable());
5570        let chunks = text.chunks_in_range(range.clone());
5571
5572        let mut this = BufferChunks {
5573            range,
5574            buffer_snapshot,
5575            chunks,
5576            diagnostic_endpoints,
5577            error_depth: 0,
5578            warning_depth: 0,
5579            information_depth: 0,
5580            hint_depth: 0,
5581            unnecessary_depth: 0,
5582            underline: true,
5583            highlights,
5584        };
5585        this.initialize_diagnostic_endpoints();
5586        this
5587    }
5588
5589    /// Seeks to the given byte offset in the buffer.
5590    pub fn seek(&mut self, range: Range<usize>) {
5591        let old_range = std::mem::replace(&mut self.range, range.clone());
5592        self.chunks.set_range(self.range.clone());
5593        if let Some(highlights) = self.highlights.as_mut() {
5594            if old_range.start <= self.range.start && old_range.end >= self.range.end {
5595                // Reuse existing highlights stack, as the new range is a subrange of the old one.
5596                highlights
5597                    .stack
5598                    .retain(|(end_offset, _)| *end_offset > range.start);
5599                if let Some(capture) = &highlights.next_capture
5600                    && range.start >= capture.node.start_byte()
5601                {
5602                    let next_capture_end = capture.node.end_byte();
5603                    if range.start < next_capture_end
5604                        && let Some(capture_id) =
5605                            highlights.highlight_maps[capture.grammar_index].get(capture.index)
5606                    {
5607                        highlights.stack.push((next_capture_end, capture_id));
5608                    }
5609                    highlights.next_capture.take();
5610                }
5611            } else if let Some(snapshot) = self.buffer_snapshot {
5612                let (captures, highlight_maps) = snapshot.get_highlights(self.range.clone());
5613                *highlights = BufferChunkHighlights {
5614                    captures,
5615                    next_capture: None,
5616                    stack: Default::default(),
5617                    highlight_maps,
5618                };
5619            } else {
5620                // We cannot obtain new highlights for a language-aware buffer iterator, as we don't have a buffer snapshot.
5621                // Seeking such BufferChunks is not supported.
5622                debug_assert!(
5623                    false,
5624                    "Attempted to seek on a language-aware buffer iterator without associated buffer snapshot"
5625                );
5626            }
5627
5628            highlights.captures.set_byte_range(self.range.clone());
5629            self.initialize_diagnostic_endpoints();
5630        }
5631    }
5632
5633    fn initialize_diagnostic_endpoints(&mut self) {
5634        if let Some(diagnostics) = self.diagnostic_endpoints.as_mut()
5635            && let Some(buffer) = self.buffer_snapshot
5636        {
5637            let mut diagnostic_endpoints = Vec::new();
5638            for entry in buffer.diagnostics_in_range::<_, usize>(self.range.clone(), false) {
5639                diagnostic_endpoints.push(DiagnosticEndpoint {
5640                    offset: entry.range.start,
5641                    is_start: true,
5642                    severity: entry.diagnostic.severity,
5643                    is_unnecessary: entry.diagnostic.is_unnecessary,
5644                    underline: entry.diagnostic.underline,
5645                });
5646                diagnostic_endpoints.push(DiagnosticEndpoint {
5647                    offset: entry.range.end,
5648                    is_start: false,
5649                    severity: entry.diagnostic.severity,
5650                    is_unnecessary: entry.diagnostic.is_unnecessary,
5651                    underline: entry.diagnostic.underline,
5652                });
5653            }
5654            diagnostic_endpoints
5655                .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
5656            *diagnostics = diagnostic_endpoints.into_iter().peekable();
5657            self.hint_depth = 0;
5658            self.error_depth = 0;
5659            self.warning_depth = 0;
5660            self.information_depth = 0;
5661        }
5662    }
5663
5664    /// The current byte offset in the buffer.
5665    pub fn offset(&self) -> usize {
5666        self.range.start
5667    }
5668
5669    pub fn range(&self) -> Range<usize> {
5670        self.range.clone()
5671    }
5672
5673    fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
5674        let depth = match endpoint.severity {
5675            DiagnosticSeverity::ERROR => &mut self.error_depth,
5676            DiagnosticSeverity::WARNING => &mut self.warning_depth,
5677            DiagnosticSeverity::INFORMATION => &mut self.information_depth,
5678            DiagnosticSeverity::HINT => &mut self.hint_depth,
5679            _ => return,
5680        };
5681        if endpoint.is_start {
5682            *depth += 1;
5683        } else {
5684            *depth -= 1;
5685        }
5686
5687        if endpoint.is_unnecessary {
5688            if endpoint.is_start {
5689                self.unnecessary_depth += 1;
5690            } else {
5691                self.unnecessary_depth -= 1;
5692            }
5693        }
5694    }
5695
5696    fn current_diagnostic_severity(&self) -> Option<DiagnosticSeverity> {
5697        if self.error_depth > 0 {
5698            Some(DiagnosticSeverity::ERROR)
5699        } else if self.warning_depth > 0 {
5700            Some(DiagnosticSeverity::WARNING)
5701        } else if self.information_depth > 0 {
5702            Some(DiagnosticSeverity::INFORMATION)
5703        } else if self.hint_depth > 0 {
5704            Some(DiagnosticSeverity::HINT)
5705        } else {
5706            None
5707        }
5708    }
5709
5710    fn current_code_is_unnecessary(&self) -> bool {
5711        self.unnecessary_depth > 0
5712    }
5713}
5714
5715impl<'a> Iterator for BufferChunks<'a> {
5716    type Item = Chunk<'a>;
5717
5718    fn next(&mut self) -> Option<Self::Item> {
5719        let mut next_capture_start = usize::MAX;
5720        let mut next_diagnostic_endpoint = usize::MAX;
5721
5722        if let Some(highlights) = self.highlights.as_mut() {
5723            while let Some((parent_capture_end, _)) = highlights.stack.last() {
5724                if *parent_capture_end <= self.range.start {
5725                    highlights.stack.pop();
5726                } else {
5727                    break;
5728                }
5729            }
5730
5731            if highlights.next_capture.is_none() {
5732                highlights.next_capture = highlights.captures.next();
5733            }
5734
5735            while let Some(capture) = highlights.next_capture.as_ref() {
5736                if self.range.start < capture.node.start_byte() {
5737                    next_capture_start = capture.node.start_byte();
5738                    break;
5739                } else {
5740                    let highlight_id =
5741                        highlights.highlight_maps[capture.grammar_index].get(capture.index);
5742                    if let Some(highlight_id) = highlight_id {
5743                        highlights
5744                            .stack
5745                            .push((capture.node.end_byte(), highlight_id));
5746                    }
5747                    highlights.next_capture = highlights.captures.next();
5748                }
5749            }
5750        }
5751
5752        let mut diagnostic_endpoints = std::mem::take(&mut self.diagnostic_endpoints);
5753        if let Some(diagnostic_endpoints) = diagnostic_endpoints.as_mut() {
5754            while let Some(endpoint) = diagnostic_endpoints.peek().copied() {
5755                if endpoint.offset <= self.range.start {
5756                    self.update_diagnostic_depths(endpoint);
5757                    diagnostic_endpoints.next();
5758                    self.underline = endpoint.underline;
5759                } else {
5760                    next_diagnostic_endpoint = endpoint.offset;
5761                    break;
5762                }
5763            }
5764        }
5765        self.diagnostic_endpoints = diagnostic_endpoints;
5766
5767        if let Some(ChunkBitmaps {
5768            text: chunk,
5769            chars: chars_map,
5770            tabs,
5771            newlines,
5772        }) = self.chunks.peek_with_bitmaps()
5773        {
5774            let chunk_start = self.range.start;
5775            let mut chunk_end = (self.chunks.offset() + chunk.len())
5776                .min(next_capture_start)
5777                .min(next_diagnostic_endpoint);
5778            let mut highlight_id = None;
5779            if let Some(highlights) = self.highlights.as_ref()
5780                && let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last()
5781            {
5782                chunk_end = chunk_end.min(*parent_capture_end);
5783                highlight_id = Some(*parent_highlight_id);
5784            }
5785            let bit_start = chunk_start - self.chunks.offset();
5786            let bit_end = chunk_end - self.chunks.offset();
5787
5788            let slice = &chunk[bit_start..bit_end];
5789
5790            let mask = 1u128.unbounded_shl(bit_end as u32).wrapping_sub(1);
5791            let tabs = (tabs >> bit_start) & mask;
5792            let chars = (chars_map >> bit_start) & mask;
5793            let newlines = (newlines >> bit_start) & mask;
5794
5795            self.range.start = chunk_end;
5796            if self.range.start == self.chunks.offset() + chunk.len() {
5797                self.chunks.next().unwrap();
5798            }
5799
5800            Some(Chunk {
5801                text: slice,
5802                syntax_highlight_id: highlight_id,
5803                underline: self.underline,
5804                diagnostic_severity: self.current_diagnostic_severity(),
5805                is_unnecessary: self.current_code_is_unnecessary(),
5806                tabs,
5807                chars,
5808                newlines,
5809                ..Chunk::default()
5810            })
5811        } else {
5812            None
5813        }
5814    }
5815}
5816
5817impl operation_queue::Operation for Operation {
5818    fn lamport_timestamp(&self) -> clock::Lamport {
5819        match self {
5820            Operation::Buffer(_) => {
5821                unreachable!("buffer operations should never be deferred at this layer")
5822            }
5823            Operation::UpdateDiagnostics {
5824                lamport_timestamp, ..
5825            }
5826            | Operation::UpdateSelections {
5827                lamport_timestamp, ..
5828            }
5829            | Operation::UpdateCompletionTriggers {
5830                lamport_timestamp, ..
5831            }
5832            | Operation::UpdateLineEnding {
5833                lamport_timestamp, ..
5834            } => *lamport_timestamp,
5835        }
5836    }
5837}
5838
5839impl IndentSize {
5840    /// Returns an [`IndentSize`] representing the given spaces.
5841    pub fn spaces(len: u32) -> Self {
5842        Self {
5843            len,
5844            kind: IndentKind::Space,
5845        }
5846    }
5847
5848    /// Returns an [`IndentSize`] representing a tab.
5849    pub fn tab() -> Self {
5850        Self {
5851            len: 1,
5852            kind: IndentKind::Tab,
5853        }
5854    }
5855
5856    /// An iterator over the characters represented by this [`IndentSize`].
5857    pub fn chars(&self) -> impl Iterator<Item = char> {
5858        iter::repeat(self.char()).take(self.len as usize)
5859    }
5860
5861    /// The character representation of this [`IndentSize`].
5862    pub fn char(&self) -> char {
5863        match self.kind {
5864            IndentKind::Space => ' ',
5865            IndentKind::Tab => '\t',
5866        }
5867    }
5868
5869    /// Consumes the current [`IndentSize`] and returns a new one that has
5870    /// been shrunk or enlarged by the given size along the given direction.
5871    pub fn with_delta(mut self, direction: Ordering, size: IndentSize) -> Self {
5872        match direction {
5873            Ordering::Less => {
5874                if self.kind == size.kind && self.len >= size.len {
5875                    self.len -= size.len;
5876                }
5877            }
5878            Ordering::Equal => {}
5879            Ordering::Greater => {
5880                if self.len == 0 {
5881                    self = size;
5882                } else if self.kind == size.kind {
5883                    self.len += size.len;
5884                }
5885            }
5886        }
5887        self
5888    }
5889
5890    pub fn len_with_expanded_tabs(&self, tab_size: NonZeroU32) -> usize {
5891        match self.kind {
5892            IndentKind::Space => self.len as usize,
5893            IndentKind::Tab => self.len as usize * tab_size.get() as usize,
5894        }
5895    }
5896}
5897
5898#[cfg(any(test, feature = "test-support"))]
5899pub struct TestFile {
5900    pub path: Arc<RelPath>,
5901    pub root_name: String,
5902    pub local_root: Option<PathBuf>,
5903}
5904
5905#[cfg(any(test, feature = "test-support"))]
5906impl File for TestFile {
5907    fn path(&self) -> &Arc<RelPath> {
5908        &self.path
5909    }
5910
5911    fn full_path(&self, _: &gpui::App) -> PathBuf {
5912        PathBuf::from(self.root_name.clone()).join(self.path.as_std_path())
5913    }
5914
5915    fn as_local(&self) -> Option<&dyn LocalFile> {
5916        if self.local_root.is_some() {
5917            Some(self)
5918        } else {
5919            None
5920        }
5921    }
5922
5923    fn disk_state(&self) -> DiskState {
5924        unimplemented!()
5925    }
5926
5927    fn file_name<'a>(&'a self, _: &'a gpui::App) -> &'a str {
5928        self.path().file_name().unwrap_or(self.root_name.as_ref())
5929    }
5930
5931    fn worktree_id(&self, _: &App) -> WorktreeId {
5932        WorktreeId::from_usize(0)
5933    }
5934
5935    fn to_proto(&self, _: &App) -> rpc::proto::File {
5936        unimplemented!()
5937    }
5938
5939    fn is_private(&self) -> bool {
5940        false
5941    }
5942
5943    fn path_style(&self, _cx: &App) -> PathStyle {
5944        PathStyle::local()
5945    }
5946}
5947
5948#[cfg(any(test, feature = "test-support"))]
5949impl LocalFile for TestFile {
5950    fn abs_path(&self, _cx: &App) -> PathBuf {
5951        PathBuf::from(self.local_root.as_ref().unwrap())
5952            .join(&self.root_name)
5953            .join(self.path.as_std_path())
5954    }
5955
5956    fn load(&self, _cx: &App) -> Task<Result<String>> {
5957        unimplemented!()
5958    }
5959
5960    fn load_bytes(&self, _cx: &App) -> Task<Result<Vec<u8>>> {
5961        unimplemented!()
5962    }
5963}
5964
5965pub(crate) fn contiguous_ranges(
5966    values: impl Iterator<Item = u32>,
5967    max_len: usize,
5968) -> impl Iterator<Item = Range<u32>> {
5969    let mut values = values;
5970    let mut current_range: Option<Range<u32>> = None;
5971    std::iter::from_fn(move || {
5972        loop {
5973            if let Some(value) = values.next() {
5974                if let Some(range) = &mut current_range
5975                    && value == range.end
5976                    && range.len() < max_len
5977                {
5978                    range.end += 1;
5979                    continue;
5980                }
5981
5982                let prev_range = current_range.clone();
5983                current_range = Some(value..(value + 1));
5984                if prev_range.is_some() {
5985                    return prev_range;
5986                }
5987            } else {
5988                return current_range.take();
5989            }
5990        }
5991    })
5992}
5993
5994#[derive(Default, Debug)]
5995pub struct CharClassifier {
5996    scope: Option<LanguageScope>,
5997    scope_context: Option<CharScopeContext>,
5998    ignore_punctuation: bool,
5999}
6000
6001impl CharClassifier {
6002    pub fn new(scope: Option<LanguageScope>) -> Self {
6003        Self {
6004            scope,
6005            scope_context: None,
6006            ignore_punctuation: false,
6007        }
6008    }
6009
6010    pub fn scope_context(self, scope_context: Option<CharScopeContext>) -> Self {
6011        Self {
6012            scope_context,
6013            ..self
6014        }
6015    }
6016
6017    pub fn ignore_punctuation(self, ignore_punctuation: bool) -> Self {
6018        Self {
6019            ignore_punctuation,
6020            ..self
6021        }
6022    }
6023
6024    pub fn is_whitespace(&self, c: char) -> bool {
6025        self.kind(c) == CharKind::Whitespace
6026    }
6027
6028    pub fn is_word(&self, c: char) -> bool {
6029        self.kind(c) == CharKind::Word
6030    }
6031
6032    pub fn is_punctuation(&self, c: char) -> bool {
6033        self.kind(c) == CharKind::Punctuation
6034    }
6035
6036    pub fn kind_with(&self, c: char, ignore_punctuation: bool) -> CharKind {
6037        if c.is_alphanumeric() || c == '_' {
6038            return CharKind::Word;
6039        }
6040
6041        if let Some(scope) = &self.scope {
6042            let characters = match self.scope_context {
6043                Some(CharScopeContext::Completion) => scope.completion_query_characters(),
6044                Some(CharScopeContext::LinkedEdit) => scope.linked_edit_characters(),
6045                None => scope.word_characters(),
6046            };
6047            if let Some(characters) = characters
6048                && characters.contains(&c)
6049            {
6050                return CharKind::Word;
6051            }
6052        }
6053
6054        if c.is_whitespace() {
6055            return CharKind::Whitespace;
6056        }
6057
6058        if ignore_punctuation {
6059            CharKind::Word
6060        } else {
6061            CharKind::Punctuation
6062        }
6063    }
6064
6065    pub fn kind(&self, c: char) -> CharKind {
6066        self.kind_with(c, self.ignore_punctuation)
6067    }
6068}
6069
6070/// Find all of the ranges of whitespace that occur at the ends of lines
6071/// in the given rope.
6072///
6073/// This could also be done with a regex search, but this implementation
6074/// avoids copying text.
6075pub fn trailing_whitespace_ranges(rope: &Rope) -> Vec<Range<usize>> {
6076    let mut ranges = Vec::new();
6077
6078    let mut offset = 0;
6079    let mut prev_chunk_trailing_whitespace_range = 0..0;
6080    for chunk in rope.chunks() {
6081        let mut prev_line_trailing_whitespace_range = 0..0;
6082        for (i, line) in chunk.split('\n').enumerate() {
6083            let line_end_offset = offset + line.len();
6084            let trimmed_line_len = line.trim_end_matches([' ', '\t']).len();
6085            let mut trailing_whitespace_range = (offset + trimmed_line_len)..line_end_offset;
6086
6087            if i == 0 && trimmed_line_len == 0 {
6088                trailing_whitespace_range.start = prev_chunk_trailing_whitespace_range.start;
6089            }
6090            if !prev_line_trailing_whitespace_range.is_empty() {
6091                ranges.push(prev_line_trailing_whitespace_range);
6092            }
6093
6094            offset = line_end_offset + 1;
6095            prev_line_trailing_whitespace_range = trailing_whitespace_range;
6096        }
6097
6098        offset -= 1;
6099        prev_chunk_trailing_whitespace_range = prev_line_trailing_whitespace_range;
6100    }
6101
6102    if !prev_chunk_trailing_whitespace_range.is_empty() {
6103        ranges.push(prev_chunk_trailing_whitespace_range);
6104    }
6105
6106    ranges
6107}