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