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