buffer.rs

   1pub use crate::{
   2    diagnostic_set::DiagnosticSet,
   3    highlight_map::{HighlightId, HighlightMap},
   4    proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, PLAIN_TEXT,
   5};
   6use crate::{
   7    diagnostic_set::{DiagnosticEntry, DiagnosticGroup},
   8    outline::OutlineItem,
   9    syntax_map::{
  10        SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures, SyntaxSnapshot, ToTreeSitterPoint,
  11    },
  12    CodeLabel, LanguageScope, Outline,
  13};
  14use anyhow::{anyhow, Result};
  15use clock::ReplicaId;
  16use fs::LineEnding;
  17use futures::FutureExt as _;
  18use gpui::{fonts::HighlightStyle, AppContext, Entity, ModelContext, Task};
  19use parking_lot::Mutex;
  20use settings::Settings;
  21use similar::{ChangeTag, TextDiff};
  22use smol::future::yield_now;
  23use std::{
  24    any::Any,
  25    cmp::{self, Ordering},
  26    collections::BTreeMap,
  27    ffi::OsStr,
  28    future::Future,
  29    iter::{self, Iterator, Peekable},
  30    mem,
  31    ops::{Deref, Range},
  32    path::{Path, PathBuf},
  33    str,
  34    sync::Arc,
  35    time::{Duration, Instant, SystemTime, UNIX_EPOCH},
  36    vec,
  37};
  38use sum_tree::TreeMap;
  39use text::operation_queue::OperationQueue;
  40pub use text::{Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, Operation as _, *};
  41use theme::SyntaxTheme;
  42#[cfg(any(test, feature = "test-support"))]
  43use util::RandomCharIter;
  44use util::{RangeExt, TryFutureExt as _};
  45
  46#[cfg(any(test, feature = "test-support"))]
  47pub use {tree_sitter_rust, tree_sitter_typescript};
  48
  49pub use lsp::DiagnosticSeverity;
  50
  51struct GitDiffStatus {
  52    diff: git::diff::BufferDiff,
  53    update_in_progress: bool,
  54    update_requested: bool,
  55}
  56
  57pub struct Buffer {
  58    text: TextBuffer,
  59    diff_base: Option<String>,
  60    git_diff_status: GitDiffStatus,
  61    file: Option<Arc<dyn File>>,
  62    saved_version: clock::Global,
  63    saved_version_fingerprint: RopeFingerprint,
  64    saved_mtime: SystemTime,
  65    transaction_depth: usize,
  66    was_dirty_before_starting_transaction: Option<bool>,
  67    language: Option<Arc<Language>>,
  68    autoindent_requests: Vec<Arc<AutoindentRequest>>,
  69    pending_autoindent: Option<Task<()>>,
  70    sync_parse_timeout: Duration,
  71    syntax_map: Mutex<SyntaxMap>,
  72    parsing_in_background: bool,
  73    parse_count: usize,
  74    diagnostics: DiagnosticSet,
  75    remote_selections: TreeMap<ReplicaId, SelectionSet>,
  76    selections_update_count: usize,
  77    diagnostics_update_count: usize,
  78    diagnostics_timestamp: clock::Lamport,
  79    file_update_count: usize,
  80    git_diff_update_count: usize,
  81    completion_triggers: Vec<String>,
  82    completion_triggers_timestamp: clock::Lamport,
  83    deferred_ops: OperationQueue<Operation>,
  84}
  85
  86pub struct BufferSnapshot {
  87    text: text::BufferSnapshot,
  88    pub git_diff: git::diff::BufferDiff,
  89    pub(crate) syntax: SyntaxSnapshot,
  90    file: Option<Arc<dyn File>>,
  91    diagnostics: DiagnosticSet,
  92    diagnostics_update_count: usize,
  93    file_update_count: usize,
  94    git_diff_update_count: usize,
  95    remote_selections: TreeMap<ReplicaId, SelectionSet>,
  96    selections_update_count: usize,
  97    language: Option<Arc<Language>>,
  98    parse_count: usize,
  99}
 100
 101#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
 102pub struct IndentSize {
 103    pub len: u32,
 104    pub kind: IndentKind,
 105}
 106
 107#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
 108pub enum IndentKind {
 109    #[default]
 110    Space,
 111    Tab,
 112}
 113
 114#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
 115pub enum CursorShape {
 116    #[default]
 117    Bar,
 118    Block,
 119    Underscore,
 120    Hollow,
 121}
 122
 123#[derive(Clone, Debug)]
 124struct SelectionSet {
 125    line_mode: bool,
 126    cursor_shape: CursorShape,
 127    selections: Arc<[Selection<Anchor>]>,
 128    lamport_timestamp: clock::Lamport,
 129}
 130
 131#[derive(Clone, Debug, PartialEq, Eq)]
 132pub struct GroupId {
 133    source: Arc<str>,
 134    id: usize,
 135}
 136
 137#[derive(Clone, Debug, PartialEq, Eq)]
 138pub struct Diagnostic {
 139    pub code: Option<String>,
 140    pub severity: DiagnosticSeverity,
 141    pub message: String,
 142    pub group_id: usize,
 143    pub is_valid: bool,
 144    pub is_primary: bool,
 145    pub is_disk_based: bool,
 146    pub is_unnecessary: bool,
 147}
 148
 149#[derive(Clone, Debug)]
 150pub struct Completion {
 151    pub old_range: Range<Anchor>,
 152    pub new_text: String,
 153    pub label: CodeLabel,
 154    pub lsp_completion: lsp::CompletionItem,
 155}
 156
 157#[derive(Clone, Debug)]
 158pub struct CodeAction {
 159    pub server_id: usize,
 160    pub range: Range<Anchor>,
 161    pub lsp_action: lsp::CodeAction,
 162}
 163
 164#[derive(Clone, Debug, PartialEq, Eq)]
 165pub enum Operation {
 166    Buffer(text::Operation),
 167    UpdateDiagnostics {
 168        diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
 169        lamport_timestamp: clock::Lamport,
 170    },
 171    UpdateSelections {
 172        selections: Arc<[Selection<Anchor>]>,
 173        lamport_timestamp: clock::Lamport,
 174        line_mode: bool,
 175        cursor_shape: CursorShape,
 176    },
 177    UpdateCompletionTriggers {
 178        triggers: Vec<String>,
 179        lamport_timestamp: clock::Lamport,
 180    },
 181}
 182
 183#[derive(Clone, Debug, PartialEq, Eq)]
 184pub enum Event {
 185    Operation(Operation),
 186    Edited,
 187    DirtyChanged,
 188    Saved,
 189    FileHandleChanged,
 190    Reloaded,
 191    LanguageChanged,
 192    Reparsed,
 193    DiagnosticsUpdated,
 194    Closed,
 195}
 196
 197pub trait File: Send + Sync {
 198    fn as_local(&self) -> Option<&dyn LocalFile>;
 199
 200    fn is_local(&self) -> bool {
 201        self.as_local().is_some()
 202    }
 203
 204    fn mtime(&self) -> SystemTime;
 205
 206    /// Returns the path of this file relative to the worktree's root directory.
 207    fn path(&self) -> &Arc<Path>;
 208
 209    /// Returns the path of this file relative to the worktree's parent directory (this means it
 210    /// includes the name of the worktree's root folder).
 211    fn full_path(&self, cx: &AppContext) -> PathBuf;
 212
 213    /// Returns the last component of this handle's absolute path. If this handle refers to the root
 214    /// of its worktree, then this method will return the name of the worktree itself.
 215    fn file_name<'a>(&'a self, cx: &'a AppContext) -> &'a OsStr;
 216
 217    fn is_deleted(&self) -> bool;
 218
 219    fn as_any(&self) -> &dyn Any;
 220
 221    fn to_proto(&self) -> rpc::proto::File;
 222}
 223
 224pub trait LocalFile: File {
 225    /// Returns the absolute path of this file.
 226    fn abs_path(&self, cx: &AppContext) -> PathBuf;
 227
 228    fn load(&self, cx: &AppContext) -> Task<Result<String>>;
 229
 230    fn buffer_reloaded(
 231        &self,
 232        buffer_id: u64,
 233        version: &clock::Global,
 234        fingerprint: RopeFingerprint,
 235        line_ending: LineEnding,
 236        mtime: SystemTime,
 237        cx: &mut AppContext,
 238    );
 239}
 240
 241#[derive(Clone, Debug)]
 242pub enum AutoindentMode {
 243    /// Indent each line of inserted text.
 244    EachLine,
 245    /// Apply the same indentation adjustment to all of the lines
 246    /// in a given insertion.
 247    Block {
 248        /// The original indentation level of the first line of each
 249        /// insertion, if it has been copied.
 250        original_indent_columns: Vec<u32>,
 251    },
 252}
 253
 254#[derive(Clone)]
 255struct AutoindentRequest {
 256    before_edit: BufferSnapshot,
 257    entries: Vec<AutoindentRequestEntry>,
 258    is_block_mode: bool,
 259}
 260
 261#[derive(Clone)]
 262struct AutoindentRequestEntry {
 263    /// A range of the buffer whose indentation should be adjusted.
 264    range: Range<Anchor>,
 265    /// Whether or not these lines should be considered brand new, for the
 266    /// purpose of auto-indent. When text is not new, its indentation will
 267    /// only be adjusted if the suggested indentation level has *changed*
 268    /// since the edit was made.
 269    first_line_is_new: bool,
 270    indent_size: IndentSize,
 271    original_indent_column: Option<u32>,
 272}
 273
 274#[derive(Debug)]
 275struct IndentSuggestion {
 276    basis_row: u32,
 277    delta: Ordering,
 278    within_error: bool,
 279}
 280
 281struct BufferChunkHighlights<'a> {
 282    captures: SyntaxMapCaptures<'a>,
 283    next_capture: Option<SyntaxMapCapture<'a>>,
 284    stack: Vec<(usize, HighlightId)>,
 285    highlight_maps: Vec<HighlightMap>,
 286}
 287
 288pub struct BufferChunks<'a> {
 289    range: Range<usize>,
 290    chunks: text::Chunks<'a>,
 291    diagnostic_endpoints: Peekable<vec::IntoIter<DiagnosticEndpoint>>,
 292    error_depth: usize,
 293    warning_depth: usize,
 294    information_depth: usize,
 295    hint_depth: usize,
 296    unnecessary_depth: usize,
 297    highlights: Option<BufferChunkHighlights<'a>>,
 298}
 299
 300#[derive(Clone, Copy, Debug, Default)]
 301pub struct Chunk<'a> {
 302    pub text: &'a str,
 303    pub syntax_highlight_id: Option<HighlightId>,
 304    pub highlight_style: Option<HighlightStyle>,
 305    pub diagnostic_severity: Option<DiagnosticSeverity>,
 306    pub is_unnecessary: bool,
 307}
 308
 309pub struct Diff {
 310    pub(crate) base_version: clock::Global,
 311    line_ending: LineEnding,
 312    edits: Vec<(Range<usize>, Arc<str>)>,
 313}
 314
 315#[derive(Clone, Copy)]
 316pub(crate) struct DiagnosticEndpoint {
 317    offset: usize,
 318    is_start: bool,
 319    severity: DiagnosticSeverity,
 320    is_unnecessary: bool,
 321}
 322
 323#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
 324pub enum CharKind {
 325    Punctuation,
 326    Whitespace,
 327    Word,
 328}
 329
 330impl CharKind {
 331    pub fn coerce_punctuation(self, treat_punctuation_as_word: bool) -> Self {
 332        if treat_punctuation_as_word && self == CharKind::Punctuation {
 333            CharKind::Word
 334        } else {
 335            self
 336        }
 337    }
 338}
 339
 340impl Buffer {
 341    pub fn new<T: Into<String>>(
 342        replica_id: ReplicaId,
 343        base_text: T,
 344        cx: &mut ModelContext<Self>,
 345    ) -> Self {
 346        Self::build(
 347            TextBuffer::new(replica_id, cx.model_id() as u64, base_text.into()),
 348            None,
 349            None,
 350        )
 351    }
 352
 353    pub fn from_file<T: Into<String>>(
 354        replica_id: ReplicaId,
 355        base_text: T,
 356        diff_base: Option<T>,
 357        file: Arc<dyn File>,
 358        cx: &mut ModelContext<Self>,
 359    ) -> Self {
 360        Self::build(
 361            TextBuffer::new(replica_id, cx.model_id() as u64, base_text.into()),
 362            diff_base.map(|h| h.into().into_boxed_str().into()),
 363            Some(file),
 364        )
 365    }
 366
 367    pub fn from_proto(
 368        replica_id: ReplicaId,
 369        message: proto::BufferState,
 370        file: Option<Arc<dyn File>>,
 371    ) -> Result<Self> {
 372        let buffer = TextBuffer::new(replica_id, message.id, message.base_text);
 373        let mut this = Self::build(
 374            buffer,
 375            message.diff_base.map(|text| text.into_boxed_str().into()),
 376            file,
 377        );
 378        this.text.set_line_ending(proto::deserialize_line_ending(
 379            rpc::proto::LineEnding::from_i32(message.line_ending)
 380                .ok_or_else(|| anyhow!("missing line_ending"))?,
 381        ));
 382        this.saved_version = proto::deserialize_version(&message.saved_version);
 383        this.saved_version_fingerprint =
 384            proto::deserialize_fingerprint(&message.saved_version_fingerprint)?;
 385        this.saved_mtime = message
 386            .saved_mtime
 387            .ok_or_else(|| anyhow!("invalid saved_mtime"))?
 388            .into();
 389        Ok(this)
 390    }
 391
 392    pub fn to_proto(&self) -> proto::BufferState {
 393        proto::BufferState {
 394            id: self.remote_id(),
 395            file: self.file.as_ref().map(|f| f.to_proto()),
 396            base_text: self.base_text().to_string(),
 397            diff_base: self.diff_base.as_ref().map(|h| h.to_string()),
 398            line_ending: proto::serialize_line_ending(self.line_ending()) as i32,
 399            saved_version: proto::serialize_version(&self.saved_version),
 400            saved_version_fingerprint: proto::serialize_fingerprint(self.saved_version_fingerprint),
 401            saved_mtime: Some(self.saved_mtime.into()),
 402        }
 403    }
 404
 405    pub fn serialize_ops(
 406        &self,
 407        since: Option<clock::Global>,
 408        cx: &AppContext,
 409    ) -> Task<Vec<proto::Operation>> {
 410        let mut operations = Vec::new();
 411        operations.extend(self.deferred_ops.iter().map(proto::serialize_operation));
 412        operations.extend(self.remote_selections.iter().map(|(_, set)| {
 413            proto::serialize_operation(&Operation::UpdateSelections {
 414                selections: set.selections.clone(),
 415                lamport_timestamp: set.lamport_timestamp,
 416                line_mode: set.line_mode,
 417                cursor_shape: set.cursor_shape,
 418            })
 419        }));
 420        operations.push(proto::serialize_operation(&Operation::UpdateDiagnostics {
 421            diagnostics: self.diagnostics.iter().cloned().collect(),
 422            lamport_timestamp: self.diagnostics_timestamp,
 423        }));
 424        operations.push(proto::serialize_operation(
 425            &Operation::UpdateCompletionTriggers {
 426                triggers: self.completion_triggers.clone(),
 427                lamport_timestamp: self.completion_triggers_timestamp,
 428            },
 429        ));
 430
 431        let text_operations = self.text.operations().clone();
 432        cx.background().spawn(async move {
 433            let since = since.unwrap_or_default();
 434            operations.extend(
 435                text_operations
 436                    .iter()
 437                    .filter(|(_, op)| !since.observed(op.local_timestamp()))
 438                    .map(|(_, op)| proto::serialize_operation(&Operation::Buffer(op.clone()))),
 439            );
 440            operations.sort_unstable_by_key(proto::lamport_timestamp_for_operation);
 441            operations
 442        })
 443    }
 444
 445    pub fn with_language(mut self, language: Arc<Language>, cx: &mut ModelContext<Self>) -> Self {
 446        self.set_language(Some(language), cx);
 447        self
 448    }
 449
 450    fn build(buffer: TextBuffer, diff_base: Option<String>, file: Option<Arc<dyn File>>) -> Self {
 451        let saved_mtime = if let Some(file) = file.as_ref() {
 452            file.mtime()
 453        } else {
 454            UNIX_EPOCH
 455        };
 456
 457        Self {
 458            saved_mtime,
 459            saved_version: buffer.version(),
 460            saved_version_fingerprint: buffer.as_rope().fingerprint(),
 461            transaction_depth: 0,
 462            was_dirty_before_starting_transaction: None,
 463            text: buffer,
 464            diff_base,
 465            git_diff_status: GitDiffStatus {
 466                diff: git::diff::BufferDiff::new(),
 467                update_in_progress: false,
 468                update_requested: false,
 469            },
 470            file,
 471            syntax_map: Mutex::new(SyntaxMap::new()),
 472            parsing_in_background: false,
 473            parse_count: 0,
 474            sync_parse_timeout: Duration::from_millis(1),
 475            autoindent_requests: Default::default(),
 476            pending_autoindent: Default::default(),
 477            language: None,
 478            remote_selections: Default::default(),
 479            selections_update_count: 0,
 480            diagnostics: Default::default(),
 481            diagnostics_update_count: 0,
 482            diagnostics_timestamp: Default::default(),
 483            file_update_count: 0,
 484            git_diff_update_count: 0,
 485            completion_triggers: Default::default(),
 486            completion_triggers_timestamp: Default::default(),
 487            deferred_ops: OperationQueue::new(),
 488        }
 489    }
 490
 491    pub fn snapshot(&self) -> BufferSnapshot {
 492        let text = self.text.snapshot();
 493        let mut syntax_map = self.syntax_map.lock();
 494        syntax_map.interpolate(&text);
 495        let syntax = syntax_map.snapshot();
 496
 497        BufferSnapshot {
 498            text,
 499            syntax,
 500            git_diff: self.git_diff_status.diff.clone(),
 501            file: self.file.clone(),
 502            remote_selections: self.remote_selections.clone(),
 503            diagnostics: self.diagnostics.clone(),
 504            diagnostics_update_count: self.diagnostics_update_count,
 505            file_update_count: self.file_update_count,
 506            git_diff_update_count: self.git_diff_update_count,
 507            language: self.language.clone(),
 508            parse_count: self.parse_count,
 509            selections_update_count: self.selections_update_count,
 510        }
 511    }
 512
 513    pub fn as_text_snapshot(&self) -> &text::BufferSnapshot {
 514        &self.text
 515    }
 516
 517    pub fn text_snapshot(&self) -> text::BufferSnapshot {
 518        self.text.snapshot()
 519    }
 520
 521    pub fn file(&self) -> Option<&Arc<dyn File>> {
 522        self.file.as_ref()
 523    }
 524
 525    pub fn saved_version(&self) -> &clock::Global {
 526        &self.saved_version
 527    }
 528
 529    pub fn saved_version_fingerprint(&self) -> RopeFingerprint {
 530        self.saved_version_fingerprint
 531    }
 532
 533    pub fn saved_mtime(&self) -> SystemTime {
 534        self.saved_mtime
 535    }
 536
 537    pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
 538        self.syntax_map.lock().clear();
 539        self.language = language;
 540        self.reparse(cx);
 541        cx.emit(Event::LanguageChanged);
 542    }
 543
 544    pub fn set_language_registry(&mut self, language_registry: Arc<LanguageRegistry>) {
 545        self.syntax_map
 546            .lock()
 547            .set_language_registry(language_registry);
 548    }
 549
 550    pub fn did_save(
 551        &mut self,
 552        version: clock::Global,
 553        fingerprint: RopeFingerprint,
 554        mtime: SystemTime,
 555        cx: &mut ModelContext<Self>,
 556    ) {
 557        self.saved_version = version;
 558        self.saved_version_fingerprint = fingerprint;
 559        self.saved_mtime = mtime;
 560        cx.emit(Event::Saved);
 561        cx.notify();
 562    }
 563
 564    pub fn reload(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<Option<Transaction>>> {
 565        cx.spawn(|this, mut cx| async move {
 566            if let Some((new_mtime, new_text)) = this.read_with(&cx, |this, cx| {
 567                let file = this.file.as_ref()?.as_local()?;
 568                Some((file.mtime(), file.load(cx)))
 569            }) {
 570                let new_text = new_text.await?;
 571                let diff = this
 572                    .read_with(&cx, |this, cx| this.diff(new_text, cx))
 573                    .await;
 574                this.update(&mut cx, |this, cx| {
 575                    if this.version() == diff.base_version {
 576                        this.finalize_last_transaction();
 577                        this.apply_diff(diff, cx);
 578                        if let Some(transaction) = this.finalize_last_transaction().cloned() {
 579                            this.did_reload(
 580                                this.version(),
 581                                this.as_rope().fingerprint(),
 582                                this.line_ending(),
 583                                new_mtime,
 584                                cx,
 585                            );
 586                            return Ok(Some(transaction));
 587                        }
 588                    }
 589                    Ok(None)
 590                })
 591            } else {
 592                Ok(None)
 593            }
 594        })
 595    }
 596
 597    pub fn did_reload(
 598        &mut self,
 599        version: clock::Global,
 600        fingerprint: RopeFingerprint,
 601        line_ending: LineEnding,
 602        mtime: SystemTime,
 603        cx: &mut ModelContext<Self>,
 604    ) {
 605        self.saved_version = version;
 606        self.saved_version_fingerprint = fingerprint;
 607        self.text.set_line_ending(line_ending);
 608        self.saved_mtime = mtime;
 609        if let Some(file) = self.file.as_ref().and_then(|f| f.as_local()) {
 610            file.buffer_reloaded(
 611                self.remote_id(),
 612                &self.saved_version,
 613                self.saved_version_fingerprint,
 614                self.line_ending(),
 615                self.saved_mtime,
 616                cx,
 617            );
 618        }
 619        self.git_diff_recalc(cx);
 620        cx.emit(Event::Reloaded);
 621        cx.notify();
 622    }
 623
 624    pub fn file_updated(
 625        &mut self,
 626        new_file: Arc<dyn File>,
 627        cx: &mut ModelContext<Self>,
 628    ) -> Task<()> {
 629        let mut file_changed = false;
 630        let mut task = Task::ready(());
 631
 632        if let Some(old_file) = self.file.as_ref() {
 633            if new_file.path() != old_file.path() {
 634                file_changed = true;
 635            }
 636
 637            if new_file.is_deleted() {
 638                if !old_file.is_deleted() {
 639                    file_changed = true;
 640                    if !self.is_dirty() {
 641                        cx.emit(Event::DirtyChanged);
 642                    }
 643                }
 644            } else {
 645                let new_mtime = new_file.mtime();
 646                if new_mtime != old_file.mtime() {
 647                    file_changed = true;
 648
 649                    if !self.is_dirty() {
 650                        let reload = self.reload(cx).log_err().map(drop);
 651                        task = cx.foreground().spawn(reload);
 652                    }
 653                }
 654            }
 655        } else {
 656            file_changed = true;
 657        };
 658
 659        if file_changed {
 660            self.file_update_count += 1;
 661            cx.emit(Event::FileHandleChanged);
 662            cx.notify();
 663        }
 664        self.file = Some(new_file);
 665        task
 666    }
 667
 668    pub fn diff_base(&self) -> Option<&str> {
 669        self.diff_base.as_deref()
 670    }
 671
 672    pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
 673        self.diff_base = diff_base;
 674        self.git_diff_recalc(cx);
 675    }
 676
 677    pub fn needs_git_diff_recalc(&self) -> bool {
 678        self.git_diff_status.diff.needs_update(self)
 679    }
 680
 681    pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) {
 682        if self.git_diff_status.update_in_progress {
 683            self.git_diff_status.update_requested = true;
 684            return;
 685        }
 686
 687        if let Some(diff_base) = &self.diff_base {
 688            let snapshot = self.snapshot();
 689            let diff_base = diff_base.clone();
 690
 691            let mut diff = self.git_diff_status.diff.clone();
 692            let diff = cx.background().spawn(async move {
 693                diff.update(&diff_base, &snapshot).await;
 694                diff
 695            });
 696
 697            cx.spawn_weak(|this, mut cx| async move {
 698                let buffer_diff = diff.await;
 699                if let Some(this) = this.upgrade(&cx) {
 700                    this.update(&mut cx, |this, cx| {
 701                        this.git_diff_status.diff = buffer_diff;
 702                        this.git_diff_update_count += 1;
 703                        cx.notify();
 704
 705                        this.git_diff_status.update_in_progress = false;
 706                        if this.git_diff_status.update_requested {
 707                            this.git_diff_recalc(cx);
 708                        }
 709                    })
 710                }
 711            })
 712            .detach()
 713        } else {
 714            let snapshot = self.snapshot();
 715            self.git_diff_status.diff.clear(&snapshot);
 716            self.git_diff_update_count += 1;
 717            cx.notify();
 718        }
 719    }
 720
 721    pub fn close(&mut self, cx: &mut ModelContext<Self>) {
 722        cx.emit(Event::Closed);
 723    }
 724
 725    pub fn language(&self) -> Option<&Arc<Language>> {
 726        self.language.as_ref()
 727    }
 728
 729    pub fn language_at<D: ToOffset>(&self, position: D) -> Option<Arc<Language>> {
 730        let offset = position.to_offset(self);
 731        self.syntax_map
 732            .lock()
 733            .layers_for_range(offset..offset, &self.text)
 734            .last()
 735            .map(|info| info.language.clone())
 736            .or_else(|| self.language.clone())
 737    }
 738
 739    pub fn parse_count(&self) -> usize {
 740        self.parse_count
 741    }
 742
 743    pub fn selections_update_count(&self) -> usize {
 744        self.selections_update_count
 745    }
 746
 747    pub fn diagnostics_update_count(&self) -> usize {
 748        self.diagnostics_update_count
 749    }
 750
 751    pub fn file_update_count(&self) -> usize {
 752        self.file_update_count
 753    }
 754
 755    pub fn git_diff_update_count(&self) -> usize {
 756        self.git_diff_update_count
 757    }
 758
 759    #[cfg(any(test, feature = "test-support"))]
 760    pub fn is_parsing(&self) -> bool {
 761        self.parsing_in_background
 762    }
 763
 764    pub fn contains_unknown_injections(&self) -> bool {
 765        self.syntax_map.lock().contains_unknown_injections()
 766    }
 767
 768    #[cfg(test)]
 769    pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
 770        self.sync_parse_timeout = timeout;
 771    }
 772
 773    /// Called after an edit to synchronize the buffer's main parse tree with
 774    /// the buffer's new underlying state.
 775    ///
 776    /// Locks the syntax map and interpolates the edits since the last reparse
 777    /// into the foreground syntax tree.
 778    ///
 779    /// Then takes a stable snapshot of the syntax map before unlocking it.
 780    /// The snapshot with the interpolated edits is sent to a background thread,
 781    /// where we ask Tree-sitter to perform an incremental parse.
 782    ///
 783    /// Meanwhile, in the foreground, we block the main thread for up to 1ms
 784    /// waiting on the parse to complete. As soon as it completes, we proceed
 785    /// synchronously, unless a 1ms timeout elapses.
 786    ///
 787    /// If we time out waiting on the parse, we spawn a second task waiting
 788    /// until the parse does complete and return with the interpolated tree still
 789    /// in the foreground. When the background parse completes, call back into
 790    /// the main thread and assign the foreground parse state.
 791    ///
 792    /// If the buffer or grammar changed since the start of the background parse,
 793    /// initiate an additional reparse recursively. To avoid concurrent parses
 794    /// for the same buffer, we only initiate a new parse if we are not already
 795    /// parsing in the background.
 796    pub fn reparse(&mut self, cx: &mut ModelContext<Self>) {
 797        if self.parsing_in_background {
 798            return;
 799        }
 800        let language = if let Some(language) = self.language.clone() {
 801            language
 802        } else {
 803            return;
 804        };
 805
 806        let text = self.text_snapshot();
 807        let parsed_version = self.version();
 808
 809        let mut syntax_map = self.syntax_map.lock();
 810        syntax_map.interpolate(&text);
 811        let language_registry = syntax_map.language_registry();
 812        let mut syntax_snapshot = syntax_map.snapshot();
 813        drop(syntax_map);
 814
 815        let parse_task = cx.background().spawn({
 816            let language = language.clone();
 817            let language_registry = language_registry.clone();
 818            async move {
 819                syntax_snapshot.reparse(&text, language_registry, language);
 820                syntax_snapshot
 821            }
 822        });
 823
 824        match cx
 825            .background()
 826            .block_with_timeout(self.sync_parse_timeout, parse_task)
 827        {
 828            Ok(new_syntax_snapshot) => {
 829                self.did_finish_parsing(new_syntax_snapshot, cx);
 830                return;
 831            }
 832            Err(parse_task) => {
 833                self.parsing_in_background = true;
 834                cx.spawn(move |this, mut cx| async move {
 835                    let new_syntax_map = parse_task.await;
 836                    this.update(&mut cx, move |this, cx| {
 837                        let grammar_changed =
 838                            this.language.as_ref().map_or(true, |current_language| {
 839                                !Arc::ptr_eq(&language, current_language)
 840                            });
 841                        let language_registry_changed = new_syntax_map
 842                            .contains_unknown_injections()
 843                            && language_registry.map_or(false, |registry| {
 844                                registry.version() != new_syntax_map.language_registry_version()
 845                            });
 846                        let parse_again = language_registry_changed
 847                            || grammar_changed
 848                            || this.version.changed_since(&parsed_version);
 849                        this.did_finish_parsing(new_syntax_map, cx);
 850                        this.parsing_in_background = false;
 851                        if parse_again {
 852                            this.reparse(cx);
 853                        }
 854                    });
 855                })
 856                .detach();
 857            }
 858        }
 859    }
 860
 861    fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut ModelContext<Self>) {
 862        self.parse_count += 1;
 863        self.syntax_map.lock().did_parse(syntax_snapshot);
 864        self.request_autoindent(cx);
 865        cx.emit(Event::Reparsed);
 866        cx.notify();
 867    }
 868
 869    pub fn update_diagnostics(&mut self, diagnostics: DiagnosticSet, cx: &mut ModelContext<Self>) {
 870        let lamport_timestamp = self.text.lamport_clock.tick();
 871        let op = Operation::UpdateDiagnostics {
 872            diagnostics: diagnostics.iter().cloned().collect(),
 873            lamport_timestamp,
 874        };
 875        self.apply_diagnostic_update(diagnostics, lamport_timestamp, cx);
 876        self.send_operation(op, cx);
 877    }
 878
 879    fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
 880        if let Some(indent_sizes) = self.compute_autoindents() {
 881            let indent_sizes = cx.background().spawn(indent_sizes);
 882            match cx
 883                .background()
 884                .block_with_timeout(Duration::from_micros(500), indent_sizes)
 885            {
 886                Ok(indent_sizes) => self.apply_autoindents(indent_sizes, cx),
 887                Err(indent_sizes) => {
 888                    self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
 889                        let indent_sizes = indent_sizes.await;
 890                        this.update(&mut cx, |this, cx| {
 891                            this.apply_autoindents(indent_sizes, cx);
 892                        });
 893                    }));
 894                }
 895            }
 896        } else {
 897            self.autoindent_requests.clear();
 898        }
 899    }
 900
 901    fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>>> {
 902        let max_rows_between_yields = 100;
 903        let snapshot = self.snapshot();
 904        if snapshot.syntax.is_empty() || self.autoindent_requests.is_empty() {
 905            return None;
 906        }
 907
 908        let autoindent_requests = self.autoindent_requests.clone();
 909        Some(async move {
 910            let mut indent_sizes = BTreeMap::new();
 911            for request in autoindent_requests {
 912                // Resolve each edited range to its row in the current buffer and in the
 913                // buffer before this batch of edits.
 914                let mut row_ranges = Vec::new();
 915                let mut old_to_new_rows = BTreeMap::new();
 916                let mut language_indent_sizes_by_new_row = Vec::new();
 917                for entry in &request.entries {
 918                    let position = entry.range.start;
 919                    let new_row = position.to_point(&snapshot).row;
 920                    let new_end_row = entry.range.end.to_point(&snapshot).row + 1;
 921                    language_indent_sizes_by_new_row.push((new_row, entry.indent_size));
 922
 923                    if !entry.first_line_is_new {
 924                        let old_row = position.to_point(&request.before_edit).row;
 925                        old_to_new_rows.insert(old_row, new_row);
 926                    }
 927                    row_ranges.push((new_row..new_end_row, entry.original_indent_column));
 928                }
 929
 930                // Build a map containing the suggested indentation for each of the edited lines
 931                // with respect to the state of the buffer before these edits. This map is keyed
 932                // by the rows for these lines in the current state of the buffer.
 933                let mut old_suggestions = BTreeMap::<u32, (IndentSize, bool)>::default();
 934                let old_edited_ranges =
 935                    contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
 936                let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
 937                let mut language_indent_size = IndentSize::default();
 938                for old_edited_range in old_edited_ranges {
 939                    let suggestions = request
 940                        .before_edit
 941                        .suggest_autoindents(old_edited_range.clone())
 942                        .into_iter()
 943                        .flatten();
 944                    for (old_row, suggestion) in old_edited_range.zip(suggestions) {
 945                        if let Some(suggestion) = suggestion {
 946                            let new_row = *old_to_new_rows.get(&old_row).unwrap();
 947
 948                            // Find the indent size based on the language for this row.
 949                            while let Some((row, size)) = language_indent_sizes.peek() {
 950                                if *row > new_row {
 951                                    break;
 952                                }
 953                                language_indent_size = *size;
 954                                language_indent_sizes.next();
 955                            }
 956
 957                            let suggested_indent = old_to_new_rows
 958                                .get(&suggestion.basis_row)
 959                                .and_then(|from_row| {
 960                                    Some(old_suggestions.get(from_row).copied()?.0)
 961                                })
 962                                .unwrap_or_else(|| {
 963                                    request
 964                                        .before_edit
 965                                        .indent_size_for_line(suggestion.basis_row)
 966                                })
 967                                .with_delta(suggestion.delta, language_indent_size);
 968                            old_suggestions
 969                                .insert(new_row, (suggested_indent, suggestion.within_error));
 970                        }
 971                    }
 972                    yield_now().await;
 973                }
 974
 975                // In block mode, only compute indentation suggestions for the first line
 976                // of each insertion. Otherwise, compute suggestions for every inserted line.
 977                let new_edited_row_ranges = contiguous_ranges(
 978                    row_ranges.iter().flat_map(|(range, _)| {
 979                        if request.is_block_mode {
 980                            range.start..range.start + 1
 981                        } else {
 982                            range.clone()
 983                        }
 984                    }),
 985                    max_rows_between_yields,
 986                );
 987
 988                // Compute new suggestions for each line, but only include them in the result
 989                // if they differ from the old suggestion for that line.
 990                let mut language_indent_sizes = language_indent_sizes_by_new_row.iter().peekable();
 991                let mut language_indent_size = IndentSize::default();
 992                for new_edited_row_range in new_edited_row_ranges {
 993                    let suggestions = snapshot
 994                        .suggest_autoindents(new_edited_row_range.clone())
 995                        .into_iter()
 996                        .flatten();
 997                    for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
 998                        if let Some(suggestion) = suggestion {
 999                            // Find the indent size based on the language for this row.
1000                            while let Some((row, size)) = language_indent_sizes.peek() {
1001                                if *row > new_row {
1002                                    break;
1003                                }
1004                                language_indent_size = *size;
1005                                language_indent_sizes.next();
1006                            }
1007
1008                            let suggested_indent = indent_sizes
1009                                .get(&suggestion.basis_row)
1010                                .copied()
1011                                .unwrap_or_else(|| {
1012                                    snapshot.indent_size_for_line(suggestion.basis_row)
1013                                })
1014                                .with_delta(suggestion.delta, language_indent_size);
1015                            if old_suggestions.get(&new_row).map_or(
1016                                true,
1017                                |(old_indentation, was_within_error)| {
1018                                    suggested_indent != *old_indentation
1019                                        && (!suggestion.within_error || *was_within_error)
1020                                },
1021                            ) {
1022                                indent_sizes.insert(new_row, suggested_indent);
1023                            }
1024                        }
1025                    }
1026                    yield_now().await;
1027                }
1028
1029                // For each block of inserted text, adjust the indentation of the remaining
1030                // lines of the block by the same amount as the first line was adjusted.
1031                if request.is_block_mode {
1032                    for (row_range, original_indent_column) in
1033                        row_ranges
1034                            .into_iter()
1035                            .filter_map(|(range, original_indent_column)| {
1036                                if range.len() > 1 {
1037                                    Some((range, original_indent_column?))
1038                                } else {
1039                                    None
1040                                }
1041                            })
1042                    {
1043                        let new_indent = indent_sizes
1044                            .get(&row_range.start)
1045                            .copied()
1046                            .unwrap_or_else(|| snapshot.indent_size_for_line(row_range.start));
1047                        let delta = new_indent.len as i64 - original_indent_column as i64;
1048                        if delta != 0 {
1049                            for row in row_range.skip(1) {
1050                                indent_sizes.entry(row).or_insert_with(|| {
1051                                    let mut size = snapshot.indent_size_for_line(row);
1052                                    if size.kind == new_indent.kind {
1053                                        match delta.cmp(&0) {
1054                                            Ordering::Greater => size.len += delta as u32,
1055                                            Ordering::Less => {
1056                                                size.len = size.len.saturating_sub(-delta as u32)
1057                                            }
1058                                            Ordering::Equal => {}
1059                                        }
1060                                    }
1061                                    size
1062                                });
1063                            }
1064                        }
1065                    }
1066                }
1067            }
1068
1069            indent_sizes
1070        })
1071    }
1072
1073    fn apply_autoindents(
1074        &mut self,
1075        indent_sizes: BTreeMap<u32, IndentSize>,
1076        cx: &mut ModelContext<Self>,
1077    ) {
1078        self.autoindent_requests.clear();
1079
1080        let edits: Vec<_> = indent_sizes
1081            .into_iter()
1082            .filter_map(|(row, indent_size)| {
1083                let current_size = indent_size_for_line(self, row);
1084                Self::edit_for_indent_size_adjustment(row, current_size, indent_size)
1085            })
1086            .collect();
1087
1088        self.edit(edits, None, cx);
1089    }
1090
1091    // Create a minimal edit that will cause the the given row to be indented
1092    // with the given size. After applying this edit, the length of the line
1093    // will always be at least `new_size.len`.
1094    pub fn edit_for_indent_size_adjustment(
1095        row: u32,
1096        current_size: IndentSize,
1097        new_size: IndentSize,
1098    ) -> Option<(Range<Point>, String)> {
1099        if new_size.kind != current_size.kind {
1100            Some((
1101                Point::new(row, 0)..Point::new(row, current_size.len),
1102                iter::repeat(new_size.char())
1103                    .take(new_size.len as usize)
1104                    .collect::<String>(),
1105            ))
1106        } else {
1107            match new_size.len.cmp(&current_size.len) {
1108                Ordering::Greater => {
1109                    let point = Point::new(row, 0);
1110                    Some((
1111                        point..point,
1112                        iter::repeat(new_size.char())
1113                            .take((new_size.len - current_size.len) as usize)
1114                            .collect::<String>(),
1115                    ))
1116                }
1117
1118                Ordering::Less => Some((
1119                    Point::new(row, 0)..Point::new(row, current_size.len - new_size.len),
1120                    String::new(),
1121                )),
1122
1123                Ordering::Equal => None,
1124            }
1125        }
1126    }
1127
1128    pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task<Diff> {
1129        let old_text = self.as_rope().clone();
1130        let base_version = self.version();
1131        cx.background().spawn(async move {
1132            let old_text = old_text.to_string();
1133            let line_ending = LineEnding::detect(&new_text);
1134            LineEnding::normalize(&mut new_text);
1135            let diff = TextDiff::from_chars(old_text.as_str(), new_text.as_str());
1136            let mut edits = Vec::new();
1137            let mut offset = 0;
1138            let empty: Arc<str> = "".into();
1139            for change in diff.iter_all_changes() {
1140                let value = change.value();
1141                let end_offset = offset + value.len();
1142                match change.tag() {
1143                    ChangeTag::Equal => {
1144                        offset = end_offset;
1145                    }
1146                    ChangeTag::Delete => {
1147                        edits.push((offset..end_offset, empty.clone()));
1148                        offset = end_offset;
1149                    }
1150                    ChangeTag::Insert => {
1151                        edits.push((offset..offset, value.into()));
1152                    }
1153                }
1154            }
1155            Diff {
1156                base_version,
1157                line_ending,
1158                edits,
1159            }
1160        })
1161    }
1162
1163    /// Spawn a background task that searches the buffer for any whitespace
1164    /// at the ends of a lines, and returns a `Diff` that removes that whitespace.
1165    pub fn remove_trailing_whitespace(&self, cx: &AppContext) -> Task<Diff> {
1166        let old_text = self.as_rope().clone();
1167        let line_ending = self.line_ending();
1168        let base_version = self.version();
1169        cx.background().spawn(async move {
1170            let ranges = trailing_whitespace_ranges(&old_text);
1171            let empty = Arc::<str>::from("");
1172            Diff {
1173                base_version,
1174                line_ending,
1175                edits: ranges
1176                    .into_iter()
1177                    .map(|range| (range, empty.clone()))
1178                    .collect(),
1179            }
1180        })
1181    }
1182
1183    /// Ensure that the buffer ends with a single newline character, and
1184    /// no other whitespace.
1185    pub fn ensure_final_newline(&mut self, cx: &mut ModelContext<Self>) {
1186        let len = self.len();
1187        let mut offset = len;
1188        for chunk in self.as_rope().reversed_chunks_in_range(0..len) {
1189            let non_whitespace_len = chunk
1190                .trim_end_matches(|c: char| c.is_ascii_whitespace())
1191                .len();
1192            offset -= chunk.len();
1193            offset += non_whitespace_len;
1194            if non_whitespace_len != 0 {
1195                if offset == len - 1 && chunk.get(non_whitespace_len..) == Some("\n") {
1196                    return;
1197                }
1198                break;
1199            }
1200        }
1201        self.edit([(offset..len, "\n")], None, cx);
1202    }
1203
1204    /// Apply a diff to the buffer. If the buffer has changed since the given diff was
1205    /// calculated, then adjust the diff to account for those changes, and discard any
1206    /// parts of the diff that conflict with those changes.
1207    pub fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1208        // Check for any edits to the buffer that have occurred since this diff
1209        // was computed.
1210        let snapshot = self.snapshot();
1211        let mut edits_since = snapshot.edits_since::<usize>(&diff.base_version).peekable();
1212        let mut delta = 0;
1213        let adjusted_edits = diff.edits.into_iter().filter_map(|(range, new_text)| {
1214            while let Some(edit_since) = edits_since.peek() {
1215                // If the edit occurs after a diff hunk, then it does not
1216                // affect that hunk.
1217                if edit_since.old.start > range.end {
1218                    break;
1219                }
1220                // If the edit precedes the diff hunk, then adjust the hunk
1221                // to reflect the edit.
1222                else if edit_since.old.end < range.start {
1223                    delta += edit_since.new_len() as i64 - edit_since.old_len() as i64;
1224                    edits_since.next();
1225                }
1226                // If the edit intersects a diff hunk, then discard that hunk.
1227                else {
1228                    return None;
1229                }
1230            }
1231
1232            let start = (range.start as i64 + delta) as usize;
1233            let end = (range.end as i64 + delta) as usize;
1234            Some((start..end, new_text))
1235        });
1236
1237        self.start_transaction();
1238        self.text.set_line_ending(diff.line_ending);
1239        self.edit(adjusted_edits, None, cx);
1240        self.end_transaction(cx)
1241    }
1242
1243    pub fn is_dirty(&self) -> bool {
1244        self.saved_version_fingerprint != self.as_rope().fingerprint()
1245            || self.file.as_ref().map_or(false, |file| file.is_deleted())
1246    }
1247
1248    pub fn has_conflict(&self) -> bool {
1249        self.saved_version_fingerprint != self.as_rope().fingerprint()
1250            && self
1251                .file
1252                .as_ref()
1253                .map_or(false, |file| file.mtime() > self.saved_mtime)
1254    }
1255
1256    pub fn subscribe(&mut self) -> Subscription {
1257        self.text.subscribe()
1258    }
1259
1260    pub fn start_transaction(&mut self) -> Option<TransactionId> {
1261        self.start_transaction_at(Instant::now())
1262    }
1263
1264    pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
1265        self.transaction_depth += 1;
1266        if self.was_dirty_before_starting_transaction.is_none() {
1267            self.was_dirty_before_starting_transaction = Some(self.is_dirty());
1268        }
1269        self.text.start_transaction_at(now)
1270    }
1271
1272    pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1273        self.end_transaction_at(Instant::now(), cx)
1274    }
1275
1276    pub fn end_transaction_at(
1277        &mut self,
1278        now: Instant,
1279        cx: &mut ModelContext<Self>,
1280    ) -> Option<TransactionId> {
1281        assert!(self.transaction_depth > 0);
1282        self.transaction_depth -= 1;
1283        let was_dirty = if self.transaction_depth == 0 {
1284            self.was_dirty_before_starting_transaction.take().unwrap()
1285        } else {
1286            false
1287        };
1288        if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
1289            self.did_edit(&start_version, was_dirty, cx);
1290            Some(transaction_id)
1291        } else {
1292            None
1293        }
1294    }
1295
1296    pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
1297        self.text.push_transaction(transaction, now);
1298    }
1299
1300    pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
1301        self.text.finalize_last_transaction()
1302    }
1303
1304    pub fn group_until_transaction(&mut self, transaction_id: TransactionId) {
1305        self.text.group_until_transaction(transaction_id);
1306    }
1307
1308    pub fn forget_transaction(&mut self, transaction_id: TransactionId) {
1309        self.text.forget_transaction(transaction_id);
1310    }
1311
1312    pub fn wait_for_edits(
1313        &mut self,
1314        edit_ids: impl IntoIterator<Item = clock::Local>,
1315    ) -> impl Future<Output = Result<()>> {
1316        self.text.wait_for_edits(edit_ids)
1317    }
1318
1319    pub fn wait_for_anchors(
1320        &mut self,
1321        anchors: impl IntoIterator<Item = Anchor>,
1322    ) -> impl 'static + Future<Output = Result<()>> {
1323        self.text.wait_for_anchors(anchors)
1324    }
1325
1326    pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = Result<()>> {
1327        self.text.wait_for_version(version)
1328    }
1329
1330    pub fn give_up_waiting(&mut self) {
1331        self.text.give_up_waiting();
1332    }
1333
1334    pub fn set_active_selections(
1335        &mut self,
1336        selections: Arc<[Selection<Anchor>]>,
1337        line_mode: bool,
1338        cursor_shape: CursorShape,
1339        cx: &mut ModelContext<Self>,
1340    ) {
1341        let lamport_timestamp = self.text.lamport_clock.tick();
1342        self.remote_selections.insert(
1343            self.text.replica_id(),
1344            SelectionSet {
1345                selections: selections.clone(),
1346                lamport_timestamp,
1347                line_mode,
1348                cursor_shape,
1349            },
1350        );
1351        self.send_operation(
1352            Operation::UpdateSelections {
1353                selections,
1354                line_mode,
1355                lamport_timestamp,
1356                cursor_shape,
1357            },
1358            cx,
1359        );
1360    }
1361
1362    pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
1363        if self
1364            .remote_selections
1365            .get(&self.text.replica_id())
1366            .map_or(true, |set| !set.selections.is_empty())
1367        {
1368            self.set_active_selections(Arc::from([]), false, Default::default(), cx);
1369        }
1370    }
1371
1372    pub fn set_text<T>(&mut self, text: T, cx: &mut ModelContext<Self>) -> Option<clock::Local>
1373    where
1374        T: Into<Arc<str>>,
1375    {
1376        self.autoindent_requests.clear();
1377        self.edit([(0..self.len(), text)], None, cx)
1378    }
1379
1380    pub fn edit<I, S, T>(
1381        &mut self,
1382        edits_iter: I,
1383        autoindent_mode: Option<AutoindentMode>,
1384        cx: &mut ModelContext<Self>,
1385    ) -> Option<clock::Local>
1386    where
1387        I: IntoIterator<Item = (Range<S>, T)>,
1388        S: ToOffset,
1389        T: Into<Arc<str>>,
1390    {
1391        // Skip invalid edits and coalesce contiguous ones.
1392        let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
1393        for (range, new_text) in edits_iter {
1394            let mut range = range.start.to_offset(self)..range.end.to_offset(self);
1395            if range.start > range.end {
1396                mem::swap(&mut range.start, &mut range.end);
1397            }
1398            let new_text = new_text.into();
1399            if !new_text.is_empty() || !range.is_empty() {
1400                if let Some((prev_range, prev_text)) = edits.last_mut() {
1401                    if prev_range.end >= range.start {
1402                        prev_range.end = cmp::max(prev_range.end, range.end);
1403                        *prev_text = format!("{prev_text}{new_text}").into();
1404                    } else {
1405                        edits.push((range, new_text));
1406                    }
1407                } else {
1408                    edits.push((range, new_text));
1409                }
1410            }
1411        }
1412        if edits.is_empty() {
1413            return None;
1414        }
1415
1416        self.start_transaction();
1417        self.pending_autoindent.take();
1418        let autoindent_request = autoindent_mode
1419            .and_then(|mode| self.language.as_ref().map(|_| (self.snapshot(), mode)));
1420
1421        let edit_operation = self.text.edit(edits.iter().cloned());
1422        let edit_id = edit_operation.local_timestamp();
1423
1424        if let Some((before_edit, mode)) = autoindent_request {
1425            let mut delta = 0isize;
1426            let entries = edits
1427                .into_iter()
1428                .enumerate()
1429                .zip(&edit_operation.as_edit().unwrap().new_text)
1430                .map(|((ix, (range, _)), new_text)| {
1431                    let new_text_length = new_text.len();
1432                    let old_start = range.start.to_point(&before_edit);
1433                    let new_start = (delta + range.start as isize) as usize;
1434                    delta += new_text_length as isize - (range.end as isize - range.start as isize);
1435
1436                    let mut range_of_insertion_to_indent = 0..new_text_length;
1437                    let mut first_line_is_new = false;
1438                    let mut original_indent_column = None;
1439
1440                    // When inserting an entire line at the beginning of an existing line,
1441                    // treat the insertion as new.
1442                    if new_text.contains('\n')
1443                        && old_start.column <= before_edit.indent_size_for_line(old_start.row).len
1444                    {
1445                        first_line_is_new = true;
1446                    }
1447
1448                    // When inserting text starting with a newline, avoid auto-indenting the
1449                    // previous line.
1450                    if new_text.starts_with('\n') {
1451                        range_of_insertion_to_indent.start += 1;
1452                        first_line_is_new = true;
1453                    }
1454
1455                    // Avoid auto-indenting after the insertion.
1456                    if let AutoindentMode::Block {
1457                        original_indent_columns,
1458                    } = &mode
1459                    {
1460                        original_indent_column =
1461                            Some(original_indent_columns.get(ix).copied().unwrap_or_else(|| {
1462                                indent_size_for_text(
1463                                    new_text[range_of_insertion_to_indent.clone()].chars(),
1464                                )
1465                                .len
1466                            }));
1467                        if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
1468                            range_of_insertion_to_indent.end -= 1;
1469                        }
1470                    }
1471
1472                    AutoindentRequestEntry {
1473                        first_line_is_new,
1474                        original_indent_column,
1475                        indent_size: before_edit.language_indent_size_at(range.start, cx),
1476                        range: self.anchor_before(new_start + range_of_insertion_to_indent.start)
1477                            ..self.anchor_after(new_start + range_of_insertion_to_indent.end),
1478                    }
1479                })
1480                .collect();
1481
1482            self.autoindent_requests.push(Arc::new(AutoindentRequest {
1483                before_edit,
1484                entries,
1485                is_block_mode: matches!(mode, AutoindentMode::Block { .. }),
1486            }));
1487        }
1488
1489        self.end_transaction(cx);
1490        self.send_operation(Operation::Buffer(edit_operation), cx);
1491        Some(edit_id)
1492    }
1493
1494    fn did_edit(
1495        &mut self,
1496        old_version: &clock::Global,
1497        was_dirty: bool,
1498        cx: &mut ModelContext<Self>,
1499    ) {
1500        if self.edits_since::<usize>(old_version).next().is_none() {
1501            return;
1502        }
1503
1504        self.reparse(cx);
1505
1506        cx.emit(Event::Edited);
1507        if was_dirty != self.is_dirty() {
1508            cx.emit(Event::DirtyChanged);
1509        }
1510        cx.notify();
1511    }
1512
1513    pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1514        &mut self,
1515        ops: I,
1516        cx: &mut ModelContext<Self>,
1517    ) -> Result<()> {
1518        self.pending_autoindent.take();
1519        let was_dirty = self.is_dirty();
1520        let old_version = self.version.clone();
1521        let mut deferred_ops = Vec::new();
1522        let buffer_ops = ops
1523            .into_iter()
1524            .filter_map(|op| match op {
1525                Operation::Buffer(op) => Some(op),
1526                _ => {
1527                    if self.can_apply_op(&op) {
1528                        self.apply_op(op, cx);
1529                    } else {
1530                        deferred_ops.push(op);
1531                    }
1532                    None
1533                }
1534            })
1535            .collect::<Vec<_>>();
1536        self.text.apply_ops(buffer_ops)?;
1537        self.deferred_ops.insert(deferred_ops);
1538        self.flush_deferred_ops(cx);
1539        self.did_edit(&old_version, was_dirty, cx);
1540        // Notify independently of whether the buffer was edited as the operations could include a
1541        // selection update.
1542        cx.notify();
1543        Ok(())
1544    }
1545
1546    fn flush_deferred_ops(&mut self, cx: &mut ModelContext<Self>) {
1547        let mut deferred_ops = Vec::new();
1548        for op in self.deferred_ops.drain().iter().cloned() {
1549            if self.can_apply_op(&op) {
1550                self.apply_op(op, cx);
1551            } else {
1552                deferred_ops.push(op);
1553            }
1554        }
1555        self.deferred_ops.insert(deferred_ops);
1556    }
1557
1558    fn can_apply_op(&self, operation: &Operation) -> bool {
1559        match operation {
1560            Operation::Buffer(_) => {
1561                unreachable!("buffer operations should never be applied at this layer")
1562            }
1563            Operation::UpdateDiagnostics {
1564                diagnostics: diagnostic_set,
1565                ..
1566            } => diagnostic_set.iter().all(|diagnostic| {
1567                self.text.can_resolve(&diagnostic.range.start)
1568                    && self.text.can_resolve(&diagnostic.range.end)
1569            }),
1570            Operation::UpdateSelections { selections, .. } => selections
1571                .iter()
1572                .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
1573            Operation::UpdateCompletionTriggers { .. } => true,
1574        }
1575    }
1576
1577    fn apply_op(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1578        match operation {
1579            Operation::Buffer(_) => {
1580                unreachable!("buffer operations should never be applied at this layer")
1581            }
1582            Operation::UpdateDiagnostics {
1583                diagnostics: diagnostic_set,
1584                lamport_timestamp,
1585            } => {
1586                let snapshot = self.snapshot();
1587                self.apply_diagnostic_update(
1588                    DiagnosticSet::from_sorted_entries(diagnostic_set.iter().cloned(), &snapshot),
1589                    lamport_timestamp,
1590                    cx,
1591                );
1592            }
1593            Operation::UpdateSelections {
1594                selections,
1595                lamport_timestamp,
1596                line_mode,
1597                cursor_shape,
1598            } => {
1599                if let Some(set) = self.remote_selections.get(&lamport_timestamp.replica_id) {
1600                    if set.lamport_timestamp > lamport_timestamp {
1601                        return;
1602                    }
1603                }
1604
1605                self.remote_selections.insert(
1606                    lamport_timestamp.replica_id,
1607                    SelectionSet {
1608                        selections,
1609                        lamport_timestamp,
1610                        line_mode,
1611                        cursor_shape,
1612                    },
1613                );
1614                self.text.lamport_clock.observe(lamport_timestamp);
1615                self.selections_update_count += 1;
1616            }
1617            Operation::UpdateCompletionTriggers {
1618                triggers,
1619                lamport_timestamp,
1620            } => {
1621                self.completion_triggers = triggers;
1622                self.text.lamport_clock.observe(lamport_timestamp);
1623            }
1624        }
1625    }
1626
1627    fn apply_diagnostic_update(
1628        &mut self,
1629        diagnostics: DiagnosticSet,
1630        lamport_timestamp: clock::Lamport,
1631        cx: &mut ModelContext<Self>,
1632    ) {
1633        if lamport_timestamp > self.diagnostics_timestamp {
1634            self.diagnostics = diagnostics;
1635            self.diagnostics_timestamp = lamport_timestamp;
1636            self.diagnostics_update_count += 1;
1637            self.text.lamport_clock.observe(lamport_timestamp);
1638            cx.notify();
1639            cx.emit(Event::DiagnosticsUpdated);
1640        }
1641    }
1642
1643    fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1644        cx.emit(Event::Operation(operation));
1645    }
1646
1647    pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1648        self.remote_selections.remove(&replica_id);
1649        cx.notify();
1650    }
1651
1652    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1653        let was_dirty = self.is_dirty();
1654        let old_version = self.version.clone();
1655
1656        if let Some((transaction_id, operation)) = self.text.undo() {
1657            self.send_operation(Operation::Buffer(operation), cx);
1658            self.did_edit(&old_version, was_dirty, cx);
1659            Some(transaction_id)
1660        } else {
1661            None
1662        }
1663    }
1664
1665    pub fn undo_to_transaction(
1666        &mut self,
1667        transaction_id: TransactionId,
1668        cx: &mut ModelContext<Self>,
1669    ) -> bool {
1670        let was_dirty = self.is_dirty();
1671        let old_version = self.version.clone();
1672
1673        let operations = self.text.undo_to_transaction(transaction_id);
1674        let undone = !operations.is_empty();
1675        for operation in operations {
1676            self.send_operation(Operation::Buffer(operation), cx);
1677        }
1678        if undone {
1679            self.did_edit(&old_version, was_dirty, cx)
1680        }
1681        undone
1682    }
1683
1684    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
1685        let was_dirty = self.is_dirty();
1686        let old_version = self.version.clone();
1687
1688        if let Some((transaction_id, operation)) = self.text.redo() {
1689            self.send_operation(Operation::Buffer(operation), cx);
1690            self.did_edit(&old_version, was_dirty, cx);
1691            Some(transaction_id)
1692        } else {
1693            None
1694        }
1695    }
1696
1697    pub fn redo_to_transaction(
1698        &mut self,
1699        transaction_id: TransactionId,
1700        cx: &mut ModelContext<Self>,
1701    ) -> bool {
1702        let was_dirty = self.is_dirty();
1703        let old_version = self.version.clone();
1704
1705        let operations = self.text.redo_to_transaction(transaction_id);
1706        let redone = !operations.is_empty();
1707        for operation in operations {
1708            self.send_operation(Operation::Buffer(operation), cx);
1709        }
1710        if redone {
1711            self.did_edit(&old_version, was_dirty, cx)
1712        }
1713        redone
1714    }
1715
1716    pub fn set_completion_triggers(&mut self, triggers: Vec<String>, cx: &mut ModelContext<Self>) {
1717        self.completion_triggers = triggers.clone();
1718        self.completion_triggers_timestamp = self.text.lamport_clock.tick();
1719        self.send_operation(
1720            Operation::UpdateCompletionTriggers {
1721                triggers,
1722                lamport_timestamp: self.completion_triggers_timestamp,
1723            },
1724            cx,
1725        );
1726        cx.notify();
1727    }
1728
1729    pub fn completion_triggers(&self) -> &[String] {
1730        &self.completion_triggers
1731    }
1732}
1733
1734#[cfg(any(test, feature = "test-support"))]
1735impl Buffer {
1736    pub fn edit_via_marked_text(
1737        &mut self,
1738        marked_string: &str,
1739        autoindent_mode: Option<AutoindentMode>,
1740        cx: &mut ModelContext<Self>,
1741    ) {
1742        let edits = self.edits_for_marked_text(marked_string);
1743        self.edit(edits, autoindent_mode, cx);
1744    }
1745
1746    pub fn set_group_interval(&mut self, group_interval: Duration) {
1747        self.text.set_group_interval(group_interval);
1748    }
1749
1750    pub fn randomly_edit<T>(
1751        &mut self,
1752        rng: &mut T,
1753        old_range_count: usize,
1754        cx: &mut ModelContext<Self>,
1755    ) where
1756        T: rand::Rng,
1757    {
1758        let mut edits: Vec<(Range<usize>, String)> = Vec::new();
1759        let mut last_end = None;
1760        for _ in 0..old_range_count {
1761            if last_end.map_or(false, |last_end| last_end >= self.len()) {
1762                break;
1763            }
1764
1765            let new_start = last_end.map_or(0, |last_end| last_end + 1);
1766            let mut range = self.random_byte_range(new_start, rng);
1767            if rng.gen_bool(0.2) {
1768                mem::swap(&mut range.start, &mut range.end);
1769            }
1770            last_end = Some(range.end);
1771
1772            let new_text_len = rng.gen_range(0..10);
1773            let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
1774
1775            edits.push((range, new_text));
1776        }
1777        log::info!("mutating buffer {} with {:?}", self.replica_id(), edits);
1778        self.edit(edits, None, cx);
1779    }
1780
1781    pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
1782        let was_dirty = self.is_dirty();
1783        let old_version = self.version.clone();
1784
1785        let ops = self.text.randomly_undo_redo(rng);
1786        if !ops.is_empty() {
1787            for op in ops {
1788                self.send_operation(Operation::Buffer(op), cx);
1789                self.did_edit(&old_version, was_dirty, cx);
1790            }
1791        }
1792    }
1793}
1794
1795impl Entity for Buffer {
1796    type Event = Event;
1797}
1798
1799impl Deref for Buffer {
1800    type Target = TextBuffer;
1801
1802    fn deref(&self) -> &Self::Target {
1803        &self.text
1804    }
1805}
1806
1807impl BufferSnapshot {
1808    pub fn indent_size_for_line(&self, row: u32) -> IndentSize {
1809        indent_size_for_line(self, row)
1810    }
1811
1812    pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &AppContext) -> IndentSize {
1813        let language_name = self.language_at(position).map(|language| language.name());
1814        let settings = cx.global::<Settings>();
1815        if settings.hard_tabs(language_name.as_deref()) {
1816            IndentSize::tab()
1817        } else {
1818            IndentSize::spaces(settings.tab_size(language_name.as_deref()).get())
1819        }
1820    }
1821
1822    pub fn suggested_indents(
1823        &self,
1824        rows: impl Iterator<Item = u32>,
1825        single_indent_size: IndentSize,
1826    ) -> BTreeMap<u32, IndentSize> {
1827        let mut result = BTreeMap::new();
1828
1829        for row_range in contiguous_ranges(rows, 10) {
1830            let suggestions = match self.suggest_autoindents(row_range.clone()) {
1831                Some(suggestions) => suggestions,
1832                _ => break,
1833            };
1834
1835            for (row, suggestion) in row_range.zip(suggestions) {
1836                let indent_size = if let Some(suggestion) = suggestion {
1837                    result
1838                        .get(&suggestion.basis_row)
1839                        .copied()
1840                        .unwrap_or_else(|| self.indent_size_for_line(suggestion.basis_row))
1841                        .with_delta(suggestion.delta, single_indent_size)
1842                } else {
1843                    self.indent_size_for_line(row)
1844                };
1845
1846                result.insert(row, indent_size);
1847            }
1848        }
1849
1850        result
1851    }
1852
1853    fn suggest_autoindents(
1854        &self,
1855        row_range: Range<u32>,
1856    ) -> Option<impl Iterator<Item = Option<IndentSuggestion>> + '_> {
1857        let config = &self.language.as_ref()?.config;
1858        let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
1859
1860        // Find the suggested indentation ranges based on the syntax tree.
1861        let start = Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0);
1862        let end = Point::new(row_range.end, 0);
1863        let range = (start..end).to_offset(&self.text);
1864        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
1865            Some(&grammar.indents_config.as_ref()?.query)
1866        });
1867        let indent_configs = matches
1868            .grammars()
1869            .iter()
1870            .map(|grammar| grammar.indents_config.as_ref().unwrap())
1871            .collect::<Vec<_>>();
1872
1873        let mut indent_ranges = Vec::<Range<Point>>::new();
1874        let mut outdent_positions = Vec::<Point>::new();
1875        while let Some(mat) = matches.peek() {
1876            let mut start: Option<Point> = None;
1877            let mut end: Option<Point> = None;
1878
1879            let config = &indent_configs[mat.grammar_index];
1880            for capture in mat.captures {
1881                if capture.index == config.indent_capture_ix {
1882                    start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
1883                    end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
1884                } else if Some(capture.index) == config.start_capture_ix {
1885                    start = Some(Point::from_ts_point(capture.node.end_position()));
1886                } else if Some(capture.index) == config.end_capture_ix {
1887                    end = Some(Point::from_ts_point(capture.node.start_position()));
1888                } else if Some(capture.index) == config.outdent_capture_ix {
1889                    outdent_positions.push(Point::from_ts_point(capture.node.start_position()));
1890                }
1891            }
1892
1893            matches.advance();
1894            if let Some((start, end)) = start.zip(end) {
1895                if start.row == end.row {
1896                    continue;
1897                }
1898
1899                let range = start..end;
1900                match indent_ranges.binary_search_by_key(&range.start, |r| r.start) {
1901                    Err(ix) => indent_ranges.insert(ix, range),
1902                    Ok(ix) => {
1903                        let prev_range = &mut indent_ranges[ix];
1904                        prev_range.end = prev_range.end.max(range.end);
1905                    }
1906                }
1907            }
1908        }
1909
1910        let mut error_ranges = Vec::<Range<Point>>::new();
1911        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
1912            Some(&grammar.error_query)
1913        });
1914        while let Some(mat) = matches.peek() {
1915            let node = mat.captures[0].node;
1916            let start = Point::from_ts_point(node.start_position());
1917            let end = Point::from_ts_point(node.end_position());
1918            let range = start..end;
1919            let ix = match error_ranges.binary_search_by_key(&range.start, |r| r.start) {
1920                Ok(ix) | Err(ix) => ix,
1921            };
1922            let mut end_ix = ix;
1923            while let Some(existing_range) = error_ranges.get(end_ix) {
1924                if existing_range.end < end {
1925                    end_ix += 1;
1926                } else {
1927                    break;
1928                }
1929            }
1930            error_ranges.splice(ix..end_ix, [range]);
1931            matches.advance();
1932        }
1933
1934        outdent_positions.sort();
1935        for outdent_position in outdent_positions {
1936            // find the innermost indent range containing this outdent_position
1937            // set its end to the outdent position
1938            if let Some(range_to_truncate) = indent_ranges
1939                .iter_mut()
1940                .filter(|indent_range| indent_range.contains(&outdent_position))
1941                .last()
1942            {
1943                range_to_truncate.end = outdent_position;
1944            }
1945        }
1946
1947        // Find the suggested indentation increases and decreased based on regexes.
1948        let mut indent_change_rows = Vec::<(u32, Ordering)>::new();
1949        self.for_each_line(
1950            Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0)
1951                ..Point::new(row_range.end, 0),
1952            |row, line| {
1953                if config
1954                    .decrease_indent_pattern
1955                    .as_ref()
1956                    .map_or(false, |regex| regex.is_match(line))
1957                {
1958                    indent_change_rows.push((row, Ordering::Less));
1959                }
1960                if config
1961                    .increase_indent_pattern
1962                    .as_ref()
1963                    .map_or(false, |regex| regex.is_match(line))
1964                {
1965                    indent_change_rows.push((row + 1, Ordering::Greater));
1966                }
1967            },
1968        );
1969
1970        let mut indent_changes = indent_change_rows.into_iter().peekable();
1971        let mut prev_row = if config.auto_indent_using_last_non_empty_line {
1972            prev_non_blank_row.unwrap_or(0)
1973        } else {
1974            row_range.start.saturating_sub(1)
1975        };
1976        let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len);
1977        Some(row_range.map(move |row| {
1978            let row_start = Point::new(row, self.indent_size_for_line(row).len);
1979
1980            let mut indent_from_prev_row = false;
1981            let mut outdent_from_prev_row = false;
1982            let mut outdent_to_row = u32::MAX;
1983
1984            while let Some((indent_row, delta)) = indent_changes.peek() {
1985                match indent_row.cmp(&row) {
1986                    Ordering::Equal => match delta {
1987                        Ordering::Less => outdent_from_prev_row = true,
1988                        Ordering::Greater => indent_from_prev_row = true,
1989                        _ => {}
1990                    },
1991
1992                    Ordering::Greater => break,
1993                    Ordering::Less => {}
1994                }
1995
1996                indent_changes.next();
1997            }
1998
1999            for range in &indent_ranges {
2000                if range.start.row >= row {
2001                    break;
2002                }
2003                if range.start.row == prev_row && range.end > row_start {
2004                    indent_from_prev_row = true;
2005                }
2006                if range.end > prev_row_start && range.end <= row_start {
2007                    outdent_to_row = outdent_to_row.min(range.start.row);
2008                }
2009            }
2010
2011            let within_error = error_ranges
2012                .iter()
2013                .any(|e| e.start.row < row && e.end > row_start);
2014
2015            let suggestion = if outdent_to_row == prev_row
2016                || (outdent_from_prev_row && indent_from_prev_row)
2017            {
2018                Some(IndentSuggestion {
2019                    basis_row: prev_row,
2020                    delta: Ordering::Equal,
2021                    within_error,
2022                })
2023            } else if indent_from_prev_row {
2024                Some(IndentSuggestion {
2025                    basis_row: prev_row,
2026                    delta: Ordering::Greater,
2027                    within_error,
2028                })
2029            } else if outdent_to_row < prev_row {
2030                Some(IndentSuggestion {
2031                    basis_row: outdent_to_row,
2032                    delta: Ordering::Equal,
2033                    within_error,
2034                })
2035            } else if outdent_from_prev_row {
2036                Some(IndentSuggestion {
2037                    basis_row: prev_row,
2038                    delta: Ordering::Less,
2039                    within_error,
2040                })
2041            } else if config.auto_indent_using_last_non_empty_line || !self.is_line_blank(prev_row)
2042            {
2043                Some(IndentSuggestion {
2044                    basis_row: prev_row,
2045                    delta: Ordering::Equal,
2046                    within_error,
2047                })
2048            } else {
2049                None
2050            };
2051
2052            prev_row = row;
2053            prev_row_start = row_start;
2054            suggestion
2055        }))
2056    }
2057
2058    fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
2059        while row > 0 {
2060            row -= 1;
2061            if !self.is_line_blank(row) {
2062                return Some(row);
2063            }
2064        }
2065        None
2066    }
2067
2068    pub fn chunks<T: ToOffset>(&self, range: Range<T>, language_aware: bool) -> BufferChunks {
2069        let range = range.start.to_offset(self)..range.end.to_offset(self);
2070
2071        let mut syntax = None;
2072        let mut diagnostic_endpoints = Vec::new();
2073        if language_aware {
2074            let captures = self.syntax.captures(range.clone(), &self.text, |grammar| {
2075                grammar.highlights_query.as_ref()
2076            });
2077            let highlight_maps = captures
2078                .grammars()
2079                .into_iter()
2080                .map(|grammar| grammar.highlight_map())
2081                .collect();
2082            syntax = Some((captures, highlight_maps));
2083            for entry in self.diagnostics_in_range::<_, usize>(range.clone(), false) {
2084                diagnostic_endpoints.push(DiagnosticEndpoint {
2085                    offset: entry.range.start,
2086                    is_start: true,
2087                    severity: entry.diagnostic.severity,
2088                    is_unnecessary: entry.diagnostic.is_unnecessary,
2089                });
2090                diagnostic_endpoints.push(DiagnosticEndpoint {
2091                    offset: entry.range.end,
2092                    is_start: false,
2093                    severity: entry.diagnostic.severity,
2094                    is_unnecessary: entry.diagnostic.is_unnecessary,
2095                });
2096            }
2097            diagnostic_endpoints
2098                .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
2099        }
2100
2101        BufferChunks::new(self.text.as_rope(), range, syntax, diagnostic_endpoints)
2102    }
2103
2104    pub fn for_each_line(&self, range: Range<Point>, mut callback: impl FnMut(u32, &str)) {
2105        let mut line = String::new();
2106        let mut row = range.start.row;
2107        for chunk in self
2108            .as_rope()
2109            .chunks_in_range(range.to_offset(self))
2110            .chain(["\n"])
2111        {
2112            for (newline_ix, text) in chunk.split('\n').enumerate() {
2113                if newline_ix > 0 {
2114                    callback(row, &line);
2115                    row += 1;
2116                    line.clear();
2117                }
2118                line.push_str(text);
2119            }
2120        }
2121    }
2122
2123    pub fn language_at<D: ToOffset>(&self, position: D) -> Option<&Arc<Language>> {
2124        let offset = position.to_offset(self);
2125        self.syntax
2126            .layers_for_range(offset..offset, &self.text)
2127            .filter(|l| l.node.end_byte() > offset)
2128            .last()
2129            .map(|info| info.language)
2130            .or(self.language.as_ref())
2131    }
2132
2133    pub fn language_scope_at<D: ToOffset>(&self, position: D) -> Option<LanguageScope> {
2134        let offset = position.to_offset(self);
2135
2136        if let Some(layer_info) = self
2137            .syntax
2138            .layers_for_range(offset..offset, &self.text)
2139            .filter(|l| l.node.end_byte() > offset)
2140            .last()
2141        {
2142            Some(LanguageScope {
2143                language: layer_info.language.clone(),
2144                override_id: layer_info.override_id(offset, &self.text),
2145            })
2146        } else {
2147            self.language.clone().map(|language| LanguageScope {
2148                language,
2149                override_id: None,
2150            })
2151        }
2152    }
2153
2154    pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
2155        let mut start = start.to_offset(self);
2156        let mut end = start;
2157        let mut next_chars = self.chars_at(start).peekable();
2158        let mut prev_chars = self.reversed_chars_at(start).peekable();
2159        let word_kind = cmp::max(
2160            prev_chars.peek().copied().map(char_kind),
2161            next_chars.peek().copied().map(char_kind),
2162        );
2163
2164        for ch in prev_chars {
2165            if Some(char_kind(ch)) == word_kind && ch != '\n' {
2166                start -= ch.len_utf8();
2167            } else {
2168                break;
2169            }
2170        }
2171
2172        for ch in next_chars {
2173            if Some(char_kind(ch)) == word_kind && ch != '\n' {
2174                end += ch.len_utf8();
2175            } else {
2176                break;
2177            }
2178        }
2179
2180        (start..end, word_kind)
2181    }
2182
2183    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
2184        let range = range.start.to_offset(self)..range.end.to_offset(self);
2185        let mut result: Option<Range<usize>> = None;
2186        'outer: for layer in self.syntax.layers_for_range(range.clone(), &self.text) {
2187            let mut cursor = layer.node.walk();
2188
2189            // Descend to the first leaf that touches the start of the range,
2190            // and if the range is non-empty, extends beyond the start.
2191            while cursor.goto_first_child_for_byte(range.start).is_some() {
2192                if !range.is_empty() && cursor.node().end_byte() == range.start {
2193                    cursor.goto_next_sibling();
2194                }
2195            }
2196
2197            // Ascend to the smallest ancestor that strictly contains the range.
2198            loop {
2199                let node_range = cursor.node().byte_range();
2200                if node_range.start <= range.start
2201                    && node_range.end >= range.end
2202                    && node_range.len() > range.len()
2203                {
2204                    break;
2205                }
2206                if !cursor.goto_parent() {
2207                    continue 'outer;
2208                }
2209            }
2210
2211            let left_node = cursor.node();
2212            let mut layer_result = left_node.byte_range();
2213
2214            // For an empty range, try to find another node immediately to the right of the range.
2215            if left_node.end_byte() == range.start {
2216                let mut right_node = None;
2217                while !cursor.goto_next_sibling() {
2218                    if !cursor.goto_parent() {
2219                        break;
2220                    }
2221                }
2222
2223                while cursor.node().start_byte() == range.start {
2224                    right_node = Some(cursor.node());
2225                    if !cursor.goto_first_child() {
2226                        break;
2227                    }
2228                }
2229
2230                // If there is a candidate node on both sides of the (empty) range, then
2231                // decide between the two by favoring a named node over an anonymous token.
2232                // If both nodes are the same in that regard, favor the right one.
2233                if let Some(right_node) = right_node {
2234                    if right_node.is_named() || !left_node.is_named() {
2235                        layer_result = right_node.byte_range();
2236                    }
2237                }
2238            }
2239
2240            if let Some(previous_result) = &result {
2241                if previous_result.len() < layer_result.len() {
2242                    continue;
2243                }
2244            }
2245            result = Some(layer_result);
2246        }
2247
2248        result
2249    }
2250
2251    pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
2252        self.outline_items_containing(0..self.len(), theme)
2253            .map(Outline::new)
2254    }
2255
2256    pub fn symbols_containing<T: ToOffset>(
2257        &self,
2258        position: T,
2259        theme: Option<&SyntaxTheme>,
2260    ) -> Option<Vec<OutlineItem<Anchor>>> {
2261        let position = position.to_offset(self);
2262        let mut items = self.outline_items_containing(
2263            position.saturating_sub(1)..self.len().min(position + 1),
2264            theme,
2265        )?;
2266        let mut prev_depth = None;
2267        items.retain(|item| {
2268            let result = prev_depth.map_or(true, |prev_depth| item.depth > prev_depth);
2269            prev_depth = Some(item.depth);
2270            result
2271        });
2272        Some(items)
2273    }
2274
2275    fn outline_items_containing(
2276        &self,
2277        range: Range<usize>,
2278        theme: Option<&SyntaxTheme>,
2279    ) -> Option<Vec<OutlineItem<Anchor>>> {
2280        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2281            grammar.outline_config.as_ref().map(|c| &c.query)
2282        });
2283        let configs = matches
2284            .grammars()
2285            .iter()
2286            .map(|g| g.outline_config.as_ref().unwrap())
2287            .collect::<Vec<_>>();
2288
2289        let mut stack = Vec::<Range<usize>>::new();
2290        let mut items = Vec::new();
2291        while let Some(mat) = matches.peek() {
2292            let config = &configs[mat.grammar_index];
2293            let item_node = mat.captures.iter().find_map(|cap| {
2294                if cap.index == config.item_capture_ix {
2295                    Some(cap.node)
2296                } else {
2297                    None
2298                }
2299            })?;
2300
2301            let item_range = item_node.byte_range();
2302            if item_range.end < range.start || item_range.start > range.end {
2303                matches.advance();
2304                continue;
2305            }
2306
2307            let mut buffer_ranges = Vec::new();
2308            for capture in mat.captures {
2309                let node_is_name;
2310                if capture.index == config.name_capture_ix {
2311                    node_is_name = true;
2312                } else if Some(capture.index) == config.context_capture_ix {
2313                    node_is_name = false;
2314                } else {
2315                    continue;
2316                }
2317
2318                let mut range = capture.node.start_byte()..capture.node.end_byte();
2319                let start = capture.node.start_position();
2320                if capture.node.end_position().row > start.row {
2321                    range.end =
2322                        range.start + self.line_len(start.row as u32) as usize - start.column;
2323                }
2324
2325                buffer_ranges.push((range, node_is_name));
2326            }
2327
2328            if buffer_ranges.is_empty() {
2329                continue;
2330            }
2331
2332            let mut text = String::new();
2333            let mut highlight_ranges = Vec::new();
2334            let mut name_ranges = Vec::new();
2335            let mut chunks = self.chunks(
2336                buffer_ranges.first().unwrap().0.start..buffer_ranges.last().unwrap().0.end,
2337                true,
2338            );
2339            for (buffer_range, is_name) in buffer_ranges {
2340                if !text.is_empty() {
2341                    text.push(' ');
2342                }
2343                if is_name {
2344                    let mut start = text.len();
2345                    let end = start + buffer_range.len();
2346
2347                    // When multiple names are captured, then the matcheable text
2348                    // includes the whitespace in between the names.
2349                    if !name_ranges.is_empty() {
2350                        start -= 1;
2351                    }
2352
2353                    name_ranges.push(start..end);
2354                }
2355
2356                let mut offset = buffer_range.start;
2357                chunks.seek(offset);
2358                for mut chunk in chunks.by_ref() {
2359                    if chunk.text.len() > buffer_range.end - offset {
2360                        chunk.text = &chunk.text[0..(buffer_range.end - offset)];
2361                        offset = buffer_range.end;
2362                    } else {
2363                        offset += chunk.text.len();
2364                    }
2365                    let style = chunk
2366                        .syntax_highlight_id
2367                        .zip(theme)
2368                        .and_then(|(highlight, theme)| highlight.style(theme));
2369                    if let Some(style) = style {
2370                        let start = text.len();
2371                        let end = start + chunk.text.len();
2372                        highlight_ranges.push((start..end, style));
2373                    }
2374                    text.push_str(chunk.text);
2375                    if offset >= buffer_range.end {
2376                        break;
2377                    }
2378                }
2379            }
2380
2381            matches.advance();
2382            while stack.last().map_or(false, |prev_range| {
2383                prev_range.start > item_range.start || prev_range.end < item_range.end
2384            }) {
2385                stack.pop();
2386            }
2387            stack.push(item_range.clone());
2388
2389            items.push(OutlineItem {
2390                depth: stack.len() - 1,
2391                range: self.anchor_after(item_range.start)..self.anchor_before(item_range.end),
2392                text,
2393                highlight_ranges,
2394                name_ranges,
2395            })
2396        }
2397        Some(items)
2398    }
2399
2400    /// Returns bracket range pairs overlapping or adjacent to `range`
2401    pub fn bracket_ranges<'a, T: ToOffset>(
2402        &'a self,
2403        range: Range<T>,
2404    ) -> impl Iterator<Item = (Range<usize>, Range<usize>)> + 'a {
2405        // Find bracket pairs that *inclusively* contain the given range.
2406        let range = range.start.to_offset(self).saturating_sub(1)
2407            ..self.len().min(range.end.to_offset(self) + 1);
2408
2409        let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
2410            grammar.brackets_config.as_ref().map(|c| &c.query)
2411        });
2412        let configs = matches
2413            .grammars()
2414            .iter()
2415            .map(|grammar| grammar.brackets_config.as_ref().unwrap())
2416            .collect::<Vec<_>>();
2417
2418        iter::from_fn(move || {
2419            while let Some(mat) = matches.peek() {
2420                let mut open = None;
2421                let mut close = None;
2422                let config = &configs[mat.grammar_index];
2423                for capture in mat.captures {
2424                    if capture.index == config.open_capture_ix {
2425                        open = Some(capture.node.byte_range());
2426                    } else if capture.index == config.close_capture_ix {
2427                        close = Some(capture.node.byte_range());
2428                    }
2429                }
2430
2431                matches.advance();
2432
2433                let Some((open, close)) = open.zip(close) else { continue };
2434
2435                let bracket_range = open.start..=close.end;
2436                if !bracket_range.overlaps(&range) {
2437                    continue;
2438                }
2439
2440                return Some((open, close));
2441            }
2442            None
2443        })
2444    }
2445
2446    #[allow(clippy::type_complexity)]
2447    pub fn remote_selections_in_range(
2448        &self,
2449        range: Range<Anchor>,
2450    ) -> impl Iterator<
2451        Item = (
2452            ReplicaId,
2453            bool,
2454            CursorShape,
2455            impl Iterator<Item = &Selection<Anchor>> + '_,
2456        ),
2457    > + '_ {
2458        self.remote_selections
2459            .iter()
2460            .filter(|(replica_id, set)| {
2461                **replica_id != self.text.replica_id() && !set.selections.is_empty()
2462            })
2463            .map(move |(replica_id, set)| {
2464                let start_ix = match set.selections.binary_search_by(|probe| {
2465                    probe.end.cmp(&range.start, self).then(Ordering::Greater)
2466                }) {
2467                    Ok(ix) | Err(ix) => ix,
2468                };
2469                let end_ix = match set.selections.binary_search_by(|probe| {
2470                    probe.start.cmp(&range.end, self).then(Ordering::Less)
2471                }) {
2472                    Ok(ix) | Err(ix) => ix,
2473                };
2474
2475                (
2476                    *replica_id,
2477                    set.line_mode,
2478                    set.cursor_shape,
2479                    set.selections[start_ix..end_ix].iter(),
2480                )
2481            })
2482    }
2483
2484    pub fn git_diff_hunks_in_row_range<'a>(
2485        &'a self,
2486        range: Range<u32>,
2487        reversed: bool,
2488    ) -> impl 'a + Iterator<Item = git::diff::DiffHunk<u32>> {
2489        self.git_diff.hunks_in_row_range(range, self, reversed)
2490    }
2491
2492    pub fn git_diff_hunks_intersecting_range<'a>(
2493        &'a self,
2494        range: Range<Anchor>,
2495        reversed: bool,
2496    ) -> impl 'a + Iterator<Item = git::diff::DiffHunk<u32>> {
2497        self.git_diff
2498            .hunks_intersecting_range(range, self, reversed)
2499    }
2500
2501    pub fn diagnostics_in_range<'a, T, O>(
2502        &'a self,
2503        search_range: Range<T>,
2504        reversed: bool,
2505    ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2506    where
2507        T: 'a + Clone + ToOffset,
2508        O: 'a + FromAnchor,
2509    {
2510        self.diagnostics.range(search_range, self, true, reversed)
2511    }
2512
2513    pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
2514        let mut groups = Vec::new();
2515        self.diagnostics.groups(&mut groups, self);
2516        groups
2517    }
2518
2519    pub fn diagnostic_group<'a, O>(
2520        &'a self,
2521        group_id: usize,
2522    ) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
2523    where
2524        O: 'a + FromAnchor,
2525    {
2526        self.diagnostics.group(group_id, self)
2527    }
2528
2529    pub fn diagnostics_update_count(&self) -> usize {
2530        self.diagnostics_update_count
2531    }
2532
2533    pub fn parse_count(&self) -> usize {
2534        self.parse_count
2535    }
2536
2537    pub fn selections_update_count(&self) -> usize {
2538        self.selections_update_count
2539    }
2540
2541    pub fn file(&self) -> Option<&Arc<dyn File>> {
2542        self.file.as_ref()
2543    }
2544
2545    pub fn resolve_file_path(&self, cx: &AppContext, include_root: bool) -> Option<PathBuf> {
2546        if let Some(file) = self.file() {
2547            if file.path().file_name().is_none() || include_root {
2548                Some(file.full_path(cx))
2549            } else {
2550                Some(file.path().to_path_buf())
2551            }
2552        } else {
2553            None
2554        }
2555    }
2556
2557    pub fn file_update_count(&self) -> usize {
2558        self.file_update_count
2559    }
2560
2561    pub fn git_diff_update_count(&self) -> usize {
2562        self.git_diff_update_count
2563    }
2564}
2565
2566fn indent_size_for_line(text: &text::BufferSnapshot, row: u32) -> IndentSize {
2567    indent_size_for_text(text.chars_at(Point::new(row, 0)))
2568}
2569
2570pub fn indent_size_for_text(text: impl Iterator<Item = char>) -> IndentSize {
2571    let mut result = IndentSize::spaces(0);
2572    for c in text {
2573        let kind = match c {
2574            ' ' => IndentKind::Space,
2575            '\t' => IndentKind::Tab,
2576            _ => break,
2577        };
2578        if result.len == 0 {
2579            result.kind = kind;
2580        }
2581        result.len += 1;
2582    }
2583    result
2584}
2585
2586impl Clone for BufferSnapshot {
2587    fn clone(&self) -> Self {
2588        Self {
2589            text: self.text.clone(),
2590            git_diff: self.git_diff.clone(),
2591            syntax: self.syntax.clone(),
2592            file: self.file.clone(),
2593            remote_selections: self.remote_selections.clone(),
2594            diagnostics: self.diagnostics.clone(),
2595            selections_update_count: self.selections_update_count,
2596            diagnostics_update_count: self.diagnostics_update_count,
2597            file_update_count: self.file_update_count,
2598            git_diff_update_count: self.git_diff_update_count,
2599            language: self.language.clone(),
2600            parse_count: self.parse_count,
2601        }
2602    }
2603}
2604
2605impl Deref for BufferSnapshot {
2606    type Target = text::BufferSnapshot;
2607
2608    fn deref(&self) -> &Self::Target {
2609        &self.text
2610    }
2611}
2612
2613unsafe impl<'a> Send for BufferChunks<'a> {}
2614
2615impl<'a> BufferChunks<'a> {
2616    pub(crate) fn new(
2617        text: &'a Rope,
2618        range: Range<usize>,
2619        syntax: Option<(SyntaxMapCaptures<'a>, Vec<HighlightMap>)>,
2620        diagnostic_endpoints: Vec<DiagnosticEndpoint>,
2621    ) -> Self {
2622        let mut highlights = None;
2623        if let Some((captures, highlight_maps)) = syntax {
2624            highlights = Some(BufferChunkHighlights {
2625                captures,
2626                next_capture: None,
2627                stack: Default::default(),
2628                highlight_maps,
2629            })
2630        }
2631
2632        let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
2633        let chunks = text.chunks_in_range(range.clone());
2634
2635        BufferChunks {
2636            range,
2637            chunks,
2638            diagnostic_endpoints,
2639            error_depth: 0,
2640            warning_depth: 0,
2641            information_depth: 0,
2642            hint_depth: 0,
2643            unnecessary_depth: 0,
2644            highlights,
2645        }
2646    }
2647
2648    pub fn seek(&mut self, offset: usize) {
2649        self.range.start = offset;
2650        self.chunks.seek(self.range.start);
2651        if let Some(highlights) = self.highlights.as_mut() {
2652            highlights
2653                .stack
2654                .retain(|(end_offset, _)| *end_offset > offset);
2655            if let Some(capture) = &highlights.next_capture {
2656                if offset >= capture.node.start_byte() {
2657                    let next_capture_end = capture.node.end_byte();
2658                    if offset < next_capture_end {
2659                        highlights.stack.push((
2660                            next_capture_end,
2661                            highlights.highlight_maps[capture.grammar_index].get(capture.index),
2662                        ));
2663                    }
2664                    highlights.next_capture.take();
2665                }
2666            }
2667            highlights.captures.set_byte_range(self.range.clone());
2668        }
2669    }
2670
2671    pub fn offset(&self) -> usize {
2672        self.range.start
2673    }
2674
2675    fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
2676        let depth = match endpoint.severity {
2677            DiagnosticSeverity::ERROR => &mut self.error_depth,
2678            DiagnosticSeverity::WARNING => &mut self.warning_depth,
2679            DiagnosticSeverity::INFORMATION => &mut self.information_depth,
2680            DiagnosticSeverity::HINT => &mut self.hint_depth,
2681            _ => return,
2682        };
2683        if endpoint.is_start {
2684            *depth += 1;
2685        } else {
2686            *depth -= 1;
2687        }
2688
2689        if endpoint.is_unnecessary {
2690            if endpoint.is_start {
2691                self.unnecessary_depth += 1;
2692            } else {
2693                self.unnecessary_depth -= 1;
2694            }
2695        }
2696    }
2697
2698    fn current_diagnostic_severity(&self) -> Option<DiagnosticSeverity> {
2699        if self.error_depth > 0 {
2700            Some(DiagnosticSeverity::ERROR)
2701        } else if self.warning_depth > 0 {
2702            Some(DiagnosticSeverity::WARNING)
2703        } else if self.information_depth > 0 {
2704            Some(DiagnosticSeverity::INFORMATION)
2705        } else if self.hint_depth > 0 {
2706            Some(DiagnosticSeverity::HINT)
2707        } else {
2708            None
2709        }
2710    }
2711
2712    fn current_code_is_unnecessary(&self) -> bool {
2713        self.unnecessary_depth > 0
2714    }
2715}
2716
2717impl<'a> Iterator for BufferChunks<'a> {
2718    type Item = Chunk<'a>;
2719
2720    fn next(&mut self) -> Option<Self::Item> {
2721        let mut next_capture_start = usize::MAX;
2722        let mut next_diagnostic_endpoint = usize::MAX;
2723
2724        if let Some(highlights) = self.highlights.as_mut() {
2725            while let Some((parent_capture_end, _)) = highlights.stack.last() {
2726                if *parent_capture_end <= self.range.start {
2727                    highlights.stack.pop();
2728                } else {
2729                    break;
2730                }
2731            }
2732
2733            if highlights.next_capture.is_none() {
2734                highlights.next_capture = highlights.captures.next();
2735            }
2736
2737            while let Some(capture) = highlights.next_capture.as_ref() {
2738                if self.range.start < capture.node.start_byte() {
2739                    next_capture_start = capture.node.start_byte();
2740                    break;
2741                } else {
2742                    let highlight_id =
2743                        highlights.highlight_maps[capture.grammar_index].get(capture.index);
2744                    highlights
2745                        .stack
2746                        .push((capture.node.end_byte(), highlight_id));
2747                    highlights.next_capture = highlights.captures.next();
2748                }
2749            }
2750        }
2751
2752        while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
2753            if endpoint.offset <= self.range.start {
2754                self.update_diagnostic_depths(endpoint);
2755                self.diagnostic_endpoints.next();
2756            } else {
2757                next_diagnostic_endpoint = endpoint.offset;
2758                break;
2759            }
2760        }
2761
2762        if let Some(chunk) = self.chunks.peek() {
2763            let chunk_start = self.range.start;
2764            let mut chunk_end = (self.chunks.offset() + chunk.len())
2765                .min(next_capture_start)
2766                .min(next_diagnostic_endpoint);
2767            let mut highlight_id = None;
2768            if let Some(highlights) = self.highlights.as_ref() {
2769                if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() {
2770                    chunk_end = chunk_end.min(*parent_capture_end);
2771                    highlight_id = Some(*parent_highlight_id);
2772                }
2773            }
2774
2775            let slice =
2776                &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2777            self.range.start = chunk_end;
2778            if self.range.start == self.chunks.offset() + chunk.len() {
2779                self.chunks.next().unwrap();
2780            }
2781
2782            Some(Chunk {
2783                text: slice,
2784                syntax_highlight_id: highlight_id,
2785                highlight_style: None,
2786                diagnostic_severity: self.current_diagnostic_severity(),
2787                is_unnecessary: self.current_code_is_unnecessary(),
2788            })
2789        } else {
2790            None
2791        }
2792    }
2793}
2794
2795impl operation_queue::Operation for Operation {
2796    fn lamport_timestamp(&self) -> clock::Lamport {
2797        match self {
2798            Operation::Buffer(_) => {
2799                unreachable!("buffer operations should never be deferred at this layer")
2800            }
2801            Operation::UpdateDiagnostics {
2802                lamport_timestamp, ..
2803            }
2804            | Operation::UpdateSelections {
2805                lamport_timestamp, ..
2806            }
2807            | Operation::UpdateCompletionTriggers {
2808                lamport_timestamp, ..
2809            } => *lamport_timestamp,
2810        }
2811    }
2812}
2813
2814impl Default for Diagnostic {
2815    fn default() -> Self {
2816        Self {
2817            code: None,
2818            severity: DiagnosticSeverity::ERROR,
2819            message: Default::default(),
2820            group_id: 0,
2821            is_primary: false,
2822            is_valid: true,
2823            is_disk_based: false,
2824            is_unnecessary: false,
2825        }
2826    }
2827}
2828
2829impl IndentSize {
2830    pub fn spaces(len: u32) -> Self {
2831        Self {
2832            len,
2833            kind: IndentKind::Space,
2834        }
2835    }
2836
2837    pub fn tab() -> Self {
2838        Self {
2839            len: 1,
2840            kind: IndentKind::Tab,
2841        }
2842    }
2843
2844    pub fn chars(&self) -> impl Iterator<Item = char> {
2845        iter::repeat(self.char()).take(self.len as usize)
2846    }
2847
2848    pub fn char(&self) -> char {
2849        match self.kind {
2850            IndentKind::Space => ' ',
2851            IndentKind::Tab => '\t',
2852        }
2853    }
2854
2855    pub fn with_delta(mut self, direction: Ordering, size: IndentSize) -> Self {
2856        match direction {
2857            Ordering::Less => {
2858                if self.kind == size.kind && self.len >= size.len {
2859                    self.len -= size.len;
2860                }
2861            }
2862            Ordering::Equal => {}
2863            Ordering::Greater => {
2864                if self.len == 0 {
2865                    self = size;
2866                } else if self.kind == size.kind {
2867                    self.len += size.len;
2868                }
2869            }
2870        }
2871        self
2872    }
2873}
2874
2875impl Completion {
2876    pub fn sort_key(&self) -> (usize, &str) {
2877        let kind_key = match self.lsp_completion.kind {
2878            Some(lsp::CompletionItemKind::VARIABLE) => 0,
2879            _ => 1,
2880        };
2881        (kind_key, &self.label.text[self.label.filter_range.clone()])
2882    }
2883
2884    pub fn is_snippet(&self) -> bool {
2885        self.lsp_completion.insert_text_format == Some(lsp::InsertTextFormat::SNIPPET)
2886    }
2887}
2888
2889pub fn contiguous_ranges(
2890    values: impl Iterator<Item = u32>,
2891    max_len: usize,
2892) -> impl Iterator<Item = Range<u32>> {
2893    let mut values = values;
2894    let mut current_range: Option<Range<u32>> = None;
2895    std::iter::from_fn(move || loop {
2896        if let Some(value) = values.next() {
2897            if let Some(range) = &mut current_range {
2898                if value == range.end && range.len() < max_len {
2899                    range.end += 1;
2900                    continue;
2901                }
2902            }
2903
2904            let prev_range = current_range.clone();
2905            current_range = Some(value..(value + 1));
2906            if prev_range.is_some() {
2907                return prev_range;
2908            }
2909        } else {
2910            return current_range.take();
2911        }
2912    })
2913}
2914
2915pub fn char_kind(c: char) -> CharKind {
2916    if c.is_whitespace() {
2917        CharKind::Whitespace
2918    } else if c.is_alphanumeric() || c == '_' {
2919        CharKind::Word
2920    } else {
2921        CharKind::Punctuation
2922    }
2923}
2924
2925/// Find all of the ranges of whitespace that occur at the ends of lines
2926/// in the given rope.
2927///
2928/// This could also be done with a regex search, but this implementation
2929/// avoids copying text.
2930pub fn trailing_whitespace_ranges(rope: &Rope) -> Vec<Range<usize>> {
2931    let mut ranges = Vec::new();
2932
2933    let mut offset = 0;
2934    let mut prev_chunk_trailing_whitespace_range = 0..0;
2935    for chunk in rope.chunks() {
2936        let mut prev_line_trailing_whitespace_range = 0..0;
2937        for (i, line) in chunk.split('\n').enumerate() {
2938            let line_end_offset = offset + line.len();
2939            let trimmed_line_len = line.trim_end_matches(|c| matches!(c, ' ' | '\t')).len();
2940            let mut trailing_whitespace_range = (offset + trimmed_line_len)..line_end_offset;
2941
2942            if i == 0 && trimmed_line_len == 0 {
2943                trailing_whitespace_range.start = prev_chunk_trailing_whitespace_range.start;
2944            }
2945            if !prev_line_trailing_whitespace_range.is_empty() {
2946                ranges.push(prev_line_trailing_whitespace_range);
2947            }
2948
2949            offset = line_end_offset + 1;
2950            prev_line_trailing_whitespace_range = trailing_whitespace_range;
2951        }
2952
2953        offset -= 1;
2954        prev_chunk_trailing_whitespace_range = prev_line_trailing_whitespace_range;
2955    }
2956
2957    if !prev_chunk_trailing_whitespace_range.is_empty() {
2958        ranges.push(prev_chunk_trailing_whitespace_range);
2959    }
2960
2961    ranges
2962}