buffer.rs

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