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