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