buffer.rs

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