buffer.rs

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