buffer.rs

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