buffer.rs

   1pub use crate::{
   2    diagnostic_set::DiagnosticSet,
   3    highlight_map::{HighlightId, HighlightMap},
   4    markdown::ParsedMarkdown,
   5    proto, Grammar, Language, LanguageRegistry,
   6};
   7use crate::{
   8    diagnostic_set::{DiagnosticEntry, DiagnosticGroup},
   9    language_settings::{language_settings, LanguageSettings},
  10    markdown::parse_markdown,
  11    outline::OutlineItem,
  12    syntax_map::{
  13        SyntaxLayer, SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures, SyntaxMapMatches,
  14        SyntaxSnapshot, ToTreeSitterPoint,
  15    },
  16    LanguageScope, Outline,
  17};
  18use anyhow::{anyhow, Context, Result};
  19pub use clock::ReplicaId;
  20use futures::channel::oneshot;
  21use gpui::{AppContext, EventEmitter, HighlightStyle, ModelContext, Task, TaskLabel};
  22use lazy_static::lazy_static;
  23use lsp::LanguageServerId;
  24use parking_lot::Mutex;
  25use similar::{ChangeTag, TextDiff};
  26use smallvec::SmallVec;
  27use smol::future::yield_now;
  28use std::{
  29    any::Any,
  30    cmp::{self, Ordering},
  31    collections::BTreeMap,
  32    ffi::OsStr,
  33    future::Future,
  34    iter::{self, Iterator, Peekable},
  35    mem,
  36    ops::{Deref, Range},
  37    path::{Path, PathBuf},
  38    str,
  39    sync::Arc,
  40    time::{Duration, Instant, SystemTime},
  41    vec,
  42};
  43use sum_tree::TreeMap;
  44use text::operation_queue::OperationQueue;
  45use text::*;
  46pub use text::{
  47    Anchor, Bias, Buffer as TextBuffer, BufferId, BufferSnapshot as TextBufferSnapshot, Edit,
  48    OffsetRangeExt, OffsetUtf16, Patch, Point, PointUtf16, Rope, Selection, SelectionGoal,
  49    Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint, ToPointUtf16,
  50    Transaction, TransactionId, Unclipped,
  51};
  52use theme::SyntaxTheme;
  53#[cfg(any(test, feature = "test-support"))]
  54use util::RandomCharIter;
  55use util::RangeExt;
  56
  57#[cfg(any(test, feature = "test-support"))]
  58pub use {tree_sitter_rust, tree_sitter_typescript};
  59
  60pub use lsp::DiagnosticSeverity;
  61
  62lazy_static! {
  63    /// A label for the background task spawned by the buffer to compute
  64    /// a diff against the contents of its file.
  65    pub static ref BUFFER_DIFF_TASK: TaskLabel = TaskLabel::new();
  66}
  67
  68/// Indicate whether a [Buffer] has permissions to edit.
  69#[derive(PartialEq, Clone, Copy, Debug)]
  70pub enum Capability {
  71    /// The buffer is a mutable replica.
  72    ReadWrite,
  73    /// The buffer is a read-only replica.
  74    ReadOnly,
  75}
  76
  77/// An in-memory representation of a source code file, including its text,
  78/// syntax trees, git status, and diagnostics.
  79pub struct Buffer {
  80    text: TextBuffer,
  81    diff_base: Option<String>,
  82    git_diff: git::diff::BufferDiff,
  83    file: Option<Arc<dyn File>>,
  84    /// The mtime of the file when this buffer was last loaded from
  85    /// or saved to disk.
  86    saved_mtime: Option<SystemTime>,
  87    /// The version vector when this buffer was last loaded from
  88    /// or saved to disk.
  89    saved_version: clock::Global,
  90    transaction_depth: usize,
  91    was_dirty_before_starting_transaction: Option<bool>,
  92    reload_task: Option<Task<Result<()>>>,
  93    language: Option<Arc<Language>>,
  94    autoindent_requests: Vec<Arc<AutoindentRequest>>,
  95    pending_autoindent: Option<Task<()>>,
  96    sync_parse_timeout: Duration,
  97    syntax_map: Mutex<SyntaxMap>,
  98    parsing_in_background: bool,
  99    parse_count: usize,
 100    diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
 101    remote_selections: TreeMap<ReplicaId, SelectionSet>,
 102    selections_update_count: usize,
 103    diagnostics_update_count: usize,
 104    diagnostics_timestamp: clock::Lamport,
 105    file_update_count: usize,
 106    git_diff_update_count: usize,
 107    completion_triggers: Vec<String>,
 108    completion_triggers_timestamp: clock::Lamport,
 109    deferred_ops: OperationQueue<Operation>,
 110    capability: Capability,
 111    has_conflict: bool,
 112}
 113
 114/// An immutable, cheaply cloneable representation of a fixed
 115/// state of a buffer.
 116pub struct BufferSnapshot {
 117    text: text::BufferSnapshot,
 118    git_diff: git::diff::BufferDiff,
 119    pub(crate) syntax: SyntaxSnapshot,
 120    file: Option<Arc<dyn File>>,
 121    diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
 122    diagnostics_update_count: usize,
 123    file_update_count: usize,
 124    git_diff_update_count: usize,
 125    remote_selections: TreeMap<ReplicaId, SelectionSet>,
 126    selections_update_count: usize,
 127    language: Option<Arc<Language>>,
 128    parse_count: usize,
 129}
 130
 131/// The kind and amount of indentation in a particular line. For now,
 132/// assumes that indentation is all the same character.
 133#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
 134pub struct IndentSize {
 135    /// The number of bytes that comprise the indentation.
 136    pub len: u32,
 137    /// The kind of whitespace used for indentation.
 138    pub kind: IndentKind,
 139}
 140
 141/// A whitespace character that's used for indentation.
 142#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
 143pub enum IndentKind {
 144    /// An ASCII space character.
 145    #[default]
 146    Space,
 147    /// An ASCII tab character.
 148    Tab,
 149}
 150
 151/// The shape of a selection cursor.
 152#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
 153pub enum CursorShape {
 154    /// A vertical bar
 155    #[default]
 156    Bar,
 157    /// A block that surrounds the following character
 158    Block,
 159    /// An underline that runs along the following character
 160    Underscore,
 161    /// A box drawn around the following character
 162    Hollow,
 163}
 164
 165#[derive(Clone, Debug)]
 166struct SelectionSet {
 167    line_mode: bool,
 168    cursor_shape: CursorShape,
 169    selections: Arc<[Selection<Anchor>]>,
 170    lamport_timestamp: clock::Lamport,
 171}
 172
 173/// A diagnostic associated with a certain range of a buffer.
 174#[derive(Clone, Debug, PartialEq, Eq)]
 175pub struct Diagnostic {
 176    /// The name of the service that produced this diagnostic.
 177    pub source: Option<String>,
 178    /// A machine-readable code that identifies this diagnostic.
 179    pub code: Option<String>,
 180    /// Whether this diagnostic is a hint, warning, or error.
 181    pub severity: DiagnosticSeverity,
 182    /// The human-readable message associated with this diagnostic.
 183    pub message: String,
 184    /// An id that identifies the group to which this diagnostic belongs.
 185    ///
 186    /// When a language server produces a diagnostic with
 187    /// one or more associated diagnostics, those diagnostics are all
 188    /// assigned a single group id.
 189    pub group_id: usize,
 190    /// Whether this diagnostic is the primary diagnostic for its group.
 191    ///
 192    /// In a given group, the primary diagnostic is the top-level diagnostic
 193    /// returned by the language server. The non-primary diagnostics are the
 194    /// associated diagnostics.
 195    pub is_primary: bool,
 196    /// Whether this diagnostic is considered to originate from an analysis of
 197    /// files on disk, as opposed to any unsaved buffer contents. This is a
 198    /// property of a given diagnostic source, and is configured for a given
 199    /// language server via the [`LspAdapter::disk_based_diagnostic_sources`](crate::LspAdapter::disk_based_diagnostic_sources) method
 200    /// for the language server.
 201    pub is_disk_based: bool,
 202    /// Whether this diagnostic marks unnecessary code.
 203    pub is_unnecessary: bool,
 204}
 205
 206/// TODO - move this into the `project` crate and make it private.
 207pub async fn prepare_completion_documentation(
 208    documentation: &lsp::Documentation,
 209    language_registry: &Arc<LanguageRegistry>,
 210    language: Option<Arc<Language>>,
 211) -> Documentation {
 212    match documentation {
 213        lsp::Documentation::String(text) => {
 214            if text.lines().count() <= 1 {
 215                Documentation::SingleLine(text.clone())
 216            } else {
 217                Documentation::MultiLinePlainText(text.clone())
 218            }
 219        }
 220
 221        lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value }) => match kind {
 222            lsp::MarkupKind::PlainText => {
 223                if value.lines().count() <= 1 {
 224                    Documentation::SingleLine(value.clone())
 225                } else {
 226                    Documentation::MultiLinePlainText(value.clone())
 227                }
 228            }
 229
 230            lsp::MarkupKind::Markdown => {
 231                let parsed = parse_markdown(value, language_registry, language).await;
 232                Documentation::MultiLineMarkdown(parsed)
 233            }
 234        },
 235    }
 236}
 237
 238/// Documentation associated with a [`Completion`].
 239#[derive(Clone, Debug)]
 240pub enum Documentation {
 241    /// There is no documentation for this completion.
 242    Undocumented,
 243    /// A single line of documentation.
 244    SingleLine(String),
 245    /// Multiple lines of plain text documentation.
 246    MultiLinePlainText(String),
 247    /// Markdown documentation.
 248    MultiLineMarkdown(ParsedMarkdown),
 249}
 250
 251/// An operation used to synchronize this buffer with its other replicas.
 252#[derive(Clone, Debug, PartialEq)]
 253pub enum Operation {
 254    /// A text operation.
 255    Buffer(text::Operation),
 256
 257    /// An update to the buffer's diagnostics.
 258    UpdateDiagnostics {
 259        /// The id of the language server that produced the new diagnostics.
 260        server_id: LanguageServerId,
 261        /// The diagnostics.
 262        diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
 263        /// The buffer's lamport timestamp.
 264        lamport_timestamp: clock::Lamport,
 265    },
 266
 267    /// An update to the most recent selections in this buffer.
 268    UpdateSelections {
 269        /// The selections.
 270        selections: Arc<[Selection<Anchor>]>,
 271        /// The buffer's lamport timestamp.
 272        lamport_timestamp: clock::Lamport,
 273        /// Whether the selections are in 'line mode'.
 274        line_mode: bool,
 275        /// The [`CursorShape`] associated with these selections.
 276        cursor_shape: CursorShape,
 277    },
 278
 279    /// An update to the characters that should trigger autocompletion
 280    /// for this buffer.
 281    UpdateCompletionTriggers {
 282        /// The characters that trigger autocompletion.
 283        triggers: Vec<String>,
 284        /// The buffer's lamport timestamp.
 285        lamport_timestamp: clock::Lamport,
 286    },
 287}
 288
 289/// An event that occurs in a buffer.
 290#[derive(Clone, Debug, PartialEq)]
 291pub enum Event {
 292    /// The buffer was changed in a way that must be
 293    /// propagated to its other replicas.
 294    Operation(Operation),
 295    /// The buffer was edited.
 296    Edited,
 297    /// The buffer's `dirty` bit changed.
 298    DirtyChanged,
 299    /// The buffer was saved.
 300    Saved,
 301    /// The buffer's file was changed on disk.
 302    FileHandleChanged,
 303    /// The buffer was reloaded.
 304    Reloaded,
 305    /// The buffer's diff_base changed.
 306    DiffBaseChanged,
 307    /// The buffer's language was changed.
 308    LanguageChanged,
 309    /// The buffer's syntax trees were updated.
 310    Reparsed,
 311    /// The buffer's diagnostics were updated.
 312    DiagnosticsUpdated,
 313    /// The buffer gained or lost editing capabilities.
 314    CapabilityChanged,
 315    /// The buffer was explicitly requested to close.
 316    Closed,
 317}
 318
 319/// The file associated with a buffer.
 320pub trait File: Send + Sync {
 321    /// Returns the [`LocalFile`] associated with this file, if the
 322    /// file is local.
 323    fn as_local(&self) -> Option<&dyn LocalFile>;
 324
 325    /// Returns whether this file is local.
 326    fn is_local(&self) -> bool {
 327        self.as_local().is_some()
 328    }
 329
 330    /// Returns the file's mtime.
 331    fn mtime(&self) -> Option<SystemTime>;
 332
 333    /// Returns the path of this file relative to the worktree's root directory.
 334    fn path(&self) -> &Arc<Path>;
 335
 336    /// Returns the path of this file relative to the worktree's parent directory (this means it
 337    /// includes the name of the worktree's root folder).
 338    fn full_path(&self, cx: &AppContext) -> PathBuf;
 339
 340    /// Returns the last component of this handle's absolute path. If this handle refers to the root
 341    /// of its worktree, then this method will return the name of the worktree itself.
 342    fn file_name<'a>(&'a self, cx: &'a AppContext) -> &'a OsStr;
 343
 344    /// Returns the id of the worktree to which this file belongs.
 345    ///
 346    /// This is needed for looking up project-specific settings.
 347    fn worktree_id(&self) -> usize;
 348
 349    /// Returns whether the file has been deleted.
 350    fn is_deleted(&self) -> bool;
 351
 352    /// Returns whether the file existed on disk at one point
 353    fn is_created(&self) -> bool {
 354        self.mtime().is_some()
 355    }
 356
 357    /// Converts this file into an [`Any`] trait object.
 358    fn as_any(&self) -> &dyn Any;
 359
 360    /// Converts this file into a protobuf message.
 361    fn to_proto(&self) -> rpc::proto::File;
 362
 363    /// Return whether Zed considers this to be a private file.
 364    fn is_private(&self) -> bool;
 365}
 366
 367/// The file associated with a buffer, in the case where the file is on the local disk.
 368pub trait LocalFile: File {
 369    /// Returns the absolute path of this file.
 370    fn abs_path(&self, cx: &AppContext) -> PathBuf;
 371
 372    /// Loads the file's contents from disk.
 373    fn load(&self, cx: &AppContext) -> Task<Result<String>>;
 374
 375    /// Called when the buffer is reloaded from disk.
 376    fn buffer_reloaded(
 377        &self,
 378        buffer_id: BufferId,
 379        version: &clock::Global,
 380        line_ending: LineEnding,
 381        mtime: Option<SystemTime>,
 382        cx: &mut AppContext,
 383    );
 384
 385    /// Returns true if the file should not be shared with collaborators.
 386    fn is_private(&self, _: &AppContext) -> bool {
 387        false
 388    }
 389}
 390
 391/// The auto-indent behavior associated with an editing operation.
 392/// For some editing operations, each affected line of text has its
 393/// indentation recomputed. For other operations, the entire block
 394/// of edited text is adjusted uniformly.
 395#[derive(Clone, Debug)]
 396pub enum AutoindentMode {
 397    /// Indent each line of inserted text.
 398    EachLine,
 399    /// Apply the same indentation adjustment to all of the lines
 400    /// in a given insertion.
 401    Block {
 402        /// The original indentation level of the first line of each
 403        /// insertion, if it has been copied.
 404        original_indent_columns: Vec<u32>,
 405    },
 406}
 407
 408#[derive(Clone)]
 409struct AutoindentRequest {
 410    before_edit: BufferSnapshot,
 411    entries: Vec<AutoindentRequestEntry>,
 412    is_block_mode: bool,
 413}
 414
 415#[derive(Clone)]
 416struct AutoindentRequestEntry {
 417    /// A range of the buffer whose indentation should be adjusted.
 418    range: Range<Anchor>,
 419    /// Whether or not these lines should be considered brand new, for the
 420    /// purpose of auto-indent. When text is not new, its indentation will
 421    /// only be adjusted if the suggested indentation level has *changed*
 422    /// since the edit was made.
 423    first_line_is_new: bool,
 424    indent_size: IndentSize,
 425    original_indent_column: Option<u32>,
 426}
 427
 428#[derive(Debug)]
 429struct IndentSuggestion {
 430    basis_row: u32,
 431    delta: Ordering,
 432    within_error: bool,
 433}
 434
 435struct BufferChunkHighlights<'a> {
 436    captures: SyntaxMapCaptures<'a>,
 437    next_capture: Option<SyntaxMapCapture<'a>>,
 438    stack: Vec<(usize, HighlightId)>,
 439    highlight_maps: Vec<HighlightMap>,
 440}
 441
 442/// An iterator that yields chunks of a buffer's text, along with their
 443/// syntax highlights and diagnostic status.
 444pub struct BufferChunks<'a> {
 445    range: Range<usize>,
 446    chunks: text::Chunks<'a>,
 447    diagnostic_endpoints: Peekable<vec::IntoIter<DiagnosticEndpoint>>,
 448    error_depth: usize,
 449    warning_depth: usize,
 450    information_depth: usize,
 451    hint_depth: usize,
 452    unnecessary_depth: usize,
 453    highlights: Option<BufferChunkHighlights<'a>>,
 454}
 455
 456/// A chunk of a buffer's text, along with its syntax highlight and
 457/// diagnostic status.
 458#[derive(Clone, Copy, Debug, Default)]
 459pub struct Chunk<'a> {
 460    /// The text of the chunk.
 461    pub text: &'a str,
 462    /// The syntax highlighting style of the chunk.
 463    pub syntax_highlight_id: Option<HighlightId>,
 464    /// The highlight style that has been applied to this chunk in
 465    /// the editor.
 466    pub highlight_style: Option<HighlightStyle>,
 467    /// The severity of diagnostic associated with this chunk, if any.
 468    pub diagnostic_severity: Option<DiagnosticSeverity>,
 469    /// Whether this chunk of text is marked as unnecessary.
 470    pub is_unnecessary: bool,
 471    /// Whether this chunk of text was originally a tab character.
 472    pub is_tab: bool,
 473}
 474
 475/// A set of edits to a given version of a buffer, computed asynchronously.
 476pub struct Diff {
 477    pub(crate) base_version: clock::Global,
 478    line_ending: LineEnding,
 479    edits: Vec<(Range<usize>, Arc<str>)>,
 480}
 481
 482#[derive(Clone, Copy)]
 483pub(crate) struct DiagnosticEndpoint {
 484    offset: usize,
 485    is_start: bool,
 486    severity: DiagnosticSeverity,
 487    is_unnecessary: bool,
 488}
 489
 490/// A class of characters, used for characterizing a run of text.
 491#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
 492pub enum CharKind {
 493    /// Whitespace.
 494    Whitespace,
 495    /// Punctuation.
 496    Punctuation,
 497    /// Word.
 498    Word,
 499}
 500
 501impl Buffer {
 502    /// Create a new buffer with the given base text.
 503    pub fn local<T: Into<String>>(base_text: T, cx: &mut ModelContext<Self>) -> Self {
 504        Self::build(
 505            TextBuffer::new(0, cx.entity_id().as_non_zero_u64().into(), base_text.into()),
 506            None,
 507            None,
 508            Capability::ReadWrite,
 509        )
 510    }
 511
 512    /// Create a new buffer that is a replica of a remote buffer.
 513    pub fn remote(
 514        remote_id: BufferId,
 515        replica_id: ReplicaId,
 516        capability: Capability,
 517        base_text: impl Into<String>,
 518    ) -> Self {
 519        Self::build(
 520            TextBuffer::new(replica_id, remote_id, base_text.into()),
 521            None,
 522            None,
 523            capability,
 524        )
 525    }
 526
 527    /// Create a new buffer that is a replica of a remote buffer, populating its
 528    /// state from the given protobuf message.
 529    pub fn from_proto(
 530        replica_id: ReplicaId,
 531        capability: Capability,
 532        message: proto::BufferState,
 533        file: Option<Arc<dyn File>>,
 534    ) -> Result<Self> {
 535        let buffer_id = BufferId::new(message.id)
 536            .with_context(|| anyhow!("Could not deserialize buffer_id"))?;
 537        let buffer = TextBuffer::new(replica_id, buffer_id, message.base_text);
 538        let mut this = Self::build(
 539            buffer,
 540            message.diff_base.map(|text| text.into_boxed_str().into()),
 541            file,
 542            capability,
 543        );
 544        this.text.set_line_ending(proto::deserialize_line_ending(
 545            rpc::proto::LineEnding::from_i32(message.line_ending)
 546                .ok_or_else(|| anyhow!("missing line_ending"))?,
 547        ));
 548        this.saved_version = proto::deserialize_version(&message.saved_version);
 549        this.saved_mtime = message.saved_mtime.map(|time| time.into());
 550        Ok(this)
 551    }
 552
 553    /// Serialize the buffer's state to a protobuf message.
 554    pub fn to_proto(&self) -> proto::BufferState {
 555        proto::BufferState {
 556            id: self.remote_id().into(),
 557            file: self.file.as_ref().map(|f| f.to_proto()),
 558            base_text: self.base_text().to_string(),
 559            diff_base: self.diff_base.as_ref().map(|h| h.to_string()),
 560            line_ending: proto::serialize_line_ending(self.line_ending()) as i32,
 561            saved_version: proto::serialize_version(&self.saved_version),
 562            saved_mtime: self.saved_mtime.map(|time| time.into()),
 563        }
 564    }
 565
 566    /// Serialize as protobufs all of the changes to the buffer since the given version.
 567    pub fn serialize_ops(
 568        &self,
 569        since: Option<clock::Global>,
 570        cx: &AppContext,
 571    ) -> Task<Vec<proto::Operation>> {
 572        let mut operations = Vec::new();
 573        operations.extend(self.deferred_ops.iter().map(proto::serialize_operation));
 574
 575        operations.extend(self.remote_selections.iter().map(|(_, set)| {
 576            proto::serialize_operation(&Operation::UpdateSelections {
 577                selections: set.selections.clone(),
 578                lamport_timestamp: set.lamport_timestamp,
 579                line_mode: set.line_mode,
 580                cursor_shape: set.cursor_shape,
 581            })
 582        }));
 583
 584        for (server_id, diagnostics) in &self.diagnostics {
 585            operations.push(proto::serialize_operation(&Operation::UpdateDiagnostics {
 586                lamport_timestamp: self.diagnostics_timestamp,
 587                server_id: *server_id,
 588                diagnostics: diagnostics.iter().cloned().collect(),
 589            }));
 590        }
 591
 592        operations.push(proto::serialize_operation(
 593            &Operation::UpdateCompletionTriggers {
 594                triggers: self.completion_triggers.clone(),
 595                lamport_timestamp: self.completion_triggers_timestamp,
 596            },
 597        ));
 598
 599        let text_operations = self.text.operations().clone();
 600        cx.background_executor().spawn(async move {
 601            let since = since.unwrap_or_default();
 602            operations.extend(
 603                text_operations
 604                    .iter()
 605                    .filter(|(_, op)| !since.observed(op.timestamp()))
 606                    .map(|(_, op)| proto::serialize_operation(&Operation::Buffer(op.clone()))),
 607            );
 608            operations.sort_unstable_by_key(proto::lamport_timestamp_for_operation);
 609            operations
 610        })
 611    }
 612
 613    /// Assign a language to the buffer, returning the buffer.
 614    pub fn with_language(mut self, language: Arc<Language>, cx: &mut ModelContext<Self>) -> Self {
 615        self.set_language(Some(language), cx);
 616        self
 617    }
 618
 619    /// Returns the [Capability] of this buffer.
 620    pub fn capability(&self) -> Capability {
 621        self.capability
 622    }
 623
 624    /// Whether this buffer can only be read.
 625    pub fn read_only(&self) -> bool {
 626        self.capability == Capability::ReadOnly
 627    }
 628
 629    /// Builds a [Buffer] with the given underlying [TextBuffer], diff base, [File] and [Capability].
 630    pub fn build(
 631        buffer: TextBuffer,
 632        diff_base: Option<String>,
 633        file: Option<Arc<dyn File>>,
 634        capability: Capability,
 635    ) -> Self {
 636        let saved_mtime = file.as_ref().and_then(|file| file.mtime());
 637
 638        Self {
 639            saved_mtime,
 640            saved_version: buffer.version(),
 641            reload_task: None,
 642            transaction_depth: 0,
 643            was_dirty_before_starting_transaction: None,
 644            text: buffer,
 645            diff_base,
 646            git_diff: git::diff::BufferDiff::new(),
 647            file,
 648            capability,
 649            syntax_map: Mutex::new(SyntaxMap::new()),
 650            parsing_in_background: false,
 651            parse_count: 0,
 652            sync_parse_timeout: Duration::from_millis(1),
 653            autoindent_requests: Default::default(),
 654            pending_autoindent: Default::default(),
 655            language: None,
 656            remote_selections: Default::default(),
 657            selections_update_count: 0,
 658            diagnostics: Default::default(),
 659            diagnostics_update_count: 0,
 660            diagnostics_timestamp: Default::default(),
 661            file_update_count: 0,
 662            git_diff_update_count: 0,
 663            completion_triggers: Default::default(),
 664            completion_triggers_timestamp: Default::default(),
 665            deferred_ops: OperationQueue::new(),
 666            has_conflict: false,
 667        }
 668    }
 669
 670    /// Retrieve a snapshot of the buffer's current state. This is computationally
 671    /// cheap, and allows reading from the buffer on a background thread.
 672    pub fn snapshot(&self) -> BufferSnapshot {
 673        let text = self.text.snapshot();
 674        let mut syntax_map = self.syntax_map.lock();
 675        syntax_map.interpolate(&text);
 676        let syntax = syntax_map.snapshot();
 677
 678        BufferSnapshot {
 679            text,
 680            syntax,
 681            git_diff: self.git_diff.clone(),
 682            file: self.file.clone(),
 683            remote_selections: self.remote_selections.clone(),
 684            diagnostics: self.diagnostics.clone(),
 685            diagnostics_update_count: self.diagnostics_update_count,
 686            file_update_count: self.file_update_count,
 687            git_diff_update_count: self.git_diff_update_count,
 688            language: self.language.clone(),
 689            parse_count: self.parse_count,
 690            selections_update_count: self.selections_update_count,
 691        }
 692    }
 693
 694    #[cfg(test)]
 695    pub(crate) fn as_text_snapshot(&self) -> &text::BufferSnapshot {
 696        &self.text
 697    }
 698
 699    /// Retrieve a snapshot of the buffer's raw text, without any
 700    /// language-related state like the syntax tree or diagnostics.
 701    pub fn text_snapshot(&self) -> text::BufferSnapshot {
 702        self.text.snapshot()
 703    }
 704
 705    /// The file associated with the buffer, if any.
 706    pub fn file(&self) -> Option<&Arc<dyn File>> {
 707        self.file.as_ref()
 708    }
 709
 710    /// The version of the buffer that was last saved or reloaded from disk.
 711    pub fn saved_version(&self) -> &clock::Global {
 712        &self.saved_version
 713    }
 714
 715    /// The mtime of the buffer's file when the buffer was last saved or reloaded from disk.
 716    pub fn saved_mtime(&self) -> Option<SystemTime> {
 717        self.saved_mtime
 718    }
 719
 720    /// Assign a language to the buffer.
 721    pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
 722        self.parse_count += 1;
 723        self.syntax_map.lock().clear();
 724        self.language = language;
 725        self.reparse(cx);
 726        cx.emit(Event::LanguageChanged);
 727    }
 728
 729    /// Assign a language registry to the buffer. This allows the buffer to retrieve
 730    /// other languages if parts of the buffer are written in different languages.
 731    pub fn set_language_registry(&mut self, language_registry: Arc<LanguageRegistry>) {
 732        self.syntax_map
 733            .lock()
 734            .set_language_registry(language_registry);
 735    }
 736
 737    /// Assign the buffer a new [Capability].
 738    pub fn set_capability(&mut self, capability: Capability, cx: &mut ModelContext<Self>) {
 739        self.capability = capability;
 740        cx.emit(Event::CapabilityChanged)
 741    }
 742
 743    /// This method is called to signal that the buffer has been saved.
 744    pub fn did_save(
 745        &mut self,
 746        version: clock::Global,
 747        mtime: Option<SystemTime>,
 748        cx: &mut ModelContext<Self>,
 749    ) {
 750        self.saved_version = version;
 751        self.has_conflict = false;
 752        self.saved_mtime = mtime;
 753        cx.emit(Event::Saved);
 754        cx.notify();
 755    }
 756
 757    /// Reloads the contents of the buffer from disk.
 758    pub fn reload(
 759        &mut self,
 760        cx: &mut ModelContext<Self>,
 761    ) -> oneshot::Receiver<Option<Transaction>> {
 762        let (tx, rx) = futures::channel::oneshot::channel();
 763        let prev_version = self.text.version();
 764        self.reload_task = Some(cx.spawn(|this, mut cx| async move {
 765            let Some((new_mtime, new_text)) = this.update(&mut cx, |this, cx| {
 766                let file = this.file.as_ref()?.as_local()?;
 767                Some((file.mtime(), file.load(cx)))
 768            })?
 769            else {
 770                return Ok(());
 771            };
 772
 773            let new_text = new_text.await?;
 774            let diff = this
 775                .update(&mut cx, |this, cx| this.diff(new_text.clone(), cx))?
 776                .await;
 777            this.update(&mut cx, |this, cx| {
 778                if this.version() == diff.base_version {
 779                    this.finalize_last_transaction();
 780                    this.apply_diff(diff, cx);
 781                    tx.send(this.finalize_last_transaction().cloned()).ok();
 782                    this.has_conflict = false;
 783                    this.did_reload(this.version(), this.line_ending(), new_mtime, cx);
 784                } else {
 785                    if !diff.edits.is_empty()
 786                        || this
 787                            .edits_since::<usize>(&diff.base_version)
 788                            .next()
 789                            .is_some()
 790                    {
 791                        this.has_conflict = true;
 792                    }
 793
 794                    this.did_reload(prev_version, this.line_ending(), this.saved_mtime, cx);
 795                }
 796
 797                this.reload_task.take();
 798            })
 799        }));
 800        rx
 801    }
 802
 803    /// This method is called to signal that the buffer has been reloaded.
 804    pub fn did_reload(
 805        &mut self,
 806        version: clock::Global,
 807        line_ending: LineEnding,
 808        mtime: Option<SystemTime>,
 809        cx: &mut ModelContext<Self>,
 810    ) {
 811        self.saved_version = version;
 812        self.text.set_line_ending(line_ending);
 813        self.saved_mtime = mtime;
 814        if let Some(file) = self.file.as_ref().and_then(|f| f.as_local()) {
 815            file.buffer_reloaded(
 816                self.remote_id(),
 817                &self.saved_version,
 818                self.line_ending(),
 819                self.saved_mtime,
 820                cx,
 821            );
 822        }
 823        cx.emit(Event::Reloaded);
 824        cx.notify();
 825    }
 826
 827    /// Updates the [File] backing this buffer. This should be called when
 828    /// the file has changed or has been deleted.
 829    pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut ModelContext<Self>) {
 830        let mut file_changed = false;
 831
 832        if let Some(old_file) = self.file.as_ref() {
 833            if new_file.path() != old_file.path() {
 834                file_changed = true;
 835            }
 836
 837            if new_file.is_deleted() {
 838                if !old_file.is_deleted() {
 839                    file_changed = true;
 840                    if !self.is_dirty() {
 841                        cx.emit(Event::DirtyChanged);
 842                    }
 843                }
 844            } else {
 845                let new_mtime = new_file.mtime();
 846                if new_mtime != old_file.mtime() {
 847                    file_changed = true;
 848
 849                    if !self.is_dirty() {
 850                        self.reload(cx).close();
 851                    }
 852                }
 853            }
 854        } else {
 855            file_changed = true;
 856        };
 857
 858        self.file = Some(new_file);
 859        if file_changed {
 860            self.file_update_count += 1;
 861            cx.emit(Event::FileHandleChanged);
 862            cx.notify();
 863        }
 864    }
 865
 866    /// Returns the current diff base, see [Buffer::set_diff_base].
 867    pub fn diff_base(&self) -> Option<&str> {
 868        self.diff_base.as_deref()
 869    }
 870
 871    /// Sets the text that will be used to compute a Git diff
 872    /// against the buffer text.
 873    pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
 874        self.diff_base = diff_base;
 875        if let Some(recalc_task) = self.git_diff_recalc(cx) {
 876            cx.spawn(|buffer, mut cx| async move {
 877                recalc_task.await;
 878                buffer
 879                    .update(&mut cx, |_, cx| {
 880                        cx.emit(Event::DiffBaseChanged);
 881                    })
 882                    .ok();
 883            })
 884            .detach();
 885        }
 886    }
 887
 888    /// Recomputes the Git diff status.
 889    pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<()>> {
 890        let diff_base = self.diff_base.clone()?; // TODO: Make this an Arc
 891        let snapshot = self.snapshot();
 892
 893        let mut diff = self.git_diff.clone();
 894        let diff = cx.background_executor().spawn(async move {
 895            diff.update(&diff_base, &snapshot).await;
 896            diff
 897        });
 898
 899        Some(cx.spawn(|this, mut cx| async move {
 900            let buffer_diff = diff.await;
 901            this.update(&mut cx, |this, _| {
 902                this.git_diff = buffer_diff;
 903                this.git_diff_update_count += 1;
 904            })
 905            .ok();
 906        }))
 907    }
 908
 909    /// Returns the primary [Language] assigned to this [Buffer].
 910    pub fn language(&self) -> Option<&Arc<Language>> {
 911        self.language.as_ref()
 912    }
 913
 914    /// Returns the [Language] at the given location.
 915    pub fn language_at<D: ToOffset>(&self, position: D) -> Option<Arc<Language>> {
 916        let offset = position.to_offset(self);
 917        self.syntax_map
 918            .lock()
 919            .layers_for_range(offset..offset, &self.text)
 920            .last()
 921            .map(|info| info.language.clone())
 922            .or_else(|| self.language.clone())
 923    }
 924
 925    /// The number of times the buffer was parsed.
 926    pub fn parse_count(&self) -> usize {
 927        self.parse_count
 928    }
 929
 930    /// The number of times selections were updated.
 931    pub fn selections_update_count(&self) -> usize {
 932        self.selections_update_count
 933    }
 934
 935    /// The number of times diagnostics were updated.
 936    pub fn diagnostics_update_count(&self) -> usize {
 937        self.diagnostics_update_count
 938    }
 939
 940    /// The number of times the underlying file was updated.
 941    pub fn file_update_count(&self) -> usize {
 942        self.file_update_count
 943    }
 944
 945    /// The number of times the git diff status was updated.
 946    pub fn git_diff_update_count(&self) -> usize {
 947        self.git_diff_update_count
 948    }
 949
 950    /// Whether the buffer is being parsed in the background.
 951    #[cfg(any(test, feature = "test-support"))]
 952    pub fn is_parsing(&self) -> bool {
 953        self.parsing_in_background
 954    }
 955
 956    /// Indicates whether the buffer contains any regions that may be
 957    /// written in a language that hasn't been loaded yet.
 958    pub fn contains_unknown_injections(&self) -> bool {
 959        self.syntax_map.lock().contains_unknown_injections()
 960    }
 961
 962    #[cfg(test)]
 963    pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
 964        self.sync_parse_timeout = timeout;
 965    }
 966
 967    /// Called after an edit to synchronize the buffer's main parse tree with
 968    /// the buffer's new underlying state.
 969    ///
 970    /// Locks the syntax map and interpolates the edits since the last reparse
 971    /// into the foreground syntax tree.
 972    ///
 973    /// Then takes a stable snapshot of the syntax map before unlocking it.
 974    /// The snapshot with the interpolated edits is sent to a background thread,
 975    /// where we ask Tree-sitter to perform an incremental parse.
 976    ///
 977    /// Meanwhile, in the foreground, we block the main thread for up to 1ms
 978    /// waiting on the parse to complete. As soon as it completes, we proceed
 979    /// synchronously, unless a 1ms timeout elapses.
 980    ///
 981    /// If we time out waiting on the parse, we spawn a second task waiting
 982    /// until the parse does complete and return with the interpolated tree still
 983    /// in the foreground. When the background parse completes, call back into
 984    /// the main thread and assign the foreground parse state.
 985    ///
 986    /// If the buffer or grammar changed since the start of the background parse,
 987    /// initiate an additional reparse recursively. To avoid concurrent parses
 988    /// for the same buffer, we only initiate a new parse if we are not already
 989    /// parsing in the background.
 990    pub fn reparse(&mut self, cx: &mut ModelContext<Self>) {
 991        if self.parsing_in_background {
 992            return;
 993        }
 994        let language = if let Some(language) = self.language.clone() {
 995            language
 996        } else {
 997            return;
 998        };
 999
1000        let text = self.text_snapshot();
1001        let parsed_version = self.version();
1002
1003        let mut syntax_map = self.syntax_map.lock();
1004        syntax_map.interpolate(&text);
1005        let language_registry = syntax_map.language_registry();
1006        let mut syntax_snapshot = syntax_map.snapshot();
1007        drop(syntax_map);
1008
1009        let parse_task = cx.background_executor().spawn({
1010            let language = language.clone();
1011            let language_registry = language_registry.clone();
1012            async move {
1013                syntax_snapshot.reparse(&text, language_registry, language);
1014                syntax_snapshot
1015            }
1016        });
1017
1018        match cx
1019            .background_executor()
1020            .block_with_timeout(self.sync_parse_timeout, parse_task)
1021        {
1022            Ok(new_syntax_snapshot) => {
1023                self.did_finish_parsing(new_syntax_snapshot, cx);
1024                return;
1025            }
1026            Err(parse_task) => {
1027                self.parsing_in_background = true;
1028                cx.spawn(move |this, mut cx| async move {
1029                    let new_syntax_map = parse_task.await;
1030                    this.update(&mut cx, move |this, cx| {
1031                        let grammar_changed =
1032                            this.language.as_ref().map_or(true, |current_language| {
1033                                !Arc::ptr_eq(&language, current_language)
1034                            });
1035                        let language_registry_changed = new_syntax_map
1036                            .contains_unknown_injections()
1037                            && language_registry.map_or(false, |registry| {
1038                                registry.version() != new_syntax_map.language_registry_version()
1039                            });
1040                        let parse_again = language_registry_changed
1041                            || grammar_changed
1042                            || this.version.changed_since(&parsed_version);
1043                        this.did_finish_parsing(new_syntax_map, cx);
1044                        this.parsing_in_background = false;
1045                        if parse_again {
1046                            this.reparse(cx);
1047                        }
1048                    })
1049                    .ok();
1050                })
1051                .detach();
1052            }
1053        }
1054    }
1055
1056    fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut ModelContext<Self>) {
1057        self.parse_count += 1;
1058        self.syntax_map.lock().did_parse(syntax_snapshot);
1059        self.request_autoindent(cx);
1060        cx.emit(Event::Reparsed);
1061        cx.notify();
1062    }
1063
1064    /// Assign to the buffer a set of diagnostics created by a given language server.
1065    pub fn update_diagnostics(
1066        &mut self,
1067        server_id: LanguageServerId,
1068        diagnostics: DiagnosticSet,
1069        cx: &mut ModelContext<Self>,
1070    ) {
1071        let lamport_timestamp = self.text.lamport_clock.tick();
1072        let op = Operation::UpdateDiagnostics {
1073            server_id,
1074            diagnostics: diagnostics.iter().cloned().collect(),
1075            lamport_timestamp,
1076        };
1077        self.apply_diagnostic_update(server_id, diagnostics, lamport_timestamp, cx);
1078        self.send_operation(op, cx);
1079    }
1080
1081    fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
1082        if let Some(indent_sizes) = self.compute_autoindents() {
1083            let indent_sizes = cx.background_executor().spawn(indent_sizes);
1084            match cx
1085                .background_executor()
1086                .block_with_timeout(Duration::from_micros(500), indent_sizes)
1087            {
1088                Ok(indent_sizes) => self.apply_autoindents(indent_sizes, cx),
1089                Err(indent_sizes) => {
1090                    self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
1091                        let indent_sizes = indent_sizes.await;
1092                        this.update(&mut cx, |this, cx| {
1093                            this.apply_autoindents(indent_sizes, cx);
1094                        })
1095                        .ok();
1096                    }));
1097                }
1098            }
1099        } else {
1100            self.autoindent_requests.clear();
1101        }
1102    }
1103
1104    fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>>> {
1105        let max_rows_between_yields = 100;
1106        let snapshot = self.snapshot();
1107        if snapshot.syntax.is_empty() || self.autoindent_requests.is_empty() {
1108            return None;
1109        }
1110
1111        let autoindent_requests = self.autoindent_requests.clone();
1112        Some(async move {
1113            let mut indent_sizes = BTreeMap::new();
1114            for request in autoindent_requests {
1115                // Resolve each edited range to its row in the current buffer and in the
1116                // buffer before this batch of edits.
1117                let mut row_ranges = Vec::new();
1118                let mut old_to_new_rows = BTreeMap::new();
1119                let mut language_indent_sizes_by_new_row = Vec::new();
1120                for entry in &request.entries {
1121                    let position = entry.range.start;
1122                    let new_row = position.to_point(&snapshot).row;
1123                    let new_end_row = entry.range.end.to_point(&snapshot).row + 1;
1124                    language_indent_sizes_by_new_row.push((new_row, entry.indent_size));
1125
1126                    if !entry.first_line_is_new {
1127                        let old_row = position.to_point(&request.before_edit).row;
1128                        old_to_new_rows.insert(old_row, new_row);
1129                    }
1130                    row_ranges.push((new_row..new_end_row, entry.original_indent_column));
1131                }
1132
1133                // Build a map containing the suggested indentation for each of the edited lines
1134                // with respect to the state of the buffer before these edits. This map is keyed
1135                // by the rows for these lines in the current state of the buffer.
1136                let mut old_suggestions = BTreeMap::<u32, (IndentSize, bool)>::default();
1137                let old_edited_ranges =
1138                    contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
1139                let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
1140                let mut language_indent_size = IndentSize::default();
1141                for old_edited_range in old_edited_ranges {
1142                    let suggestions = request
1143                        .before_edit
1144                        .suggest_autoindents(old_edited_range.clone())
1145                        .into_iter()
1146                        .flatten();
1147                    for (old_row, suggestion) in old_edited_range.zip(suggestions) {
1148                        if let Some(suggestion) = suggestion {
1149                            let new_row = *old_to_new_rows.get(&old_row).unwrap();
1150
1151                            // Find the indent size based on the language for this row.
1152                            while let Some((row, size)) = language_indent_sizes.peek() {
1153                                if *row > new_row {
1154                                    break;
1155                                }
1156                                language_indent_size = *size;
1157                                language_indent_sizes.next();
1158                            }
1159
1160                            let suggested_indent = old_to_new_rows
1161                                .get(&suggestion.basis_row)
1162                                .and_then(|from_row| {
1163                                    Some(old_suggestions.get(from_row).copied()?.0)
1164                                })
1165                                .unwrap_or_else(|| {
1166                                    request
1167                                        .before_edit
1168                                        .indent_size_for_line(suggestion.basis_row)
1169                                })
1170                                .with_delta(suggestion.delta, language_indent_size);
1171                            old_suggestions
1172                                .insert(new_row, (suggested_indent, suggestion.within_error));
1173                        }
1174                    }
1175                    yield_now().await;
1176                }
1177
1178                // In block mode, only compute indentation suggestions for the first line
1179                // of each insertion. Otherwise, compute suggestions for every inserted line.
1180                let new_edited_row_ranges = contiguous_ranges(
1181                    row_ranges.iter().flat_map(|(range, _)| {
1182                        if request.is_block_mode {
1183                            range.start..range.start + 1
1184                        } else {
1185                            range.clone()
1186                        }
1187                    }),
1188                    max_rows_between_yields,
1189                );
1190
1191                // Compute new suggestions for each line, but only include them in the result
1192                // if they differ from the old suggestion for that line.
1193                let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
1194                let mut language_indent_size = IndentSize::default();
1195                for new_edited_row_range in new_edited_row_ranges {
1196                    let suggestions = snapshot
1197                        .suggest_autoindents(new_edited_row_range.clone())
1198                        .into_iter()
1199                        .flatten();
1200                    for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
1201                        if let Some(suggestion) = suggestion {
1202                            // Find the indent size based on the language for this row.
1203                            while let Some((row, size)) = language_indent_sizes.peek() {
1204                                if *row > new_row {
1205                                    break;
1206                                }
1207                                language_indent_size = *size;
1208                                language_indent_sizes.next();
1209                            }
1210
1211                            let suggested_indent = indent_sizes
1212                                .get(&suggestion.basis_row)
1213                                .copied()
1214                                .unwrap_or_else(|| {
1215                                    snapshot.indent_size_for_line(suggestion.basis_row)
1216                                })
1217                                .with_delta(suggestion.delta, language_indent_size);
1218                            if old_suggestions.get(&new_row).map_or(
1219                                true,
1220                                |(old_indentation, was_within_error)| {
1221                                    suggested_indent != *old_indentation
1222                                        && (!suggestion.within_error || *was_within_error)
1223                                },
1224                            ) {
1225                                indent_sizes.insert(new_row, suggested_indent);
1226                            }
1227                        }
1228                    }
1229                    yield_now().await;
1230                }
1231
1232                // For each block of inserted text, adjust the indentation of the remaining
1233                // lines of the block by the same amount as the first line was adjusted.
1234                if request.is_block_mode {
1235                    for (row_range, original_indent_column) in
1236                        row_ranges
1237                            .into_iter()
1238                            .filter_map(|(range, original_indent_column)| {
1239                                if range.len() > 1 {
1240                                    Some((range, original_indent_column?))
1241                                } else {
1242                                    None
1243                                }
1244                            })
1245                    {
1246                        let new_indent = indent_sizes
1247                            .get(&row_range.start)
1248                            .copied()
1249                            .unwrap_or_else(|| snapshot.indent_size_for_line(row_range.start));
1250                        let delta = new_indent.len as i64 - original_indent_column as i64;
1251                        if delta != 0 {
1252                            for row in row_range.skip(1) {
1253                                indent_sizes.entry(row).or_insert_with(|| {
1254                                    let mut size = snapshot.indent_size_for_line(row);
1255                                    if size.kind == new_indent.kind {
1256                                        match delta.cmp(&0) {
1257                                            Ordering::Greater => size.len += delta as u32,
1258                                            Ordering::Less => {
1259                                                size.len = size.len.saturating_sub(-delta as u32)
1260                                            }
1261                                            Ordering::Equal => {}
1262                                        }
1263                                    }
1264                                    size
1265                                });
1266                            }
1267                        }
1268                    }
1269                }
1270            }
1271
1272            indent_sizes
1273        })
1274    }
1275
1276    fn apply_autoindents(
1277        &mut self,
1278        indent_sizes: BTreeMap<u32, IndentSize>,
1279        cx: &mut ModelContext<Self>,
1280    ) {
1281        self.autoindent_requests.clear();
1282
1283        let edits: Vec<_> = indent_sizes
1284            .into_iter()
1285            .filter_map(|(row, indent_size)| {
1286                let current_size = indent_size_for_line(self, row);
1287                Self::edit_for_indent_size_adjustment(row, current_size, indent_size)
1288            })
1289            .collect();
1290
1291        self.edit(edits, None, cx);
1292    }
1293
1294    /// Create a minimal edit that will cause the given row to be indented
1295    /// with the given size. After applying this edit, the length of the line
1296    /// will always be at least `new_size.len`.
1297    pub fn edit_for_indent_size_adjustment(
1298        row: u32,
1299        current_size: IndentSize,
1300        new_size: IndentSize,
1301    ) -> Option<(Range<Point>, String)> {
1302        if new_size.kind == current_size.kind {
1303            match new_size.len.cmp(&current_size.len) {
1304                Ordering::Greater => {
1305                    let point = Point::new(row, 0);
1306                    Some((
1307                        point..point,
1308                        iter::repeat(new_size.char())
1309                            .take((new_size.len - current_size.len) as usize)
1310                            .collect::<String>(),
1311                    ))
1312                }
1313
1314                Ordering::Less => Some((
1315                    Point::new(row, 0)..Point::new(row, current_size.len - new_size.len),
1316                    String::new(),
1317                )),
1318
1319                Ordering::Equal => None,
1320            }
1321        } else {
1322            Some((
1323                Point::new(row, 0)..Point::new(row, current_size.len),
1324                iter::repeat(new_size.char())
1325                    .take(new_size.len as usize)
1326                    .collect::<String>(),
1327            ))
1328        }
1329    }
1330
1331    /// Spawns a background task that asynchronously computes a `Diff` between the buffer's text
1332    /// and the given new text.
1333    pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task<Diff> {
1334        let old_text = self.as_rope().clone();
1335        let base_version = self.version();
1336        cx.background_executor()
1337            .spawn_labeled(*BUFFER_DIFF_TASK, async move {
1338                let old_text = old_text.to_string();
1339                let line_ending = LineEnding::detect(&new_text);
1340                LineEnding::normalize(&mut new_text);
1341
1342                let diff = TextDiff::from_chars(old_text.as_str(), new_text.as_str());
1343                let empty: Arc<str> = "".into();
1344
1345                let mut edits = Vec::new();
1346                let mut old_offset = 0;
1347                let mut new_offset = 0;
1348                let mut last_edit: Option<(Range<usize>, Range<usize>)> = None;
1349                for change in diff.iter_all_changes().map(Some).chain([None]) {
1350                    if let Some(change) = &change {
1351                        let len = change.value().len();
1352                        match change.tag() {
1353                            ChangeTag::Equal => {
1354                                old_offset += len;
1355                                new_offset += len;
1356                            }
1357                            ChangeTag::Delete => {
1358                                let old_end_offset = old_offset + len;
1359                                if let Some((last_old_range, _)) = &mut last_edit {
1360                                    last_old_range.end = old_end_offset;
1361                                } else {
1362                                    last_edit =
1363                                        Some((old_offset..old_end_offset, new_offset..new_offset));
1364                                }
1365                                old_offset = old_end_offset;
1366                            }
1367                            ChangeTag::Insert => {
1368                                let new_end_offset = new_offset + len;
1369                                if let Some((_, last_new_range)) = &mut last_edit {
1370                                    last_new_range.end = new_end_offset;
1371                                } else {
1372                                    last_edit =
1373                                        Some((old_offset..old_offset, new_offset..new_end_offset));
1374                                }
1375                                new_offset = new_end_offset;
1376                            }
1377                        }
1378                    }
1379
1380                    if let Some((old_range, new_range)) = &last_edit {
1381                        if old_offset > old_range.end
1382                            || new_offset > new_range.end
1383                            || change.is_none()
1384                        {
1385                            let text = if new_range.is_empty() {
1386                                empty.clone()
1387                            } else {
1388                                new_text[new_range.clone()].into()
1389                            };
1390                            edits.push((old_range.clone(), text));
1391                            last_edit.take();
1392                        }
1393                    }
1394                }
1395
1396                Diff {
1397                    base_version,
1398                    line_ending,
1399                    edits,
1400                }
1401            })
1402    }
1403
1404    /// Spawns a background task that searches the buffer for any whitespace
1405    /// at the ends of a lines, and returns a `Diff` that removes that whitespace.
1406    pub fn remove_trailing_whitespace(&self, cx: &AppContext) -> Task<Diff> {
1407        let old_text = self.as_rope().clone();
1408        let line_ending = self.line_ending();
1409        let base_version = self.version();
1410        cx.background_executor().spawn(async move {
1411            let ranges = trailing_whitespace_ranges(&old_text);
1412            let empty = Arc::<str>::from("");
1413            Diff {
1414                base_version,
1415                line_ending,
1416                edits: ranges
1417                    .into_iter()
1418                    .map(|range| (range, empty.clone()))
1419                    .collect(),
1420            }
1421        })
1422    }
1423
1424    /// Ensures that the buffer ends with a single newline character, and
1425    /// no other whitespace.
1426    pub fn ensure_final_newline(&mut self, cx: &mut ModelContext<Self>) {
1427        let len = self.len();
1428        let mut offset = len;
1429        for chunk in self.as_rope().reversed_chunks_in_range(0..len) {
1430            let non_whitespace_len = chunk
1431                .trim_end_matches(|c: char| c.is_ascii_whitespace())
1432                .len();
1433            offset -= chunk.len();
1434            offset += non_whitespace_len;
1435            if non_whitespace_len != 0 {
1436                if offset == len - 1 && chunk.get(non_whitespace_len..) == Some("\n") {
1437                    return;
1438                }
1439                break;
1440            }
1441        }
1442        self.edit([(offset..len, "\n")], None, cx);
1443    }
1444
1445    /// Applies a diff to the buffer. If the buffer has changed since the given diff was
1446    /// calculated, then adjust the diff to account for those changes, and discard any
1447    /// parts of the diff that conflict with those changes.
1448    pub fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1449        // Check for any edits to the buffer that have occurred since this diff
1450        // was computed.
1451        let snapshot = self.snapshot();
1452        let mut edits_since = snapshot.edits_since::<usize>(&diff.base_version).peekable();
1453        let mut delta = 0;
1454        let adjusted_edits = diff.edits.into_iter().filter_map(|(range, new_text)| {
1455            while let Some(edit_since) = edits_since.peek() {
1456                // If the edit occurs after a diff hunk, then it does not
1457                // affect that hunk.
1458                if edit_since.old.start > range.end {
1459                    break;
1460                }
1461                // If the edit precedes the diff hunk, then adjust the hunk
1462                // to reflect the edit.
1463                else if edit_since.old.end < range.start {
1464                    delta += edit_since.new_len() as i64 - edit_since.old_len() as i64;
1465                    edits_since.next();
1466                }
1467                // If the edit intersects a diff hunk, then discard that hunk.
1468                else {
1469                    return None;
1470                }
1471            }
1472
1473            let start = (range.start as i64 + delta) as usize;
1474            let end = (range.end as i64 + delta) as usize;
1475            Some((start..end, new_text))
1476        });
1477
1478        self.start_transaction();
1479        self.text.set_line_ending(diff.line_ending);
1480        self.edit(adjusted_edits, None, cx);
1481        self.end_transaction(cx)
1482    }
1483
1484    fn changed_since_saved_version(&self) -> bool {
1485        self.edits_since::<usize>(&self.saved_version)
1486            .next()
1487            .is_some()
1488    }
1489    /// Checks if the buffer has unsaved changes.
1490    pub fn is_dirty(&self) -> bool {
1491        (self.has_conflict || self.changed_since_saved_version())
1492            || self
1493                .file
1494                .as_ref()
1495                .map_or(false, |file| file.is_deleted() || !file.is_created())
1496    }
1497
1498    /// Checks if the buffer and its file have both changed since the buffer
1499    /// was last saved or reloaded.
1500    pub fn has_conflict(&self) -> bool {
1501        (self.has_conflict || self.changed_since_saved_version())
1502            && self
1503                .file
1504                .as_ref()
1505                .map_or(false, |file| file.mtime() > self.saved_mtime)
1506    }
1507
1508    /// Gets a [`Subscription`] that tracks all of the changes to the buffer's text.
1509    pub fn subscribe(&mut self) -> Subscription {
1510        self.text.subscribe()
1511    }
1512
1513    /// Starts a transaction, if one is not already in-progress. When undoing or
1514    /// redoing edits, all of the edits performed within a transaction are undone
1515    /// or redone together.
1516    pub fn start_transaction(&mut self) -> Option<TransactionId> {
1517        self.start_transaction_at(Instant::now())
1518    }
1519
1520    /// Starts a transaction, providing the current time. Subsequent transactions
1521    /// that occur within a short period of time will be grouped together. This
1522    /// is controlled by the buffer's undo grouping duration.
1523    pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
1524        self.transaction_depth += 1;
1525        if self.was_dirty_before_starting_transaction.is_none() {
1526            self.was_dirty_before_starting_transaction = Some(self.is_dirty());
1527        }
1528        self.text.start_transaction_at(now)
1529    }
1530
1531    /// Terminates the current transaction, if this is the outermost transaction.
1532    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1533        self.end_transaction_at(Instant::now(), cx)
1534    }
1535
1536    /// Terminates the current transaction, providing the current time. Subsequent transactions
1537    /// that occur within a short period of time will be grouped together. This
1538    /// is controlled by the buffer's undo grouping duration.
1539    pub fn end_transaction_at(
1540        &mut self,
1541        now: Instant,
1542        cx: &mut ModelContext<Self>,
1543    ) -> Option<TransactionId> {
1544        assert!(self.transaction_depth > 0);
1545        self.transaction_depth -= 1;
1546        let was_dirty = if self.transaction_depth == 0 {
1547            self.was_dirty_before_starting_transaction.take().unwrap()
1548        } else {
1549            false
1550        };
1551        if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
1552            self.did_edit(&start_version, was_dirty, cx);
1553            Some(transaction_id)
1554        } else {
1555            None
1556        }
1557    }
1558
1559    /// Manually add a transaction to the buffer's undo history.
1560    pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
1561        self.text.push_transaction(transaction, now);
1562    }
1563
1564    /// Prevent the last transaction from being grouped with any subsequent transactions,
1565    /// even if they occur with the buffer's undo grouping duration.
1566    pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
1567        self.text.finalize_last_transaction()
1568    }
1569
1570    /// Manually group all changes since a given transaction.
1571    pub fn group_until_transaction(&mut self, transaction_id: TransactionId) {
1572        self.text.group_until_transaction(transaction_id);
1573    }
1574
1575    /// Manually remove a transaction from the buffer's undo history
1576    pub fn forget_transaction(&mut self, transaction_id: TransactionId) {
1577        self.text.forget_transaction(transaction_id);
1578    }
1579
1580    /// Manually merge two adjacent transactions in the buffer's undo history.
1581    pub fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) {
1582        self.text.merge_transactions(transaction, destination);
1583    }
1584
1585    /// Waits for the buffer to receive operations with the given timestamps.
1586    pub fn wait_for_edits(
1587        &mut self,
1588        edit_ids: impl IntoIterator<Item = clock::Lamport>,
1589    ) -> impl Future<Output = Result<()>> {
1590        self.text.wait_for_edits(edit_ids)
1591    }
1592
1593    /// Waits for the buffer to receive the operations necessary for resolving the given anchors.
1594    pub fn wait_for_anchors(
1595        &mut self,
1596        anchors: impl IntoIterator<Item = Anchor>,
1597    ) -> impl 'static + Future<Output = Result<()>> {
1598        self.text.wait_for_anchors(anchors)
1599    }
1600
1601    /// Waits for the buffer to receive operations up to the given version.
1602    pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = Result<()>> {
1603        self.text.wait_for_version(version)
1604    }
1605
1606    /// Forces all futures returned by [`Buffer::wait_for_version`], [`Buffer::wait_for_edits`], or
1607    /// [`Buffer::wait_for_version`] to resolve with an error.
1608    pub fn give_up_waiting(&mut self) {
1609        self.text.give_up_waiting();
1610    }
1611
1612    /// Stores a set of selections that should be broadcasted to all of the buffer's replicas.
1613    pub fn set_active_selections(
1614        &mut self,
1615        selections: Arc<[Selection<Anchor>]>,
1616        line_mode: bool,
1617        cursor_shape: CursorShape,
1618        cx: &mut ModelContext<Self>,
1619    ) {
1620        let lamport_timestamp = self.text.lamport_clock.tick();
1621        self.remote_selections.insert(
1622            self.text.replica_id(),
1623            SelectionSet {
1624                selections: selections.clone(),
1625                lamport_timestamp,
1626                line_mode,
1627                cursor_shape,
1628            },
1629        );
1630        self.send_operation(
1631            Operation::UpdateSelections {
1632                selections,
1633                line_mode,
1634                lamport_timestamp,
1635                cursor_shape,
1636            },
1637            cx,
1638        );
1639    }
1640
1641    /// Clears the selections, so that other replicas of the buffer do not see any selections for
1642    /// this replica.
1643    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
1644        if self
1645            .remote_selections
1646            .get(&self.text.replica_id())
1647            .map_or(true, |set| !set.selections.is_empty())
1648        {
1649            self.set_active_selections(Arc::from([]), false, Default::default(), cx);
1650        }
1651    }
1652
1653    /// Replaces the buffer's entire text.
1654    pub fn set_text<T>(&mut self, text: T, cx: &mut ModelContext<Self>) -> Option<clock::Lamport>
1655    where
1656        T: Into<Arc<str>>,
1657    {
1658        self.autoindent_requests.clear();
1659        self.edit([(0..self.len(), text)], None, cx)
1660    }
1661
1662    /// Applies the given edits to the buffer. Each edit is specified as a range of text to
1663    /// delete, and a string of text to insert at that location.
1664    ///
1665    /// If an [`AutoindentMode`] is provided, then the buffer will enqueue an auto-indent
1666    /// request for the edited ranges, which will be processed when the buffer finishes
1667    /// parsing.
1668    ///
1669    /// Parsing takes place at the end of a transaction, and may compute synchronously
1670    /// or asynchronously, depending on the changes.
1671    pub fn edit<I, S, T>(
1672        &mut self,
1673        edits_iter: I,
1674        autoindent_mode: Option<AutoindentMode>,
1675        cx: &mut ModelContext<Self>,
1676    ) -> Option<clock::Lamport>
1677    where
1678        I: IntoIterator<Item = (Range<S>, T)>,
1679        S: ToOffset,
1680        T: Into<Arc<str>>,
1681    {
1682        // Skip invalid edits and coalesce contiguous ones.
1683        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
1684        for (range, new_text) in edits_iter {
1685            let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1686            if range.start > range.end {
1687                mem::swap(&mut range.start, &mut range.end);
1688            }
1689            let new_text = new_text.into();
1690            if !new_text.is_empty() || !range.is_empty() {
1691                if let Some((prev_range, prev_text)) = edits.last_mut() {
1692                    if prev_range.end >= range.start {
1693                        prev_range.end = cmp::max(prev_range.end, range.end);
1694                        *prev_text = format!("{prev_text}{new_text}").into();
1695                    } else {
1696                        edits.push((range, new_text));
1697                    }
1698                } else {
1699                    edits.push((range, new_text));
1700                }
1701            }
1702        }
1703        if edits.is_empty() {
1704            return None;
1705        }
1706
1707        self.start_transaction();
1708        self.pending_autoindent.take();
1709        let autoindent_request = autoindent_mode
1710            .and_then(|mode| self.language.as_ref().map(|_| (self.snapshot(), mode)));
1711
1712        let edit_operation = self.text.edit(edits.iter().cloned());
1713        let edit_id = edit_operation.timestamp();
1714
1715        if let Some((before_edit, mode)) = autoindent_request {
1716            let mut delta = 0isize;
1717            let entries = edits
1718                .into_iter()
1719                .enumerate()
1720                .zip(&edit_operation.as_edit().unwrap().new_text)
1721                .map(|((ix, (range, _)), new_text)| {
1722                    let new_text_length = new_text.len();
1723                    let old_start = range.start.to_point(&before_edit);
1724                    let new_start = (delta + range.start as isize) as usize;
1725                    delta += new_text_length as isize - (range.end as isize - range.start as isize);
1726
1727                    let mut range_of_insertion_to_indent = 0..new_text_length;
1728                    let mut first_line_is_new = false;
1729                    let mut original_indent_column = None;
1730
1731                    // When inserting an entire line at the beginning of an existing line,
1732                    // treat the insertion as new.
1733                    if new_text.contains('\n')
1734                        && old_start.column <= before_edit.indent_size_for_line(old_start.row).len
1735                    {
1736                        first_line_is_new = true;
1737                    }
1738
1739                    // When inserting text starting with a newline, avoid auto-indenting the
1740                    // previous line.
1741                    if new_text.starts_with('\n') {
1742                        range_of_insertion_to_indent.start += 1;
1743                        first_line_is_new = true;
1744                    }
1745
1746                    // Avoid auto-indenting after the insertion.
1747                    if let AutoindentMode::Block {
1748                        original_indent_columns,
1749                    } = &mode
1750                    {
1751                        original_indent_column =
1752                            Some(original_indent_columns.get(ix).copied().unwrap_or_else(|| {
1753                                indent_size_for_text(
1754                                    new_text[range_of_insertion_to_indent.clone()].chars(),
1755                                )
1756                                .len
1757                            }));
1758                        if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
1759                            range_of_insertion_to_indent.end -= 1;
1760                        }
1761                    }
1762
1763                    AutoindentRequestEntry {
1764                        first_line_is_new,
1765                        original_indent_column,
1766                        indent_size: before_edit.language_indent_size_at(range.start, cx),
1767                        range: self.anchor_before(new_start + range_of_insertion_to_indent.start)
1768                            ..self.anchor_after(new_start + range_of_insertion_to_indent.end),
1769                    }
1770                })
1771                .collect();
1772
1773            self.autoindent_requests.push(Arc::new(AutoindentRequest {
1774                before_edit,
1775                entries,
1776                is_block_mode: matches!(mode, AutoindentMode::Block { .. }),
1777            }));
1778        }
1779
1780        self.end_transaction(cx);
1781        self.send_operation(Operation::Buffer(edit_operation), cx);
1782        Some(edit_id)
1783    }
1784
1785    fn did_edit(
1786        &mut self,
1787        old_version: &clock::Global,
1788        was_dirty: bool,
1789        cx: &mut ModelContext<Self>,
1790    ) {
1791        if self.edits_since::<usize>(old_version).next().is_none() {
1792            return;
1793        }
1794
1795        self.reparse(cx);
1796
1797        cx.emit(Event::Edited);
1798        if was_dirty != self.is_dirty() {
1799            cx.emit(Event::DirtyChanged);
1800        }
1801        cx.notify();
1802    }
1803
1804    /// Applies the given remote operations to the buffer.
1805    pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1806        &mut self,
1807        ops: I,
1808        cx: &mut ModelContext<Self>,
1809    ) -> Result<()> {
1810        self.pending_autoindent.take();
1811        let was_dirty = self.is_dirty();
1812        let old_version = self.version.clone();
1813        let mut deferred_ops = Vec::new();
1814        let buffer_ops = ops
1815            .into_iter()
1816            .filter_map(|op| match op {
1817                Operation::Buffer(op) => Some(op),
1818                _ => {
1819                    if self.can_apply_op(&op) {
1820                        self.apply_op(op, cx);
1821                    } else {
1822                        deferred_ops.push(op);
1823                    }
1824                    None
1825                }
1826            })
1827            .collect::<Vec<_>>();
1828        self.text.apply_ops(buffer_ops)?;
1829        self.deferred_ops.insert(deferred_ops);
1830        self.flush_deferred_ops(cx);
1831        self.did_edit(&old_version, was_dirty, cx);
1832        // Notify independently of whether the buffer was edited as the operations could include a
1833        // selection update.
1834        cx.notify();
1835        Ok(())
1836    }
1837
1838    fn flush_deferred_ops(&mut self, cx: &mut ModelContext<Self>) {
1839        let mut deferred_ops = Vec::new();
1840        for op in self.deferred_ops.drain().iter().cloned() {
1841            if self.can_apply_op(&op) {
1842                self.apply_op(op, cx);
1843            } else {
1844                deferred_ops.push(op);
1845            }
1846        }
1847        self.deferred_ops.insert(deferred_ops);
1848    }
1849
1850    fn can_apply_op(&self, operation: &Operation) -> bool {
1851        match operation {
1852            Operation::Buffer(_) => {
1853                unreachable!("buffer operations should never be applied at this layer")
1854            }
1855            Operation::UpdateDiagnostics {
1856                diagnostics: diagnostic_set,
1857                ..
1858            } => diagnostic_set.iter().all(|diagnostic| {
1859                self.text.can_resolve(&diagnostic.range.start)
1860                    && self.text.can_resolve(&diagnostic.range.end)
1861            }),
1862            Operation::UpdateSelections { selections, .. } => selections
1863                .iter()
1864                .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
1865            Operation::UpdateCompletionTriggers { .. } => true,
1866        }
1867    }
1868
1869    fn apply_op(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1870        match operation {
1871            Operation::Buffer(_) => {
1872                unreachable!("buffer operations should never be applied at this layer")
1873            }
1874            Operation::UpdateDiagnostics {
1875                server_id,
1876                diagnostics: diagnostic_set,
1877                lamport_timestamp,
1878            } => {
1879                let snapshot = self.snapshot();
1880                self.apply_diagnostic_update(
1881                    server_id,
1882                    DiagnosticSet::from_sorted_entries(diagnostic_set.iter().cloned(), &snapshot),
1883                    lamport_timestamp,
1884                    cx,
1885                );
1886            }
1887            Operation::UpdateSelections {
1888                selections,
1889                lamport_timestamp,
1890                line_mode,
1891                cursor_shape,
1892            } => {
1893                if let Some(set) = self.remote_selections.get(&lamport_timestamp.replica_id) {
1894                    if set.lamport_timestamp > lamport_timestamp {
1895                        return;
1896                    }
1897                }
1898
1899                self.remote_selections.insert(
1900                    lamport_timestamp.replica_id,
1901                    SelectionSet {
1902                        selections,
1903                        lamport_timestamp,
1904                        line_mode,
1905                        cursor_shape,
1906                    },
1907                );
1908                self.text.lamport_clock.observe(lamport_timestamp);
1909                self.selections_update_count += 1;
1910            }
1911            Operation::UpdateCompletionTriggers {
1912                triggers,
1913                lamport_timestamp,
1914            } => {
1915                self.completion_triggers = triggers;
1916                self.text.lamport_clock.observe(lamport_timestamp);
1917            }
1918        }
1919    }
1920
1921    fn apply_diagnostic_update(
1922        &mut self,
1923        server_id: LanguageServerId,
1924        diagnostics: DiagnosticSet,
1925        lamport_timestamp: clock::Lamport,
1926        cx: &mut ModelContext<Self>,
1927    ) {
1928        if lamport_timestamp > self.diagnostics_timestamp {
1929            let ix = self.diagnostics.binary_search_by_key(&server_id, |e| e.0);
1930            if diagnostics.len() == 0 {
1931                if let Ok(ix) = ix {
1932                    self.diagnostics.remove(ix);
1933                }
1934            } else {
1935                match ix {
1936                    Err(ix) => self.diagnostics.insert(ix, (server_id, diagnostics)),
1937                    Ok(ix) => self.diagnostics[ix].1 = diagnostics,
1938                };
1939            }
1940            self.diagnostics_timestamp = lamport_timestamp;
1941            self.diagnostics_update_count += 1;
1942            self.text.lamport_clock.observe(lamport_timestamp);
1943            cx.notify();
1944            cx.emit(Event::DiagnosticsUpdated);
1945        }
1946    }
1947
1948    fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1949        cx.emit(Event::Operation(operation));
1950    }
1951
1952    /// Removes the selections for a given peer.
1953    pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1954        self.remote_selections.remove(&replica_id);
1955        cx.notify();
1956    }
1957
1958    /// Undoes the most recent transaction.
1959    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1960        let was_dirty = self.is_dirty();
1961        let old_version = self.version.clone();
1962
1963        if let Some((transaction_id, operation)) = self.text.undo() {
1964            self.send_operation(Operation::Buffer(operation), cx);
1965            self.did_edit(&old_version, was_dirty, cx);
1966            Some(transaction_id)
1967        } else {
1968            None
1969        }
1970    }
1971
1972    /// Manually undoes a specific transaction in the buffer's undo history.
1973    pub fn undo_transaction(
1974        &mut self,
1975        transaction_id: TransactionId,
1976        cx: &mut ModelContext<Self>,
1977    ) -> bool {
1978        let was_dirty = self.is_dirty();
1979        let old_version = self.version.clone();
1980        if let Some(operation) = self.text.undo_transaction(transaction_id) {
1981            self.send_operation(Operation::Buffer(operation), cx);
1982            self.did_edit(&old_version, was_dirty, cx);
1983            true
1984        } else {
1985            false
1986        }
1987    }
1988
1989    /// Manually undoes all changes after a given transaction in the buffer's undo history.
1990    pub fn undo_to_transaction(
1991        &mut self,
1992        transaction_id: TransactionId,
1993        cx: &mut ModelContext<Self>,
1994    ) -> bool {
1995        let was_dirty = self.is_dirty();
1996        let old_version = self.version.clone();
1997
1998        let operations = self.text.undo_to_transaction(transaction_id);
1999        let undone = !operations.is_empty();
2000        for operation in operations {
2001            self.send_operation(Operation::Buffer(operation), cx);
2002        }
2003        if undone {
2004            self.did_edit(&old_version, was_dirty, cx)
2005        }
2006        undone
2007    }
2008
2009    /// Manually redoes a specific transaction in the buffer's redo history.
2010    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
2011        let was_dirty = self.is_dirty();
2012        let old_version = self.version.clone();
2013
2014        if let Some((transaction_id, operation)) = self.text.redo() {
2015            self.send_operation(Operation::Buffer(operation), cx);
2016            self.did_edit(&old_version, was_dirty, cx);
2017            Some(transaction_id)
2018        } else {
2019            None
2020        }
2021    }
2022
2023    /// Manually undoes all changes until a given transaction in the buffer's redo history.
2024    pub fn redo_to_transaction(
2025        &mut self,
2026        transaction_id: TransactionId,
2027        cx: &mut ModelContext<Self>,
2028    ) -> bool {
2029        let was_dirty = self.is_dirty();
2030        let old_version = self.version.clone();
2031
2032        let operations = self.text.redo_to_transaction(transaction_id);
2033        let redone = !operations.is_empty();
2034        for operation in operations {
2035            self.send_operation(Operation::Buffer(operation), cx);
2036        }
2037        if redone {
2038            self.did_edit(&old_version, was_dirty, cx)
2039        }
2040        redone
2041    }
2042
2043    /// Override current completion triggers with the user-provided completion triggers.
2044    pub fn set_completion_triggers(&mut self, triggers: Vec<String>, cx: &mut ModelContext<Self>) {
2045        self.completion_triggers = triggers.clone();
2046        self.completion_triggers_timestamp = self.text.lamport_clock.tick();
2047        self.send_operation(
2048            Operation::UpdateCompletionTriggers {
2049                triggers,
2050                lamport_timestamp: self.completion_triggers_timestamp,
2051            },
2052            cx,
2053        );
2054        cx.notify();
2055    }
2056
2057    /// Returns a list of strings which trigger a completion menu for this language.
2058    /// Usually this is driven by LSP server which returns a list of trigger characters for completions.
2059    pub fn completion_triggers(&self) -> &[String] {
2060        &self.completion_triggers
2061    }
2062}
2063
2064#[doc(hidden)]
2065#[cfg(any(test, feature = "test-support"))]
2066impl Buffer {
2067    pub fn edit_via_marked_text(
2068        &mut self,
2069        marked_string: &str,
2070        autoindent_mode: Option<AutoindentMode>,
2071        cx: &mut ModelContext<Self>,
2072    ) {
2073        let edits = self.edits_for_marked_text(marked_string);
2074        self.edit(edits, autoindent_mode, cx);
2075    }
2076
2077    pub fn set_group_interval(&mut self, group_interval: Duration) {
2078        self.text.set_group_interval(group_interval);
2079    }
2080
2081    pub fn randomly_edit<T>(
2082        &mut self,
2083        rng: &mut T,
2084        old_range_count: usize,
2085        cx: &mut ModelContext<Self>,
2086    ) where
2087        T: rand::Rng,
2088    {
2089        let mut edits: Vec<(Range<usize>, String)> = Vec::new();
2090        let mut last_end = None;
2091        for _ in 0..old_range_count {
2092            if last_end.map_or(false, |last_end| last_end >= self.len()) {
2093                break;
2094            }
2095
2096            let new_start = last_end.map_or(0, |last_end| last_end + 1);
2097            let mut range = self.random_byte_range(new_start, rng);
2098            if rng.gen_bool(0.2) {
2099                mem::swap(&mut range.start, &mut range.end);
2100            }
2101            last_end = Some(range.end);
2102
2103            let new_text_len = rng.gen_range(0..10);
2104            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
2105
2106            edits.push((range, new_text));
2107        }
2108        log::info!("mutating buffer {} with {:?}", self.replica_id(), edits);
2109        self.edit(edits, None, cx);
2110    }
2111
2112    pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
2113        let was_dirty = self.is_dirty();
2114        let old_version = self.version.clone();
2115
2116        let ops = self.text.randomly_undo_redo(rng);
2117        if !ops.is_empty() {
2118            for op in ops {
2119                self.send_operation(Operation::Buffer(op), cx);
2120                self.did_edit(&old_version, was_dirty, cx);
2121            }
2122        }
2123    }
2124}
2125
2126impl EventEmitter<Event> for Buffer {}
2127
2128impl Deref for Buffer {
2129    type Target = TextBuffer;
2130
2131    fn deref(&self) -> &Self::Target {
2132        &self.text
2133    }
2134}
2135
2136impl BufferSnapshot {
2137    /// Returns [`IndentSize`] for a given line that respects user settings and /// language preferences.
2138    pub fn indent_size_for_line(&self, row: u32) -> IndentSize {
2139        indent_size_for_line(self, row)
2140    }
2141    /// Returns [`IndentSize`] for a given position that respects user settings
2142    /// and language preferences.
2143    pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &AppContext) -> IndentSize {
2144        let settings = language_settings(self.language_at(position), self.file(), cx);
2145        if settings.hard_tabs {
2146            IndentSize::tab()
2147        } else {
2148            IndentSize::spaces(settings.tab_size.get())
2149        }
2150    }
2151
2152    /// Retrieve the suggested indent size for all of the given rows. The unit of indentation
2153    /// is passed in as `single_indent_size`.
2154    pub fn suggested_indents(
2155        &self,
2156        rows: impl Iterator<Item = u32>,
2157        single_indent_size: IndentSize,
2158    ) -> BTreeMap<u32, IndentSize> {
2159        let mut result = BTreeMap::new();
2160
2161        for row_range in contiguous_ranges(rows, 10) {
2162            let suggestions = match self.suggest_autoindents(row_range.clone()) {
2163                Some(suggestions) => suggestions,
2164                _ => break,
2165            };
2166
2167            for (row, suggestion) in row_range.zip(suggestions) {
2168                let indent_size = if let Some(suggestion) = suggestion {
2169                    result
2170                        .get(&suggestion.basis_row)
2171                        .copied()
2172                        .unwrap_or_else(|| self.indent_size_for_line(suggestion.basis_row))
2173                        .with_delta(suggestion.delta, single_indent_size)
2174                } else {
2175                    self.indent_size_for_line(row)
2176                };
2177
2178                result.insert(row, indent_size);
2179            }
2180        }
2181
2182        result
2183    }
2184
2185    fn suggest_autoindents(
2186        &self,
2187        row_range: Range<u32>,
2188    ) -> Option<impl Iterator<Item = Option<IndentSuggestion>> + '_> {
2189        let config = &self.language.as_ref()?.config;
2190        let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
2191
2192        // Find the suggested indentation ranges based on the syntax tree.
2193        let start = Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0);
2194        let end = Point::new(row_range.end, 0);
2195        let range = (start..end).to_offset(&self.text);
2196        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2197            Some(&grammar.indents_config.as_ref()?.query)
2198        });
2199        let indent_configs = matches
2200            .grammars()
2201            .iter()
2202            .map(|grammar| grammar.indents_config.as_ref().unwrap())
2203            .collect::<Vec<_>>();
2204
2205        let mut indent_ranges = Vec::<Range<Point>>::new();
2206        let mut outdent_positions = Vec::<Point>::new();
2207        while let Some(mat) = matches.peek() {
2208            let mut start: Option<Point> = None;
2209            let mut end: Option<Point> = None;
2210
2211            let config = &indent_configs[mat.grammar_index];
2212            for capture in mat.captures {
2213                if capture.index == config.indent_capture_ix {
2214                    start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
2215                    end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
2216                } else if Some(capture.index) == config.start_capture_ix {
2217                    start = Some(Point::from_ts_point(capture.node.end_position()));
2218                } else if Some(capture.index) == config.end_capture_ix {
2219                    end = Some(Point::from_ts_point(capture.node.start_position()));
2220                } else if Some(capture.index) == config.outdent_capture_ix {
2221                    outdent_positions.push(Point::from_ts_point(capture.node.start_position()));
2222                }
2223            }
2224
2225            matches.advance();
2226            if let Some((start, end)) = start.zip(end) {
2227                if start.row == end.row {
2228                    continue;
2229                }
2230
2231                let range = start..end;
2232                match indent_ranges.binary_search_by_key(&range.start, |r| r.start) {
2233                    Err(ix) => indent_ranges.insert(ix, range),
2234                    Ok(ix) => {
2235                        let prev_range = &mut indent_ranges[ix];
2236                        prev_range.end = prev_range.end.max(range.end);
2237                    }
2238                }
2239            }
2240        }
2241
2242        let mut error_ranges = Vec::<Range<Point>>::new();
2243        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2244            Some(&grammar.error_query)
2245        });
2246        while let Some(mat) = matches.peek() {
2247            let node = mat.captures[0].node;
2248            let start = Point::from_ts_point(node.start_position());
2249            let end = Point::from_ts_point(node.end_position());
2250            let range = start..end;
2251            let ix = match error_ranges.binary_search_by_key(&range.start, |r| r.start) {
2252                Ok(ix) | Err(ix) => ix,
2253            };
2254            let mut end_ix = ix;
2255            while let Some(existing_range) = error_ranges.get(end_ix) {
2256                if existing_range.end < end {
2257                    end_ix += 1;
2258                } else {
2259                    break;
2260                }
2261            }
2262            error_ranges.splice(ix..end_ix, [range]);
2263            matches.advance();
2264        }
2265
2266        outdent_positions.sort();
2267        for outdent_position in outdent_positions {
2268            // find the innermost indent range containing this outdent_position
2269            // set its end to the outdent position
2270            if let Some(range_to_truncate) = indent_ranges
2271                .iter_mut()
2272                .filter(|indent_range| indent_range.contains(&outdent_position))
2273                .last()
2274            {
2275                range_to_truncate.end = outdent_position;
2276            }
2277        }
2278
2279        // Find the suggested indentation increases and decreased based on regexes.
2280        let mut indent_change_rows = Vec::<(u32, Ordering)>::new();
2281        self.for_each_line(
2282            Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0)
2283                ..Point::new(row_range.end, 0),
2284            |row, line| {
2285                if config
2286                    .decrease_indent_pattern
2287                    .as_ref()
2288                    .map_or(false, |regex| regex.is_match(line))
2289                {
2290                    indent_change_rows.push((row, Ordering::Less));
2291                }
2292                if config
2293                    .increase_indent_pattern
2294                    .as_ref()
2295                    .map_or(false, |regex| regex.is_match(line))
2296                {
2297                    indent_change_rows.push((row + 1, Ordering::Greater));
2298                }
2299            },
2300        );
2301
2302        let mut indent_changes = indent_change_rows.into_iter().peekable();
2303        let mut prev_row = if config.auto_indent_using_last_non_empty_line {
2304            prev_non_blank_row.unwrap_or(0)
2305        } else {
2306            row_range.start.saturating_sub(1)
2307        };
2308        let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len);
2309        Some(row_range.map(move |row| {
2310            let row_start = Point::new(row, self.indent_size_for_line(row).len);
2311
2312            let mut indent_from_prev_row = false;
2313            let mut outdent_from_prev_row = false;
2314            let mut outdent_to_row = u32::MAX;
2315
2316            while let Some((indent_row, delta)) = indent_changes.peek() {
2317                match indent_row.cmp(&row) {
2318                    Ordering::Equal => match delta {
2319                        Ordering::Less => outdent_from_prev_row = true,
2320                        Ordering::Greater => indent_from_prev_row = true,
2321                        _ => {}
2322                    },
2323
2324                    Ordering::Greater => break,
2325                    Ordering::Less => {}
2326                }
2327
2328                indent_changes.next();
2329            }
2330
2331            for range in &indent_ranges {
2332                if range.start.row >= row {
2333                    break;
2334                }
2335                if range.start.row == prev_row && range.end > row_start {
2336                    indent_from_prev_row = true;
2337                }
2338                if range.end > prev_row_start && range.end <= row_start {
2339                    outdent_to_row = outdent_to_row.min(range.start.row);
2340                }
2341            }
2342
2343            let within_error = error_ranges
2344                .iter()
2345                .any(|e| e.start.row < row && e.end > row_start);
2346
2347            let suggestion = if outdent_to_row == prev_row
2348                || (outdent_from_prev_row && indent_from_prev_row)
2349            {
2350                Some(IndentSuggestion {
2351                    basis_row: prev_row,
2352                    delta: Ordering::Equal,
2353                    within_error,
2354                })
2355            } else if indent_from_prev_row {
2356                Some(IndentSuggestion {
2357                    basis_row: prev_row,
2358                    delta: Ordering::Greater,
2359                    within_error,
2360                })
2361            } else if outdent_to_row < prev_row {
2362                Some(IndentSuggestion {
2363                    basis_row: outdent_to_row,
2364                    delta: Ordering::Equal,
2365                    within_error,
2366                })
2367            } else if outdent_from_prev_row {
2368                Some(IndentSuggestion {
2369                    basis_row: prev_row,
2370                    delta: Ordering::Less,
2371                    within_error,
2372                })
2373            } else if config.auto_indent_using_last_non_empty_line || !self.is_line_blank(prev_row)
2374            {
2375                Some(IndentSuggestion {
2376                    basis_row: prev_row,
2377                    delta: Ordering::Equal,
2378                    within_error,
2379                })
2380            } else {
2381                None
2382            };
2383
2384            prev_row = row;
2385            prev_row_start = row_start;
2386            suggestion
2387        }))
2388    }
2389
2390    fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
2391        while row > 0 {
2392            row -= 1;
2393            if !self.is_line_blank(row) {
2394                return Some(row);
2395            }
2396        }
2397        None
2398    }
2399
2400    /// Iterates over chunks of text in the given range of the buffer. Text is chunked
2401    /// in an arbitrary way due to being stored in a [`Rope`](text::Rope). The text is also
2402    /// returned in chunks where each chunk has a single syntax highlighting style and
2403    /// diagnostic status.
2404    pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> BufferChunks {
2405        let range = range.start.to_offset(self)..range.end.to_offset(self);
2406
2407        let mut syntax = None;
2408        let mut diagnostic_endpoints = Vec::new();
2409        if language_aware {
2410            let captures = self.syntax.captures(range.clone(), &self.text, |grammar| {
2411                grammar.highlights_query.as_ref()
2412            });
2413            let highlight_maps = captures
2414                .grammars()
2415                .into_iter()
2416                .map(|grammar| grammar.highlight_map())
2417                .collect();
2418            syntax = Some((captures, highlight_maps));
2419            for entry in self.diagnostics_in_range::<_, usize>(range.clone(), false) {
2420                diagnostic_endpoints.push(DiagnosticEndpoint {
2421                    offset: entry.range.start,
2422                    is_start: true,
2423                    severity: entry.diagnostic.severity,
2424                    is_unnecessary: entry.diagnostic.is_unnecessary,
2425                });
2426                diagnostic_endpoints.push(DiagnosticEndpoint {
2427                    offset: entry.range.end,
2428                    is_start: false,
2429                    severity: entry.diagnostic.severity,
2430                    is_unnecessary: entry.diagnostic.is_unnecessary,
2431                });
2432            }
2433            diagnostic_endpoints
2434                .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
2435        }
2436
2437        BufferChunks::new(self.text.as_rope(), range, syntax, diagnostic_endpoints)
2438    }
2439
2440    /// Invokes the given callback for each line of text in the given range of the buffer.
2441    /// Uses callback to avoid allocating a string for each line.
2442    fn for_each_line(&self, range: Range<Point>, mut callback: impl FnMut(u32, &str)) {
2443        let mut line = String::new();
2444        let mut row = range.start.row;
2445        for chunk in self
2446            .as_rope()
2447            .chunks_in_range(range.to_offset(self))
2448            .chain(["\n"])
2449        {
2450            for (newline_ix, text) in chunk.split('\n').enumerate() {
2451                if newline_ix > 0 {
2452                    callback(row, &line);
2453                    row += 1;
2454                    line.clear();
2455                }
2456                line.push_str(text);
2457            }
2458        }
2459    }
2460
2461    /// Iterates over every [`SyntaxLayer`] in the buffer.
2462    pub fn syntax_layers(&self) -> impl Iterator<Item = SyntaxLayer> + '_ {
2463        self.syntax.layers_for_range(0..self.len(), &self.text)
2464    }
2465
2466    pub fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer> {
2467        let offset = position.to_offset(self);
2468        self.syntax
2469            .layers_for_range(offset..offset, &self.text)
2470            .filter(|l| l.node().end_byte() > offset)
2471            .last()
2472    }
2473
2474    /// Returns the main [Language]
2475    pub fn language(&self) -> Option<&Arc<Language>> {
2476        self.language.as_ref()
2477    }
2478
2479    /// Returns the [Language] at the given location.
2480    pub fn language_at<D: ToOffset>(&self, position: D) -> Option<&Arc<Language>> {
2481        self.syntax_layer_at(position)
2482            .map(|info| info.language)
2483            .or(self.language.as_ref())
2484    }
2485
2486    /// Returns the settings for the language at the given location.
2487    pub fn settings_at<'a, D: ToOffset>(
2488        &self,
2489        position: D,
2490        cx: &'a AppContext,
2491    ) -> &'a LanguageSettings {
2492        language_settings(self.language_at(position), self.file.as_ref(), cx)
2493    }
2494
2495    /// Returns the [LanguageScope] at the given location.
2496    pub fn language_scope_at<D: ToOffset>(&self, position: D) -> Option<LanguageScope> {
2497        let offset = position.to_offset(self);
2498        let mut scope = None;
2499        let mut smallest_range: Option<Range<usize>> = None;
2500
2501        // Use the layer that has the smallest node intersecting the given point.
2502        for layer in self.syntax.layers_for_range(offset..offset, &self.text) {
2503            let mut cursor = layer.node().walk();
2504
2505            let mut range = None;
2506            loop {
2507                let child_range = cursor.node().byte_range();
2508                if !child_range.to_inclusive().contains(&offset) {
2509                    break;
2510                }
2511
2512                range = Some(child_range);
2513                if cursor.goto_first_child_for_byte(offset).is_none() {
2514                    break;
2515                }
2516            }
2517
2518            if let Some(range) = range {
2519                if smallest_range
2520                    .as_ref()
2521                    .map_or(true, |smallest_range| range.len() < smallest_range.len())
2522                {
2523                    smallest_range = Some(range);
2524                    scope = Some(LanguageScope {
2525                        language: layer.language.clone(),
2526                        override_id: layer.override_id(offset, &self.text),
2527                    });
2528                }
2529            }
2530        }
2531
2532        scope.or_else(|| {
2533            self.language.clone().map(|language| LanguageScope {
2534                language,
2535                override_id: None,
2536            })
2537        })
2538    }
2539
2540    /// Returns a tuple of the range and character kind of the word
2541    /// surrounding the given position.
2542    pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
2543        let mut start = start.to_offset(self);
2544        let mut end = start;
2545        let mut next_chars = self.chars_at(start).peekable();
2546        let mut prev_chars = self.reversed_chars_at(start).peekable();
2547
2548        let scope = self.language_scope_at(start);
2549        let kind = |c| char_kind(&scope, c);
2550        let word_kind = cmp::max(
2551            prev_chars.peek().copied().map(kind),
2552            next_chars.peek().copied().map(kind),
2553        );
2554
2555        for ch in prev_chars {
2556            if Some(kind(ch)) == word_kind && ch != '\n' {
2557                start -= ch.len_utf8();
2558            } else {
2559                break;
2560            }
2561        }
2562
2563        for ch in next_chars {
2564            if Some(kind(ch)) == word_kind && ch != '\n' {
2565                end += ch.len_utf8();
2566            } else {
2567                break;
2568            }
2569        }
2570
2571        (start..end, word_kind)
2572    }
2573
2574    /// Returns the range for the closes syntax node enclosing the given range.
2575    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2576        let range = range.start.to_offset(self)..range.end.to_offset(self);
2577        let mut result: Option<Range<usize>> = None;
2578        'outer: for layer in self.syntax.layers_for_range(range.clone(), &self.text) {
2579            let mut cursor = layer.node().walk();
2580
2581            // Descend to the first leaf that touches the start of the range,
2582            // and if the range is non-empty, extends beyond the start.
2583            while cursor.goto_first_child_for_byte(range.start).is_some() {
2584                if !range.is_empty() && cursor.node().end_byte() == range.start {
2585                    cursor.goto_next_sibling();
2586                }
2587            }
2588
2589            // Ascend to the smallest ancestor that strictly contains the range.
2590            loop {
2591                let node_range = cursor.node().byte_range();
2592                if node_range.start <= range.start
2593                    && node_range.end >= range.end
2594                    && node_range.len() > range.len()
2595                {
2596                    break;
2597                }
2598                if !cursor.goto_parent() {
2599                    continue 'outer;
2600                }
2601            }
2602
2603            let left_node = cursor.node();
2604            let mut layer_result = left_node.byte_range();
2605
2606            // For an empty range, try to find another node immediately to the right of the range.
2607            if left_node.end_byte() == range.start {
2608                let mut right_node = None;
2609                while !cursor.goto_next_sibling() {
2610                    if !cursor.goto_parent() {
2611                        break;
2612                    }
2613                }
2614
2615                while cursor.node().start_byte() == range.start {
2616                    right_node = Some(cursor.node());
2617                    if !cursor.goto_first_child() {
2618                        break;
2619                    }
2620                }
2621
2622                // If there is a candidate node on both sides of the (empty) range, then
2623                // decide between the two by favoring a named node over an anonymous token.
2624                // If both nodes are the same in that regard, favor the right one.
2625                if let Some(right_node) = right_node {
2626                    if right_node.is_named() || !left_node.is_named() {
2627                        layer_result = right_node.byte_range();
2628                    }
2629                }
2630            }
2631
2632            if let Some(previous_result) = &result {
2633                if previous_result.len() < layer_result.len() {
2634                    continue;
2635                }
2636            }
2637            result = Some(layer_result);
2638        }
2639
2640        result
2641    }
2642
2643    /// Returns the outline for the buffer.
2644    ///
2645    /// This method allows passing an optional [SyntaxTheme] to
2646    /// syntax-highlight the returned symbols.
2647    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2648        self.outline_items_containing(0..self.len(), true, theme)
2649            .map(Outline::new)
2650    }
2651
2652    /// Returns all the symbols that contain the given position.
2653    ///
2654    /// This method allows passing an optional [SyntaxTheme] to
2655    /// syntax-highlight the returned symbols.
2656    pub fn symbols_containing<T: ToOffset>(
2657        &self,
2658        position: T,
2659        theme: Option<&SyntaxTheme>,
2660    ) -> Option<Vec<OutlineItem<Anchor>>> {
2661        let position = position.to_offset(self);
2662        let mut items = self.outline_items_containing(
2663            position.saturating_sub(1)..self.len().min(position + 1),
2664            false,
2665            theme,
2666        )?;
2667        let mut prev_depth = None;
2668        items.retain(|item| {
2669            let result = prev_depth.map_or(true, |prev_depth| item.depth > prev_depth);
2670            prev_depth = Some(item.depth);
2671            result
2672        });
2673        Some(items)
2674    }
2675
2676    fn outline_items_containing(
2677        &self,
2678        range: Range<usize>,
2679        include_extra_context: bool,
2680        theme: Option<&SyntaxTheme>,
2681    ) -> Option<Vec<OutlineItem<Anchor>>> {
2682        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2683            grammar.outline_config.as_ref().map(|c| &c.query)
2684        });
2685        let configs = matches
2686            .grammars()
2687            .iter()
2688            .map(|g| g.outline_config.as_ref().unwrap())
2689            .collect::<Vec<_>>();
2690
2691        let mut stack = Vec::<Range<usize>>::new();
2692        let mut items = Vec::new();
2693        while let Some(mat) = matches.peek() {
2694            let config = &configs[mat.grammar_index];
2695            let item_node = mat.captures.iter().find_map(|cap| {
2696                if cap.index == config.item_capture_ix {
2697                    Some(cap.node)
2698                } else {
2699                    None
2700                }
2701            })?;
2702
2703            let item_range = item_node.byte_range();
2704            if item_range.end < range.start || item_range.start > range.end {
2705                matches.advance();
2706                continue;
2707            }
2708
2709            let mut buffer_ranges = Vec::new();
2710            for capture in mat.captures {
2711                let node_is_name;
2712                if capture.index == config.name_capture_ix {
2713                    node_is_name = true;
2714                } else if Some(capture.index) == config.context_capture_ix
2715                    || (Some(capture.index) == config.extra_context_capture_ix
2716                        && include_extra_context)
2717                {
2718                    node_is_name = false;
2719                } else {
2720                    continue;
2721                }
2722
2723                let mut range = capture.node.start_byte()..capture.node.end_byte();
2724                let start = capture.node.start_position();
2725                if capture.node.end_position().row > start.row {
2726                    range.end =
2727                        range.start + self.line_len(start.row as u32) as usize - start.column;
2728                }
2729
2730                if !range.is_empty() {
2731                    buffer_ranges.push((range, node_is_name));
2732                }
2733            }
2734
2735            if buffer_ranges.is_empty() {
2736                matches.advance();
2737                continue;
2738            }
2739
2740            let mut text = String::new();
2741            let mut highlight_ranges = Vec::new();
2742            let mut name_ranges = Vec::new();
2743            let mut chunks = self.chunks(
2744                buffer_ranges.first().unwrap().0.start..buffer_ranges.last().unwrap().0.end,
2745                true,
2746            );
2747            let mut last_buffer_range_end = 0;
2748            for (buffer_range, is_name) in buffer_ranges {
2749                if !text.is_empty() && buffer_range.start > last_buffer_range_end {
2750                    text.push(' ');
2751                }
2752                last_buffer_range_end = buffer_range.end;
2753                if is_name {
2754                    let mut start = text.len();
2755                    let end = start + buffer_range.len();
2756
2757                    // When multiple names are captured, then the matcheable text
2758                    // includes the whitespace in between the names.
2759                    if !name_ranges.is_empty() {
2760                        start -= 1;
2761                    }
2762
2763                    name_ranges.push(start..end);
2764                }
2765
2766                let mut offset = buffer_range.start;
2767                chunks.seek(offset);
2768                for mut chunk in chunks.by_ref() {
2769                    if chunk.text.len() > buffer_range.end - offset {
2770                        chunk.text = &chunk.text[0..(buffer_range.end - offset)];
2771                        offset = buffer_range.end;
2772                    } else {
2773                        offset += chunk.text.len();
2774                    }
2775                    let style = chunk
2776                        .syntax_highlight_id
2777                        .zip(theme)
2778                        .and_then(|(highlight, theme)| highlight.style(theme));
2779                    if let Some(style) = style {
2780                        let start = text.len();
2781                        let end = start + chunk.text.len();
2782                        highlight_ranges.push((start..end, style));
2783                    }
2784                    text.push_str(chunk.text);
2785                    if offset >= buffer_range.end {
2786                        break;
2787                    }
2788                }
2789            }
2790
2791            matches.advance();
2792            while stack.last().map_or(false, |prev_range| {
2793                prev_range.start > item_range.start || prev_range.end < item_range.end
2794            }) {
2795                stack.pop();
2796            }
2797            stack.push(item_range.clone());
2798
2799            items.push(OutlineItem {
2800                depth: stack.len() - 1,
2801                range: self.anchor_after(item_range.start)..self.anchor_before(item_range.end),
2802                text,
2803                highlight_ranges,
2804                name_ranges,
2805            })
2806        }
2807        Some(items)
2808    }
2809
2810    /// For each grammar in the language, runs the provided
2811    /// [tree_sitter::Query] against the given range.
2812    pub fn matches(
2813        &self,
2814        range: Range<usize>,
2815        query: fn(&Grammar) -> Option<&tree_sitter::Query>,
2816    ) -> SyntaxMapMatches {
2817        self.syntax.matches(range, self, query)
2818    }
2819
2820    /// Returns bracket range pairs overlapping or adjacent to `range`
2821    pub fn bracket_ranges<T: ToOffset>(
2822        &self,
2823        range: Range<T>,
2824    ) -> impl Iterator<Item = (Range<usize>, Range<usize>)> + '_ {
2825        // Find bracket pairs that *inclusively* contain the given range.
2826        let range = range.start.to_offset(self).saturating_sub(1)
2827            ..self.len().min(range.end.to_offset(self) + 1);
2828
2829        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2830            grammar.brackets_config.as_ref().map(|c| &c.query)
2831        });
2832        let configs = matches
2833            .grammars()
2834            .iter()
2835            .map(|grammar| grammar.brackets_config.as_ref().unwrap())
2836            .collect::<Vec<_>>();
2837
2838        iter::from_fn(move || {
2839            while let Some(mat) = matches.peek() {
2840                let mut open = None;
2841                let mut close = None;
2842                let config = &configs[mat.grammar_index];
2843                for capture in mat.captures {
2844                    if capture.index == config.open_capture_ix {
2845                        open = Some(capture.node.byte_range());
2846                    } else if capture.index == config.close_capture_ix {
2847                        close = Some(capture.node.byte_range());
2848                    }
2849                }
2850
2851                matches.advance();
2852
2853                let Some((open, close)) = open.zip(close) else {
2854                    continue;
2855                };
2856
2857                let bracket_range = open.start..=close.end;
2858                if !bracket_range.overlaps(&range) {
2859                    continue;
2860                }
2861
2862                return Some((open, close));
2863            }
2864            None
2865        })
2866    }
2867
2868    /// Returns enclosing bracket ranges containing the given range
2869    pub fn enclosing_bracket_ranges<T: ToOffset>(
2870        &self,
2871        range: Range<T>,
2872    ) -> impl Iterator<Item = (Range<usize>, Range<usize>)> + '_ {
2873        let range = range.start.to_offset(self)..range.end.to_offset(self);
2874
2875        self.bracket_ranges(range.clone())
2876            .filter(move |(open, close)| open.start <= range.start && close.end >= range.end)
2877    }
2878
2879    /// Returns the smallest enclosing bracket ranges containing the given range or None if no brackets contain range
2880    ///
2881    /// Can optionally pass a range_filter to filter the ranges of brackets to consider
2882    pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
2883        &self,
2884        range: Range<T>,
2885        range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
2886    ) -> Option<(Range<usize>, Range<usize>)> {
2887        let range = range.start.to_offset(self)..range.end.to_offset(self);
2888
2889        // Get the ranges of the innermost pair of brackets.
2890        let mut result: Option<(Range<usize>, Range<usize>)> = None;
2891
2892        for (open, close) in self.enclosing_bracket_ranges(range.clone()) {
2893            if let Some(range_filter) = range_filter {
2894                if !range_filter(open.clone(), close.clone()) {
2895                    continue;
2896                }
2897            }
2898
2899            let len = close.end - open.start;
2900
2901            if let Some((existing_open, existing_close)) = &result {
2902                let existing_len = existing_close.end - existing_open.start;
2903                if len > existing_len {
2904                    continue;
2905                }
2906            }
2907
2908            result = Some((open, close));
2909        }
2910
2911        result
2912    }
2913
2914    /// Returns anchor ranges for any matches of the redaction query.
2915    /// The buffer can be associated with multiple languages, and the redaction query associated with each
2916    /// will be run on the relevant section of the buffer.
2917    pub fn redacted_ranges<T: ToOffset>(
2918        &self,
2919        range: Range<T>,
2920    ) -> impl Iterator<Item = Range<usize>> + '_ {
2921        let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
2922        let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
2923            grammar
2924                .redactions_config
2925                .as_ref()
2926                .map(|config| &config.query)
2927        });
2928
2929        let configs = syntax_matches
2930            .grammars()
2931            .iter()
2932            .map(|grammar| grammar.redactions_config.as_ref())
2933            .collect::<Vec<_>>();
2934
2935        iter::from_fn(move || {
2936            let redacted_range = syntax_matches
2937                .peek()
2938                .and_then(|mat| {
2939                    configs[mat.grammar_index].and_then(|config| {
2940                        mat.captures
2941                            .iter()
2942                            .find(|capture| capture.index == config.redaction_capture_ix)
2943                    })
2944                })
2945                .map(|mat| mat.node.byte_range());
2946            syntax_matches.advance();
2947            redacted_range
2948        })
2949    }
2950
2951    /// Returns selections for remote peers intersecting the given range.
2952    #[allow(clippy::type_complexity)]
2953    pub fn remote_selections_in_range(
2954        &self,
2955        range: Range<Anchor>,
2956    ) -> impl Iterator<
2957        Item = (
2958            ReplicaId,
2959            bool,
2960            CursorShape,
2961            impl Iterator<Item = &Selection<Anchor>> + '_,
2962        ),
2963    > + '_ {
2964        self.remote_selections
2965            .iter()
2966            .filter(|(replica_id, set)| {
2967                **replica_id != self.text.replica_id() && !set.selections.is_empty()
2968            })
2969            .map(move |(replica_id, set)| {
2970                let start_ix = match set.selections.binary_search_by(|probe| {
2971                    probe.end.cmp(&range.start, self).then(Ordering::Greater)
2972                }) {
2973                    Ok(ix) | Err(ix) => ix,
2974                };
2975                let end_ix = match set.selections.binary_search_by(|probe| {
2976                    probe.start.cmp(&range.end, self).then(Ordering::Less)
2977                }) {
2978                    Ok(ix) | Err(ix) => ix,
2979                };
2980
2981                (
2982                    *replica_id,
2983                    set.line_mode,
2984                    set.cursor_shape,
2985                    set.selections[start_ix..end_ix].iter(),
2986                )
2987            })
2988    }
2989
2990    /// Whether the buffer contains any git changes.
2991    pub fn has_git_diff(&self) -> bool {
2992        !self.git_diff.is_empty()
2993    }
2994
2995    /// Returns all the Git diff hunks intersecting the given
2996    /// row range.
2997    pub fn git_diff_hunks_in_row_range(
2998        &self,
2999        range: Range<u32>,
3000    ) -> impl '_ + Iterator<Item = git::diff::DiffHunk<u32>> {
3001        self.git_diff.hunks_in_row_range(range, self)
3002    }
3003
3004    /// Returns all the Git diff hunks intersecting the given
3005    /// range.
3006    pub fn git_diff_hunks_intersecting_range(
3007        &self,
3008        range: Range<Anchor>,
3009    ) -> impl '_ + Iterator<Item = git::diff::DiffHunk<u32>> {
3010        self.git_diff.hunks_intersecting_range(range, self)
3011    }
3012
3013    /// Returns all the Git diff hunks intersecting the given
3014    /// range, in reverse order.
3015    pub fn git_diff_hunks_intersecting_range_rev(
3016        &self,
3017        range: Range<Anchor>,
3018    ) -> impl '_ + Iterator<Item = git::diff::DiffHunk<u32>> {
3019        self.git_diff.hunks_intersecting_range_rev(range, self)
3020    }
3021
3022    /// Returns if the buffer contains any diagnostics.
3023    pub fn has_diagnostics(&self) -> bool {
3024        !self.diagnostics.is_empty()
3025    }
3026
3027    /// Returns all the diagnostics intersecting the given range.
3028    pub fn diagnostics_in_range<'a, T, O>(
3029        &'a self,
3030        search_range: Range<T>,
3031        reversed: bool,
3032    ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
3033    where
3034        T: 'a + Clone + ToOffset,
3035        O: 'a + FromAnchor + Ord,
3036    {
3037        let mut iterators: Vec<_> = self
3038            .diagnostics
3039            .iter()
3040            .map(|(_, collection)| {
3041                collection
3042                    .range::<T, O>(search_range.clone(), self, true, reversed)
3043                    .peekable()
3044            })
3045            .collect();
3046
3047        std::iter::from_fn(move || {
3048            let (next_ix, _) = iterators
3049                .iter_mut()
3050                .enumerate()
3051                .flat_map(|(ix, iter)| Some((ix, iter.peek()?)))
3052                .min_by(|(_, a), (_, b)| a.range.start.cmp(&b.range.start))?;
3053            iterators[next_ix].next()
3054        })
3055    }
3056
3057    /// Returns all the diagnostic groups associated with the given
3058    /// language server id. If no language server id is provided,
3059    /// all diagnostics groups are returned.
3060    pub fn diagnostic_groups(
3061        &self,
3062        language_server_id: Option<LanguageServerId>,
3063    ) -> Vec<(LanguageServerId, DiagnosticGroup<Anchor>)> {
3064        let mut groups = Vec::new();
3065
3066        if let Some(language_server_id) = language_server_id {
3067            if let Ok(ix) = self
3068                .diagnostics
3069                .binary_search_by_key(&language_server_id, |e| e.0)
3070            {
3071                self.diagnostics[ix]
3072                    .1
3073                    .groups(language_server_id, &mut groups, self);
3074            }
3075        } else {
3076            for (language_server_id, diagnostics) in self.diagnostics.iter() {
3077                diagnostics.groups(*language_server_id, &mut groups, self);
3078            }
3079        }
3080
3081        groups.sort_by(|(id_a, group_a), (id_b, group_b)| {
3082            let a_start = &group_a.entries[group_a.primary_ix].range.start;
3083            let b_start = &group_b.entries[group_b.primary_ix].range.start;
3084            a_start.cmp(b_start, self).then_with(|| id_a.cmp(id_b))
3085        });
3086
3087        groups
3088    }
3089
3090    /// Returns an iterator over the diagnostics for the given group.
3091    pub fn diagnostic_group<'a, O>(
3092        &'a self,
3093        group_id: usize,
3094    ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
3095    where
3096        O: 'a + FromAnchor,
3097    {
3098        self.diagnostics
3099            .iter()
3100            .flat_map(move |(_, set)| set.group(group_id, self))
3101    }
3102
3103    /// The number of times diagnostics were updated.
3104    pub fn diagnostics_update_count(&self) -> usize {
3105        self.diagnostics_update_count
3106    }
3107
3108    /// The number of times the buffer was parsed.
3109    pub fn parse_count(&self) -> usize {
3110        self.parse_count
3111    }
3112
3113    /// The number of times selections were updated.
3114    pub fn selections_update_count(&self) -> usize {
3115        self.selections_update_count
3116    }
3117
3118    /// Returns a snapshot of underlying file.
3119    pub fn file(&self) -> Option<&Arc<dyn File>> {
3120        self.file.as_ref()
3121    }
3122
3123    /// Resolves the file path (relative to the worktree root) associated with the underlying file.
3124    pub fn resolve_file_path(&self, cx: &AppContext, include_root: bool) -> Option<PathBuf> {
3125        if let Some(file) = self.file() {
3126            if file.path().file_name().is_none() || include_root {
3127                Some(file.full_path(cx))
3128            } else {
3129                Some(file.path().to_path_buf())
3130            }
3131        } else {
3132            None
3133        }
3134    }
3135
3136    /// The number of times the underlying file was updated.
3137    pub fn file_update_count(&self) -> usize {
3138        self.file_update_count
3139    }
3140
3141    /// The number of times the git diff status was updated.
3142    pub fn git_diff_update_count(&self) -> usize {
3143        self.git_diff_update_count
3144    }
3145}
3146
3147fn indent_size_for_line(text: &text::BufferSnapshot, row: u32) -> IndentSize {
3148    indent_size_for_text(text.chars_at(Point::new(row, 0)))
3149}
3150
3151fn indent_size_for_text(text: impl Iterator<Item = char>) -> IndentSize {
3152    let mut result = IndentSize::spaces(0);
3153    for c in text {
3154        let kind = match c {
3155            ' ' => IndentKind::Space,
3156            '\t' => IndentKind::Tab,
3157            _ => break,
3158        };
3159        if result.len == 0 {
3160            result.kind = kind;
3161        }
3162        result.len += 1;
3163    }
3164    result
3165}
3166
3167impl Clone for BufferSnapshot {
3168    fn clone(&self) -> Self {
3169        Self {
3170            text: self.text.clone(),
3171            git_diff: self.git_diff.clone(),
3172            syntax: self.syntax.clone(),
3173            file: self.file.clone(),
3174            remote_selections: self.remote_selections.clone(),
3175            diagnostics: self.diagnostics.clone(),
3176            selections_update_count: self.selections_update_count,
3177            diagnostics_update_count: self.diagnostics_update_count,
3178            file_update_count: self.file_update_count,
3179            git_diff_update_count: self.git_diff_update_count,
3180            language: self.language.clone(),
3181            parse_count: self.parse_count,
3182        }
3183    }
3184}
3185
3186impl Deref for BufferSnapshot {
3187    type Target = text::BufferSnapshot;
3188
3189    fn deref(&self) -> &Self::Target {
3190        &self.text
3191    }
3192}
3193
3194unsafe impl<'a> Send for BufferChunks<'a> {}
3195
3196impl<'a> BufferChunks<'a> {
3197    pub(crate) fn new(
3198        text: &'a Rope,
3199        range: Range<usize>,
3200        syntax: Option<(SyntaxMapCaptures<'a>, Vec<HighlightMap>)>,
3201        diagnostic_endpoints: Vec<DiagnosticEndpoint>,
3202    ) -> Self {
3203        let mut highlights = None;
3204        if let Some((captures, highlight_maps)) = syntax {
3205            highlights = Some(BufferChunkHighlights {
3206                captures,
3207                next_capture: None,
3208                stack: Default::default(),
3209                highlight_maps,
3210            })
3211        }
3212
3213        let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
3214        let chunks = text.chunks_in_range(range.clone());
3215
3216        BufferChunks {
3217            range,
3218            chunks,
3219            diagnostic_endpoints,
3220            error_depth: 0,
3221            warning_depth: 0,
3222            information_depth: 0,
3223            hint_depth: 0,
3224            unnecessary_depth: 0,
3225            highlights,
3226        }
3227    }
3228
3229    /// Seeks to the given byte offset in the buffer.
3230    pub fn seek(&mut self, offset: usize) {
3231        self.range.start = offset;
3232        self.chunks.seek(self.range.start);
3233        if let Some(highlights) = self.highlights.as_mut() {
3234            highlights
3235                .stack
3236                .retain(|(end_offset, _)| *end_offset > offset);
3237            if let Some(capture) = &highlights.next_capture {
3238                if offset >= capture.node.start_byte() {
3239                    let next_capture_end = capture.node.end_byte();
3240                    if offset < next_capture_end {
3241                        highlights.stack.push((
3242                            next_capture_end,
3243                            highlights.highlight_maps[capture.grammar_index].get(capture.index),
3244                        ));
3245                    }
3246                    highlights.next_capture.take();
3247                }
3248            }
3249            highlights.captures.set_byte_range(self.range.clone());
3250        }
3251    }
3252
3253    /// The current byte offset in the buffer.
3254    pub fn offset(&self) -> usize {
3255        self.range.start
3256    }
3257
3258    fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
3259        let depth = match endpoint.severity {
3260            DiagnosticSeverity::ERROR => &mut self.error_depth,
3261            DiagnosticSeverity::WARNING => &mut self.warning_depth,
3262            DiagnosticSeverity::INFORMATION => &mut self.information_depth,
3263            DiagnosticSeverity::HINT => &mut self.hint_depth,
3264            _ => return,
3265        };
3266        if endpoint.is_start {
3267            *depth += 1;
3268        } else {
3269            *depth -= 1;
3270        }
3271
3272        if endpoint.is_unnecessary {
3273            if endpoint.is_start {
3274                self.unnecessary_depth += 1;
3275            } else {
3276                self.unnecessary_depth -= 1;
3277            }
3278        }
3279    }
3280
3281    fn current_diagnostic_severity(&self) -> Option<DiagnosticSeverity> {
3282        if self.error_depth > 0 {
3283            Some(DiagnosticSeverity::ERROR)
3284        } else if self.warning_depth > 0 {
3285            Some(DiagnosticSeverity::WARNING)
3286        } else if self.information_depth > 0 {
3287            Some(DiagnosticSeverity::INFORMATION)
3288        } else if self.hint_depth > 0 {
3289            Some(DiagnosticSeverity::HINT)
3290        } else {
3291            None
3292        }
3293    }
3294
3295    fn current_code_is_unnecessary(&self) -> bool {
3296        self.unnecessary_depth > 0
3297    }
3298}
3299
3300impl<'a> Iterator for BufferChunks<'a> {
3301    type Item = Chunk<'a>;
3302
3303    fn next(&mut self) -> Option<Self::Item> {
3304        let mut next_capture_start = usize::MAX;
3305        let mut next_diagnostic_endpoint = usize::MAX;
3306
3307        if let Some(highlights) = self.highlights.as_mut() {
3308            while let Some((parent_capture_end, _)) = highlights.stack.last() {
3309                if *parent_capture_end <= self.range.start {
3310                    highlights.stack.pop();
3311                } else {
3312                    break;
3313                }
3314            }
3315
3316            if highlights.next_capture.is_none() {
3317                highlights.next_capture = highlights.captures.next();
3318            }
3319
3320            while let Some(capture) = highlights.next_capture.as_ref() {
3321                if self.range.start < capture.node.start_byte() {
3322                    next_capture_start = capture.node.start_byte();
3323                    break;
3324                } else {
3325                    let highlight_id =
3326                        highlights.highlight_maps[capture.grammar_index].get(capture.index);
3327                    highlights
3328                        .stack
3329                        .push((capture.node.end_byte(), highlight_id));
3330                    highlights.next_capture = highlights.captures.next();
3331                }
3332            }
3333        }
3334
3335        while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
3336            if endpoint.offset <= self.range.start {
3337                self.update_diagnostic_depths(endpoint);
3338                self.diagnostic_endpoints.next();
3339            } else {
3340                next_diagnostic_endpoint = endpoint.offset;
3341                break;
3342            }
3343        }
3344
3345        if let Some(chunk) = self.chunks.peek() {
3346            let chunk_start = self.range.start;
3347            let mut chunk_end = (self.chunks.offset() + chunk.len())
3348                .min(next_capture_start)
3349                .min(next_diagnostic_endpoint);
3350            let mut highlight_id = None;
3351            if let Some(highlights) = self.highlights.as_ref() {
3352                if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
3353                    chunk_end = chunk_end.min(*parent_capture_end);
3354                    highlight_id = Some(*parent_highlight_id);
3355                }
3356            }
3357
3358            let slice =
3359                &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
3360            self.range.start = chunk_end;
3361            if self.range.start == self.chunks.offset() + chunk.len() {
3362                self.chunks.next().unwrap();
3363            }
3364
3365            Some(Chunk {
3366                text: slice,
3367                syntax_highlight_id: highlight_id,
3368                diagnostic_severity: self.current_diagnostic_severity(),
3369                is_unnecessary: self.current_code_is_unnecessary(),
3370                ..Default::default()
3371            })
3372        } else {
3373            None
3374        }
3375    }
3376}
3377
3378impl operation_queue::Operation for Operation {
3379    fn lamport_timestamp(&self) -> clock::Lamport {
3380        match self {
3381            Operation::Buffer(_) => {
3382                unreachable!("buffer operations should never be deferred at this layer")
3383            }
3384            Operation::UpdateDiagnostics {
3385                lamport_timestamp, ..
3386            }
3387            | Operation::UpdateSelections {
3388                lamport_timestamp, ..
3389            }
3390            | Operation::UpdateCompletionTriggers {
3391                lamport_timestamp, ..
3392            } => *lamport_timestamp,
3393        }
3394    }
3395}
3396
3397impl Default for Diagnostic {
3398    fn default() -> Self {
3399        Self {
3400            source: Default::default(),
3401            code: None,
3402            severity: DiagnosticSeverity::ERROR,
3403            message: Default::default(),
3404            group_id: 0,
3405            is_primary: false,
3406            is_disk_based: false,
3407            is_unnecessary: false,
3408        }
3409    }
3410}
3411
3412impl IndentSize {
3413    /// Returns an [IndentSize] representing the given spaces.
3414    pub fn spaces(len: u32) -> Self {
3415        Self {
3416            len,
3417            kind: IndentKind::Space,
3418        }
3419    }
3420
3421    /// Returns an [IndentSize] representing a tab.
3422    pub fn tab() -> Self {
3423        Self {
3424            len: 1,
3425            kind: IndentKind::Tab,
3426        }
3427    }
3428
3429    /// An iterator over the characters represented by this [IndentSize].
3430    pub fn chars(&self) -> impl Iterator<Item = char> {
3431        iter::repeat(self.char()).take(self.len as usize)
3432    }
3433
3434    /// The character representation of this [IndentSize].
3435    pub fn char(&self) -> char {
3436        match self.kind {
3437            IndentKind::Space => ' ',
3438            IndentKind::Tab => '\t',
3439        }
3440    }
3441
3442    /// Consumes the current [IndentSize] and returns a new one that has
3443    /// been shrunk or enlarged by the given size along the given direction.
3444    pub fn with_delta(mut self, direction: Ordering, size: IndentSize) -> Self {
3445        match direction {
3446            Ordering::Less => {
3447                if self.kind == size.kind && self.len >= size.len {
3448                    self.len -= size.len;
3449                }
3450            }
3451            Ordering::Equal => {}
3452            Ordering::Greater => {
3453                if self.len == 0 {
3454                    self = size;
3455                } else if self.kind == size.kind {
3456                    self.len += size.len;
3457                }
3458            }
3459        }
3460        self
3461    }
3462}
3463
3464#[cfg(any(test, feature = "test-support"))]
3465pub struct TestFile {
3466    pub path: Arc<Path>,
3467    pub root_name: String,
3468}
3469
3470#[cfg(any(test, feature = "test-support"))]
3471impl File for TestFile {
3472    fn path(&self) -> &Arc<Path> {
3473        &self.path
3474    }
3475
3476    fn full_path(&self, _: &gpui::AppContext) -> PathBuf {
3477        PathBuf::from(&self.root_name).join(self.path.as_ref())
3478    }
3479
3480    fn as_local(&self) -> Option<&dyn LocalFile> {
3481        None
3482    }
3483
3484    fn mtime(&self) -> Option<SystemTime> {
3485        unimplemented!()
3486    }
3487
3488    fn file_name<'a>(&'a self, _: &'a gpui::AppContext) -> &'a std::ffi::OsStr {
3489        self.path().file_name().unwrap_or(self.root_name.as_ref())
3490    }
3491
3492    fn worktree_id(&self) -> usize {
3493        0
3494    }
3495
3496    fn is_deleted(&self) -> bool {
3497        unimplemented!()
3498    }
3499
3500    fn as_any(&self) -> &dyn std::any::Any {
3501        unimplemented!()
3502    }
3503
3504    fn to_proto(&self) -> rpc::proto::File {
3505        unimplemented!()
3506    }
3507
3508    fn is_private(&self) -> bool {
3509        false
3510    }
3511}
3512
3513pub(crate) fn contiguous_ranges(
3514    values: impl Iterator<Item = u32>,
3515    max_len: usize,
3516) -> impl Iterator<Item = Range<u32>> {
3517    let mut values = values;
3518    let mut current_range: Option<Range<u32>> = None;
3519    std::iter::from_fn(move || loop {
3520        if let Some(value) = values.next() {
3521            if let Some(range) = &mut current_range {
3522                if value == range.end && range.len() < max_len {
3523                    range.end += 1;
3524                    continue;
3525                }
3526            }
3527
3528            let prev_range = current_range.clone();
3529            current_range = Some(value..(value + 1));
3530            if prev_range.is_some() {
3531                return prev_range;
3532            }
3533        } else {
3534            return current_range.take();
3535        }
3536    })
3537}
3538
3539/// Returns the [CharKind] for the given character. When a scope is provided,
3540/// the function checks if the character is considered a word character
3541/// based on the language scope's word character settings.
3542pub fn char_kind(scope: &Option<LanguageScope>, c: char) -> CharKind {
3543    if c.is_whitespace() {
3544        return CharKind::Whitespace;
3545    } else if c.is_alphanumeric() || c == '_' {
3546        return CharKind::Word;
3547    }
3548
3549    if let Some(scope) = scope {
3550        if let Some(characters) = scope.word_characters() {
3551            if characters.contains(&c) {
3552                return CharKind::Word;
3553            }
3554        }
3555    }
3556
3557    CharKind::Punctuation
3558}
3559
3560/// Find all of the ranges of whitespace that occur at the ends of lines
3561/// in the given rope.
3562///
3563/// This could also be done with a regex search, but this implementation
3564/// avoids copying text.
3565pub fn trailing_whitespace_ranges(rope: &Rope) -> Vec<Range<usize>> {
3566    let mut ranges = Vec::new();
3567
3568    let mut offset = 0;
3569    let mut prev_chunk_trailing_whitespace_range = 0..0;
3570    for chunk in rope.chunks() {
3571        let mut prev_line_trailing_whitespace_range = 0..0;
3572        for (i, line) in chunk.split('\n').enumerate() {
3573            let line_end_offset = offset + line.len();
3574            let trimmed_line_len = line.trim_end_matches(|c| matches!(c, ' ' | '\t')).len();
3575            let mut trailing_whitespace_range = (offset + trimmed_line_len)..line_end_offset;
3576
3577            if i == 0 && trimmed_line_len == 0 {
3578                trailing_whitespace_range.start = prev_chunk_trailing_whitespace_range.start;
3579            }
3580            if !prev_line_trailing_whitespace_range.is_empty() {
3581                ranges.push(prev_line_trailing_whitespace_range);
3582            }
3583
3584            offset = line_end_offset + 1;
3585            prev_line_trailing_whitespace_range = trailing_whitespace_range;
3586        }
3587
3588        offset -= 1;
3589        prev_chunk_trailing_whitespace_range = prev_line_trailing_whitespace_range;
3590    }
3591
3592    if !prev_chunk_trailing_whitespace_range.is_empty() {
3593        ranges.push(prev_chunk_trailing_whitespace_range);
3594    }
3595
3596    ranges
3597}