buffer.rs

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