buffer.rs

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