buffer.rs

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