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