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