lib.rs

   1mod highlight_map;
   2mod language;
   3#[cfg(test)]
   4mod tests;
   5
   6pub use self::{
   7    highlight_map::{HighlightId, HighlightMap},
   8    language::{BracketPair, Language, LanguageConfig, LanguageRegistry},
   9};
  10use anyhow::{anyhow, Result};
  11pub use buffer::{Buffer as TextBuffer, *};
  12use clock::ReplicaId;
  13use futures::FutureExt as _;
  14use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task};
  15use lazy_static::lazy_static;
  16use lsp::LanguageServer;
  17use parking_lot::Mutex;
  18use postage::{prelude::Stream, sink::Sink, watch};
  19use rpc::proto;
  20use similar::{ChangeTag, TextDiff};
  21use smol::future::yield_now;
  22use std::{
  23    any::Any,
  24    cell::RefCell,
  25    cmp,
  26    collections::{BTreeMap, HashMap, HashSet},
  27    ffi::OsString,
  28    future::Future,
  29    iter::{Iterator, Peekable},
  30    ops::{Deref, DerefMut, Range},
  31    path::{Path, PathBuf},
  32    str,
  33    sync::Arc,
  34    time::{Duration, Instant, SystemTime, UNIX_EPOCH},
  35    vec,
  36};
  37use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
  38use util::{post_inc, TryFutureExt as _};
  39
  40pub use lsp::DiagnosticSeverity;
  41
  42thread_local! {
  43    static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
  44}
  45
  46lazy_static! {
  47    static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
  48}
  49
  50// TODO - Make this configurable
  51const INDENT_SIZE: u32 = 4;
  52
  53pub struct Buffer {
  54    text: TextBuffer,
  55    file: Option<Box<dyn File>>,
  56    saved_version: clock::Global,
  57    saved_mtime: SystemTime,
  58    language: Option<Arc<Language>>,
  59    autoindent_requests: Vec<Arc<AutoindentRequest>>,
  60    pending_autoindent: Option<Task<()>>,
  61    sync_parse_timeout: Duration,
  62    syntax_tree: Mutex<Option<SyntaxTree>>,
  63    parsing_in_background: bool,
  64    parse_count: usize,
  65    diagnostics: AnchorRangeMultimap<(DiagnosticSeverity, String)>,
  66    language_server: Option<LanguageServerState>,
  67    #[cfg(test)]
  68    operations: Vec<Operation>,
  69}
  70
  71pub struct Snapshot {
  72    text: buffer::Snapshot,
  73    tree: Option<Tree>,
  74    diagnostics: AnchorRangeMultimap<(DiagnosticSeverity, String)>,
  75    is_parsing: bool,
  76    language: Option<Arc<Language>>,
  77    query_cursor: QueryCursorHandle,
  78}
  79
  80#[derive(Debug, PartialEq, Eq)]
  81pub struct Diagnostic {
  82    pub range: Range<Point>,
  83    pub severity: DiagnosticSeverity,
  84    pub message: String,
  85}
  86
  87struct LanguageServerState {
  88    server: Arc<LanguageServer>,
  89    latest_snapshot: watch::Sender<Option<LanguageServerSnapshot>>,
  90    pending_snapshots: BTreeMap<usize, LanguageServerSnapshot>,
  91    next_version: usize,
  92    _maintain_server: Task<Option<()>>,
  93}
  94
  95#[derive(Clone)]
  96struct LanguageServerSnapshot {
  97    buffer_snapshot: buffer::Snapshot,
  98    version: usize,
  99    path: Arc<Path>,
 100}
 101
 102#[derive(Clone, Debug, Eq, PartialEq)]
 103pub enum Event {
 104    Edited,
 105    Dirtied,
 106    Saved,
 107    FileHandleChanged,
 108    Reloaded,
 109    Reparsed,
 110    Closed,
 111}
 112
 113pub trait File {
 114    fn worktree_id(&self) -> usize;
 115
 116    fn entry_id(&self) -> Option<usize>;
 117
 118    fn mtime(&self) -> SystemTime;
 119
 120    /// Returns the path of this file relative to the worktree's root directory.
 121    fn path(&self) -> &Arc<Path>;
 122
 123    /// Returns the absolute path of this file.
 124    fn abs_path(&self, cx: &AppContext) -> Option<PathBuf>;
 125
 126    /// Returns the path of this file relative to the worktree's parent directory (this means it
 127    /// includes the name of the worktree's root folder).
 128    fn full_path(&self, cx: &AppContext) -> PathBuf;
 129
 130    /// Returns the last component of this handle's absolute path. If this handle refers to the root
 131    /// of its worktree, then this method will return the name of the worktree itself.
 132    fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString>;
 133
 134    fn is_deleted(&self) -> bool;
 135
 136    fn save(
 137        &self,
 138        buffer_id: u64,
 139        text: Rope,
 140        version: clock::Global,
 141        cx: &mut MutableAppContext,
 142    ) -> Task<Result<(clock::Global, SystemTime)>>;
 143
 144    fn load_local(&self, cx: &AppContext) -> Option<Task<Result<String>>>;
 145
 146    fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
 147
 148    fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
 149
 150    fn boxed_clone(&self) -> Box<dyn File>;
 151
 152    fn as_any(&self) -> &dyn Any;
 153}
 154
 155struct QueryCursorHandle(Option<QueryCursor>);
 156
 157#[derive(Clone)]
 158struct SyntaxTree {
 159    tree: Tree,
 160    version: clock::Global,
 161}
 162
 163#[derive(Clone)]
 164struct AutoindentRequest {
 165    selection_set_ids: HashSet<SelectionSetId>,
 166    before_edit: Snapshot,
 167    edited: AnchorSet,
 168    inserted: Option<AnchorRangeSet>,
 169}
 170
 171#[derive(Debug)]
 172struct IndentSuggestion {
 173    basis_row: u32,
 174    indent: bool,
 175}
 176
 177struct TextProvider<'a>(&'a Rope);
 178
 179struct Highlights<'a> {
 180    captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
 181    next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
 182    stack: Vec<(usize, HighlightId)>,
 183    highlight_map: HighlightMap,
 184}
 185
 186pub struct HighlightedChunks<'a> {
 187    range: Range<usize>,
 188    chunks: Chunks<'a>,
 189    diagnostic_endpoints: Peekable<vec::IntoIter<DiagnosticEndpoint>>,
 190    error_depth: usize,
 191    warning_depth: usize,
 192    information_depth: usize,
 193    hint_depth: usize,
 194    highlights: Option<Highlights<'a>>,
 195}
 196
 197#[derive(Clone, Copy, Debug, Default)]
 198pub struct HighlightedChunk<'a> {
 199    pub text: &'a str,
 200    pub highlight_id: HighlightId,
 201    pub diagnostic: Option<DiagnosticSeverity>,
 202}
 203
 204struct Diff {
 205    base_version: clock::Global,
 206    new_text: Arc<str>,
 207    changes: Vec<(ChangeTag, usize)>,
 208}
 209
 210#[derive(Clone, Copy)]
 211struct DiagnosticEndpoint {
 212    offset: usize,
 213    is_start: bool,
 214    severity: DiagnosticSeverity,
 215}
 216
 217impl Buffer {
 218    pub fn new<T: Into<Arc<str>>>(
 219        replica_id: ReplicaId,
 220        base_text: T,
 221        cx: &mut ModelContext<Self>,
 222    ) -> Self {
 223        Self::build(
 224            TextBuffer::new(
 225                replica_id,
 226                cx.model_id() as u64,
 227                History::new(base_text.into()),
 228            ),
 229            None,
 230        )
 231    }
 232
 233    pub fn from_file<T: Into<Arc<str>>>(
 234        replica_id: ReplicaId,
 235        base_text: T,
 236        file: Box<dyn File>,
 237        cx: &mut ModelContext<Self>,
 238    ) -> Self {
 239        Self::build(
 240            TextBuffer::new(
 241                replica_id,
 242                cx.model_id() as u64,
 243                History::new(base_text.into()),
 244            ),
 245            Some(file),
 246        )
 247    }
 248
 249    pub fn from_proto(
 250        replica_id: ReplicaId,
 251        message: proto::Buffer,
 252        file: Option<Box<dyn File>>,
 253    ) -> Result<Self> {
 254        Ok(Self::build(
 255            TextBuffer::from_proto(replica_id, message)?,
 256            file,
 257        ))
 258    }
 259
 260    pub fn with_language(
 261        mut self,
 262        language: Option<Arc<Language>>,
 263        language_server: Option<Arc<LanguageServer>>,
 264        cx: &mut ModelContext<Self>,
 265    ) -> Self {
 266        self.set_language(language, language_server, cx);
 267        self
 268    }
 269
 270    fn build(buffer: TextBuffer, file: Option<Box<dyn File>>) -> Self {
 271        let saved_mtime;
 272        if let Some(file) = file.as_ref() {
 273            saved_mtime = file.mtime();
 274        } else {
 275            saved_mtime = UNIX_EPOCH;
 276        }
 277
 278        Self {
 279            text: buffer,
 280            saved_mtime,
 281            saved_version: clock::Global::new(),
 282            file,
 283            syntax_tree: Mutex::new(None),
 284            parsing_in_background: false,
 285            parse_count: 0,
 286            sync_parse_timeout: Duration::from_millis(1),
 287            autoindent_requests: Default::default(),
 288            pending_autoindent: Default::default(),
 289            language: None,
 290            diagnostics: Default::default(),
 291            language_server: None,
 292            #[cfg(test)]
 293            operations: Default::default(),
 294        }
 295    }
 296
 297    pub fn snapshot(&self) -> Snapshot {
 298        Snapshot {
 299            text: self.text.snapshot(),
 300            tree: self.syntax_tree(),
 301            diagnostics: self.diagnostics.clone(),
 302            is_parsing: self.parsing_in_background,
 303            language: self.language.clone(),
 304            query_cursor: QueryCursorHandle::new(),
 305        }
 306    }
 307
 308    pub fn file(&self) -> Option<&dyn File> {
 309        self.file.as_deref()
 310    }
 311
 312    pub fn save(
 313        &mut self,
 314        cx: &mut ModelContext<Self>,
 315    ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
 316        let file = self
 317            .file
 318            .as_ref()
 319            .ok_or_else(|| anyhow!("buffer has no file"))?;
 320        let text = self.as_rope().clone();
 321        let version = self.version.clone();
 322        let save = file.save(self.remote_id(), text, version, cx.as_mut());
 323        Ok(cx.spawn(|this, mut cx| async move {
 324            let (version, mtime) = save.await?;
 325            this.update(&mut cx, |this, cx| {
 326                this.did_save(version.clone(), mtime, None, cx);
 327            });
 328            Ok((version, mtime))
 329        }))
 330    }
 331
 332    pub fn set_language(
 333        &mut self,
 334        language: Option<Arc<Language>>,
 335        language_server: Option<Arc<lsp::LanguageServer>>,
 336        cx: &mut ModelContext<Self>,
 337    ) {
 338        self.language = language;
 339        self.language_server = if let Some(server) = language_server {
 340            let (latest_snapshot_tx, mut latest_snapshot_rx) = watch::channel();
 341            Some(LanguageServerState {
 342                latest_snapshot: latest_snapshot_tx,
 343                pending_snapshots: Default::default(),
 344                next_version: 0,
 345                server: server.clone(),
 346                _maintain_server: cx.background().spawn(
 347                    async move {
 348                        let mut prev_snapshot: Option<LanguageServerSnapshot> = None;
 349                        while let Some(snapshot) = latest_snapshot_rx.recv().await {
 350                            if let Some(snapshot) = snapshot {
 351                                let uri = lsp::Url::from_file_path(&snapshot.path).unwrap();
 352                                if let Some(prev_snapshot) = prev_snapshot {
 353                                    let changes = lsp::DidChangeTextDocumentParams {
 354                                        text_document: lsp::VersionedTextDocumentIdentifier::new(
 355                                            uri,
 356                                            snapshot.version as i32,
 357                                        ),
 358                                        content_changes: snapshot
 359                                            .buffer_snapshot
 360                                            .edits_since(
 361                                                prev_snapshot.buffer_snapshot.version().clone(),
 362                                            )
 363                                            .map(|edit| {
 364                                                lsp::TextDocumentContentChangeEvent {
 365                                                    // TODO: Use UTF-16 positions.
 366                                                    range: Some(lsp::Range::new(
 367                                                        lsp::Position::new(
 368                                                            edit.old_lines.start.row,
 369                                                            edit.old_lines.start.column,
 370                                                        ),
 371                                                        lsp::Position::new(
 372                                                            edit.old_lines.end.row,
 373                                                            edit.old_lines.end.column,
 374                                                        ),
 375                                                    )),
 376                                                    range_length: None,
 377                                                    text: snapshot
 378                                                        .buffer_snapshot
 379                                                        .text_for_range(edit.new_bytes)
 380                                                        .collect(),
 381                                                }
 382                                            })
 383                                            .collect(),
 384                                    };
 385                                    server
 386                                        .notify::<lsp::notification::DidChangeTextDocument>(changes)
 387                                        .await?;
 388                                } else {
 389                                    server
 390                                        .notify::<lsp::notification::DidOpenTextDocument>(
 391                                            lsp::DidOpenTextDocumentParams {
 392                                                text_document: lsp::TextDocumentItem::new(
 393                                                    uri,
 394                                                    Default::default(),
 395                                                    snapshot.version as i32,
 396                                                    snapshot.buffer_snapshot.text().into(),
 397                                                ),
 398                                            },
 399                                        )
 400                                        .await?;
 401                                }
 402
 403                                prev_snapshot = Some(snapshot);
 404                            }
 405                        }
 406                        Ok(())
 407                    }
 408                    .log_err(),
 409                ),
 410            })
 411        } else {
 412            None
 413        };
 414
 415        self.reparse(cx);
 416        self.update_language_server(cx);
 417    }
 418
 419    pub fn did_save(
 420        &mut self,
 421        version: clock::Global,
 422        mtime: SystemTime,
 423        new_file: Option<Box<dyn File>>,
 424        cx: &mut ModelContext<Self>,
 425    ) {
 426        self.saved_mtime = mtime;
 427        self.saved_version = version;
 428        if let Some(new_file) = new_file {
 429            self.file = Some(new_file);
 430        }
 431        if let Some(state) = &self.language_server {
 432            cx.background()
 433                .spawn(
 434                    state
 435                        .server
 436                        .notify::<lsp::notification::DidSaveTextDocument>(
 437                            lsp::DidSaveTextDocumentParams {
 438                                text_document: lsp::TextDocumentIdentifier {
 439                                    uri: lsp::Url::from_file_path(
 440                                        self.file.as_ref().unwrap().abs_path(cx).unwrap(),
 441                                    )
 442                                    .unwrap(),
 443                                },
 444                                text: None,
 445                            },
 446                        ),
 447                )
 448                .detach()
 449        }
 450        cx.emit(Event::Saved);
 451    }
 452
 453    pub fn file_updated(
 454        &mut self,
 455        new_file: Box<dyn File>,
 456        cx: &mut ModelContext<Self>,
 457    ) -> Option<Task<()>> {
 458        let old_file = self.file.as_ref()?;
 459        let mut file_changed = false;
 460        let mut task = None;
 461
 462        if new_file.path() != old_file.path() {
 463            file_changed = true;
 464        }
 465
 466        if new_file.is_deleted() {
 467            if !old_file.is_deleted() {
 468                file_changed = true;
 469                if !self.is_dirty() {
 470                    cx.emit(Event::Dirtied);
 471                }
 472            }
 473        } else {
 474            let new_mtime = new_file.mtime();
 475            if new_mtime != old_file.mtime() {
 476                file_changed = true;
 477
 478                if !self.is_dirty() {
 479                    task = Some(cx.spawn(|this, mut cx| {
 480                        async move {
 481                            let new_text = this.read_with(&cx, |this, cx| {
 482                                this.file.as_ref().and_then(|file| file.load_local(cx))
 483                            });
 484                            if let Some(new_text) = new_text {
 485                                let new_text = new_text.await?;
 486                                let diff = this
 487                                    .read_with(&cx, |this, cx| this.diff(new_text.into(), cx))
 488                                    .await;
 489                                this.update(&mut cx, |this, cx| {
 490                                    if this.apply_diff(diff, cx) {
 491                                        this.saved_version = this.version.clone();
 492                                        this.saved_mtime = new_mtime;
 493                                        cx.emit(Event::Reloaded);
 494                                    }
 495                                });
 496                            }
 497                            Ok(())
 498                        }
 499                        .log_err()
 500                        .map(drop)
 501                    }));
 502                }
 503            }
 504        }
 505
 506        if file_changed {
 507            cx.emit(Event::FileHandleChanged);
 508        }
 509        self.file = Some(new_file);
 510        task
 511    }
 512
 513    pub fn close(&mut self, cx: &mut ModelContext<Self>) {
 514        cx.emit(Event::Closed);
 515    }
 516
 517    pub fn language(&self) -> Option<&Arc<Language>> {
 518        self.language.as_ref()
 519    }
 520
 521    pub fn parse_count(&self) -> usize {
 522        self.parse_count
 523    }
 524
 525    fn syntax_tree(&self) -> Option<Tree> {
 526        if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
 527            self.interpolate_tree(syntax_tree);
 528            Some(syntax_tree.tree.clone())
 529        } else {
 530            None
 531        }
 532    }
 533
 534    #[cfg(any(test, feature = "test-support"))]
 535    pub fn is_parsing(&self) -> bool {
 536        self.parsing_in_background
 537    }
 538
 539    #[cfg(test)]
 540    pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
 541        self.sync_parse_timeout = timeout;
 542    }
 543
 544    fn reparse(&mut self, cx: &mut ModelContext<Self>) -> bool {
 545        if self.parsing_in_background {
 546            return false;
 547        }
 548
 549        if let Some(language) = self.language.clone() {
 550            let old_tree = self.syntax_tree();
 551            let text = self.as_rope().clone();
 552            let parsed_version = self.version();
 553            let parse_task = cx.background().spawn({
 554                let language = language.clone();
 555                async move { Self::parse_text(&text, old_tree, &language) }
 556            });
 557
 558            match cx
 559                .background()
 560                .block_with_timeout(self.sync_parse_timeout, parse_task)
 561            {
 562                Ok(new_tree) => {
 563                    self.did_finish_parsing(new_tree, parsed_version, cx);
 564                    return true;
 565                }
 566                Err(parse_task) => {
 567                    self.parsing_in_background = true;
 568                    cx.spawn(move |this, mut cx| async move {
 569                        let new_tree = parse_task.await;
 570                        this.update(&mut cx, move |this, cx| {
 571                            let language_changed =
 572                                this.language.as_ref().map_or(true, |curr_language| {
 573                                    !Arc::ptr_eq(curr_language, &language)
 574                                });
 575                            let parse_again = this.version > parsed_version || language_changed;
 576                            this.parsing_in_background = false;
 577                            this.did_finish_parsing(new_tree, parsed_version, cx);
 578
 579                            if parse_again && this.reparse(cx) {
 580                                return;
 581                            }
 582                        });
 583                    })
 584                    .detach();
 585                }
 586            }
 587        }
 588        false
 589    }
 590
 591    fn parse_text(text: &Rope, old_tree: Option<Tree>, language: &Language) -> Tree {
 592        PARSER.with(|parser| {
 593            let mut parser = parser.borrow_mut();
 594            parser
 595                .set_language(language.grammar)
 596                .expect("incompatible grammar");
 597            let mut chunks = text.chunks_in_range(0..text.len());
 598            let tree = parser
 599                .parse_with(
 600                    &mut move |offset, _| {
 601                        chunks.seek(offset);
 602                        chunks.next().unwrap_or("").as_bytes()
 603                    },
 604                    old_tree.as_ref(),
 605                )
 606                .unwrap();
 607            tree
 608        })
 609    }
 610
 611    fn interpolate_tree(&self, tree: &mut SyntaxTree) {
 612        let mut delta = 0_isize;
 613        for edit in self.edits_since(tree.version.clone()) {
 614            let start_offset = (edit.old_bytes.start as isize + delta) as usize;
 615            let start_point = self.as_rope().to_point(start_offset);
 616            tree.tree.edit(&InputEdit {
 617                start_byte: start_offset,
 618                old_end_byte: start_offset + edit.deleted_bytes(),
 619                new_end_byte: start_offset + edit.inserted_bytes(),
 620                start_position: start_point.to_ts_point(),
 621                old_end_position: (start_point + edit.deleted_lines()).to_ts_point(),
 622                new_end_position: self
 623                    .as_rope()
 624                    .to_point(start_offset + edit.inserted_bytes())
 625                    .to_ts_point(),
 626            });
 627            delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
 628        }
 629        tree.version = self.version();
 630    }
 631
 632    fn did_finish_parsing(
 633        &mut self,
 634        tree: Tree,
 635        version: clock::Global,
 636        cx: &mut ModelContext<Self>,
 637    ) {
 638        self.parse_count += 1;
 639        *self.syntax_tree.lock() = Some(SyntaxTree { tree, version });
 640        self.request_autoindent(cx);
 641        cx.emit(Event::Reparsed);
 642        cx.notify();
 643    }
 644
 645    pub fn update_diagnostics(
 646        &mut self,
 647        version: Option<i32>,
 648        diagnostics: Vec<lsp::Diagnostic>,
 649        cx: &mut ModelContext<Self>,
 650    ) -> Result<()> {
 651        let version = version.map(|version| version as usize);
 652        let content = if let Some(version) = version {
 653            let language_server = self.language_server.as_mut().unwrap();
 654            let snapshot = language_server
 655                .pending_snapshots
 656                .get(&version)
 657                .ok_or_else(|| anyhow!("missing snapshot"))?;
 658            snapshot.buffer_snapshot.content()
 659        } else {
 660            self.content()
 661        };
 662        self.diagnostics = content.anchor_range_multimap(
 663            Bias::Left,
 664            Bias::Right,
 665            diagnostics.into_iter().map(|diagnostic| {
 666                // TODO: Use UTF-16 positions.
 667                let start = Point::new(
 668                    diagnostic.range.start.line,
 669                    diagnostic.range.start.character,
 670                );
 671                let end = Point::new(diagnostic.range.end.line, diagnostic.range.end.character);
 672                let severity = diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR);
 673                (start..end, (severity, diagnostic.message))
 674            }),
 675        );
 676
 677        if let Some(version) = version {
 678            let language_server = self.language_server.as_mut().unwrap();
 679            let versions_to_delete = language_server
 680                .pending_snapshots
 681                .range(..version)
 682                .map(|(v, _)| *v)
 683                .collect::<Vec<_>>();
 684            for version in versions_to_delete {
 685                language_server.pending_snapshots.remove(&version);
 686            }
 687        }
 688
 689        cx.notify();
 690        Ok(())
 691    }
 692
 693    pub fn diagnostics_in_range<'a, T: ToOffset>(
 694        &'a self,
 695        range: Range<T>,
 696    ) -> impl Iterator<Item = Diagnostic> + 'a {
 697        let content = self.content();
 698        let range = range.start.to_offset(&content)..range.end.to_offset(&content);
 699        self.diagnostics
 700            .intersecting_ranges(range, content, true)
 701            .map(move |(_, range, (severity, message))| Diagnostic {
 702                range,
 703                severity: *severity,
 704                message: message.clone(),
 705            })
 706    }
 707
 708    fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
 709        if let Some(indent_columns) = self.compute_autoindents() {
 710            let indent_columns = cx.background().spawn(indent_columns);
 711            match cx
 712                .background()
 713                .block_with_timeout(Duration::from_micros(500), indent_columns)
 714            {
 715                Ok(indent_columns) => self.apply_autoindents(indent_columns, cx),
 716                Err(indent_columns) => {
 717                    self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
 718                        let indent_columns = indent_columns.await;
 719                        this.update(&mut cx, |this, cx| {
 720                            this.apply_autoindents(indent_columns, cx);
 721                        });
 722                    }));
 723                }
 724            }
 725        }
 726    }
 727
 728    fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, u32>>> {
 729        let max_rows_between_yields = 100;
 730        let snapshot = self.snapshot();
 731        if snapshot.language.is_none()
 732            || snapshot.tree.is_none()
 733            || self.autoindent_requests.is_empty()
 734        {
 735            return None;
 736        }
 737
 738        let autoindent_requests = self.autoindent_requests.clone();
 739        Some(async move {
 740            let mut indent_columns = BTreeMap::new();
 741            for request in autoindent_requests {
 742                let old_to_new_rows = request
 743                    .edited
 744                    .to_points(&request.before_edit)
 745                    .map(|point| point.row)
 746                    .zip(request.edited.to_points(&snapshot).map(|point| point.row))
 747                    .collect::<BTreeMap<u32, u32>>();
 748
 749                let mut old_suggestions = HashMap::<u32, u32>::default();
 750                let old_edited_ranges =
 751                    contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
 752                for old_edited_range in old_edited_ranges {
 753                    let suggestions = request
 754                        .before_edit
 755                        .suggest_autoindents(old_edited_range.clone())
 756                        .into_iter()
 757                        .flatten();
 758                    for (old_row, suggestion) in old_edited_range.zip(suggestions) {
 759                        let indentation_basis = old_to_new_rows
 760                            .get(&suggestion.basis_row)
 761                            .and_then(|from_row| old_suggestions.get(from_row).copied())
 762                            .unwrap_or_else(|| {
 763                                request
 764                                    .before_edit
 765                                    .indent_column_for_line(suggestion.basis_row)
 766                            });
 767                        let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
 768                        old_suggestions.insert(
 769                            *old_to_new_rows.get(&old_row).unwrap(),
 770                            indentation_basis + delta,
 771                        );
 772                    }
 773                    yield_now().await;
 774                }
 775
 776                // At this point, old_suggestions contains the suggested indentation for all edited lines with respect to the state of the
 777                // buffer before the edit, but keyed by the row for these lines after the edits were applied.
 778                let new_edited_row_ranges =
 779                    contiguous_ranges(old_to_new_rows.values().copied(), max_rows_between_yields);
 780                for new_edited_row_range in new_edited_row_ranges {
 781                    let suggestions = snapshot
 782                        .suggest_autoindents(new_edited_row_range.clone())
 783                        .into_iter()
 784                        .flatten();
 785                    for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
 786                        let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
 787                        let new_indentation = indent_columns
 788                            .get(&suggestion.basis_row)
 789                            .copied()
 790                            .unwrap_or_else(|| {
 791                                snapshot.indent_column_for_line(suggestion.basis_row)
 792                            })
 793                            + delta;
 794                        if old_suggestions
 795                            .get(&new_row)
 796                            .map_or(true, |old_indentation| new_indentation != *old_indentation)
 797                        {
 798                            indent_columns.insert(new_row, new_indentation);
 799                        }
 800                    }
 801                    yield_now().await;
 802                }
 803
 804                if let Some(inserted) = request.inserted.as_ref() {
 805                    let inserted_row_ranges = contiguous_ranges(
 806                        inserted
 807                            .to_point_ranges(&snapshot)
 808                            .flat_map(|range| range.start.row..range.end.row + 1),
 809                        max_rows_between_yields,
 810                    );
 811                    for inserted_row_range in inserted_row_ranges {
 812                        let suggestions = snapshot
 813                            .suggest_autoindents(inserted_row_range.clone())
 814                            .into_iter()
 815                            .flatten();
 816                        for (row, suggestion) in inserted_row_range.zip(suggestions) {
 817                            let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
 818                            let new_indentation = indent_columns
 819                                .get(&suggestion.basis_row)
 820                                .copied()
 821                                .unwrap_or_else(|| {
 822                                    snapshot.indent_column_for_line(suggestion.basis_row)
 823                                })
 824                                + delta;
 825                            indent_columns.insert(row, new_indentation);
 826                        }
 827                        yield_now().await;
 828                    }
 829                }
 830            }
 831            indent_columns
 832        })
 833    }
 834
 835    fn apply_autoindents(
 836        &mut self,
 837        indent_columns: BTreeMap<u32, u32>,
 838        cx: &mut ModelContext<Self>,
 839    ) {
 840        let selection_set_ids = self
 841            .autoindent_requests
 842            .drain(..)
 843            .flat_map(|req| req.selection_set_ids.clone())
 844            .collect::<HashSet<_>>();
 845
 846        self.start_transaction(selection_set_ids.iter().copied())
 847            .unwrap();
 848        for (row, indent_column) in &indent_columns {
 849            self.set_indent_column_for_line(*row, *indent_column, cx);
 850        }
 851
 852        for selection_set_id in &selection_set_ids {
 853            if let Ok(set) = self.selection_set(*selection_set_id) {
 854                let new_selections = set
 855                    .selections
 856                    .iter()
 857                    .map(|selection| {
 858                        let start_point = selection.start.to_point(&self.text);
 859                        if start_point.column == 0 {
 860                            let end_point = selection.end.to_point(&self.text);
 861                            let delta = Point::new(
 862                                0,
 863                                indent_columns.get(&start_point.row).copied().unwrap_or(0),
 864                            );
 865                            if delta.column > 0 {
 866                                return Selection {
 867                                    id: selection.id,
 868                                    goal: selection.goal,
 869                                    reversed: selection.reversed,
 870                                    start: self
 871                                        .anchor_at(start_point + delta, selection.start.bias),
 872                                    end: self.anchor_at(end_point + delta, selection.end.bias),
 873                                };
 874                            }
 875                        }
 876                        selection.clone()
 877                    })
 878                    .collect::<Arc<[_]>>();
 879                self.update_selection_set(*selection_set_id, new_selections, cx)
 880                    .unwrap();
 881            }
 882        }
 883
 884        self.end_transaction(selection_set_ids.iter().copied(), cx)
 885            .unwrap();
 886    }
 887
 888    pub fn indent_column_for_line(&self, row: u32) -> u32 {
 889        self.content().indent_column_for_line(row)
 890    }
 891
 892    fn set_indent_column_for_line(&mut self, row: u32, column: u32, cx: &mut ModelContext<Self>) {
 893        let current_column = self.indent_column_for_line(row);
 894        if column > current_column {
 895            let offset = Point::new(row, 0).to_offset(&*self);
 896            self.edit(
 897                [offset..offset],
 898                " ".repeat((column - current_column) as usize),
 899                cx,
 900            );
 901        } else if column < current_column {
 902            self.edit(
 903                [Point::new(row, 0)..Point::new(row, current_column - column)],
 904                "",
 905                cx,
 906            );
 907        }
 908    }
 909
 910    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
 911        if let Some(tree) = self.syntax_tree() {
 912            let root = tree.root_node();
 913            let range = range.start.to_offset(self)..range.end.to_offset(self);
 914            let mut node = root.descendant_for_byte_range(range.start, range.end);
 915            while node.map_or(false, |n| n.byte_range() == range) {
 916                node = node.unwrap().parent();
 917            }
 918            node.map(|n| n.byte_range())
 919        } else {
 920            None
 921        }
 922    }
 923
 924    pub fn enclosing_bracket_ranges<T: ToOffset>(
 925        &self,
 926        range: Range<T>,
 927    ) -> Option<(Range<usize>, Range<usize>)> {
 928        let (lang, tree) = self.language.as_ref().zip(self.syntax_tree())?;
 929        let open_capture_ix = lang.brackets_query.capture_index_for_name("open")?;
 930        let close_capture_ix = lang.brackets_query.capture_index_for_name("close")?;
 931
 932        // Find bracket pairs that *inclusively* contain the given range.
 933        let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
 934        let mut cursor = QueryCursorHandle::new();
 935        let matches = cursor.set_byte_range(range).matches(
 936            &lang.brackets_query,
 937            tree.root_node(),
 938            TextProvider(self.as_rope()),
 939        );
 940
 941        // Get the ranges of the innermost pair of brackets.
 942        matches
 943            .filter_map(|mat| {
 944                let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
 945                let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
 946                Some((open.byte_range(), close.byte_range()))
 947            })
 948            .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
 949    }
 950
 951    fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
 952        // TODO: it would be nice to not allocate here.
 953        let old_text = self.text();
 954        let base_version = self.version();
 955        cx.background().spawn(async move {
 956            let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
 957                .iter_all_changes()
 958                .map(|c| (c.tag(), c.value().len()))
 959                .collect::<Vec<_>>();
 960            Diff {
 961                base_version,
 962                new_text,
 963                changes,
 964            }
 965        })
 966    }
 967
 968    fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> bool {
 969        if self.version == diff.base_version {
 970            self.start_transaction(None).unwrap();
 971            let mut offset = 0;
 972            for (tag, len) in diff.changes {
 973                let range = offset..(offset + len);
 974                match tag {
 975                    ChangeTag::Equal => offset += len,
 976                    ChangeTag::Delete => self.edit(Some(range), "", cx),
 977                    ChangeTag::Insert => {
 978                        self.edit(Some(offset..offset), &diff.new_text[range], cx);
 979                        offset += len;
 980                    }
 981                }
 982            }
 983            self.end_transaction(None, cx).unwrap();
 984            true
 985        } else {
 986            false
 987        }
 988    }
 989
 990    pub fn is_dirty(&self) -> bool {
 991        self.version > self.saved_version
 992            || self.file.as_ref().map_or(false, |file| file.is_deleted())
 993    }
 994
 995    pub fn has_conflict(&self) -> bool {
 996        self.version > self.saved_version
 997            && self
 998                .file
 999                .as_ref()
1000                .map_or(false, |file| file.mtime() > self.saved_mtime)
1001    }
1002
1003    pub fn start_transaction(
1004        &mut self,
1005        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
1006    ) -> Result<()> {
1007        self.start_transaction_at(selection_set_ids, Instant::now())
1008    }
1009
1010    fn start_transaction_at(
1011        &mut self,
1012        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
1013        now: Instant,
1014    ) -> Result<()> {
1015        self.text.start_transaction_at(selection_set_ids, now)
1016    }
1017
1018    pub fn end_transaction(
1019        &mut self,
1020        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
1021        cx: &mut ModelContext<Self>,
1022    ) -> Result<()> {
1023        self.end_transaction_at(selection_set_ids, Instant::now(), cx)
1024    }
1025
1026    fn end_transaction_at(
1027        &mut self,
1028        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
1029        now: Instant,
1030        cx: &mut ModelContext<Self>,
1031    ) -> Result<()> {
1032        if let Some(start_version) = self.text.end_transaction_at(selection_set_ids, now) {
1033            let was_dirty = start_version != self.saved_version;
1034            self.did_edit(start_version, was_dirty, cx);
1035        }
1036        Ok(())
1037    }
1038
1039    fn update_language_server(&mut self, cx: &AppContext) {
1040        let language_server = if let Some(language_server) = self.language_server.as_mut() {
1041            language_server
1042        } else {
1043            return;
1044        };
1045        let abs_path = self
1046            .file
1047            .as_ref()
1048            .map_or(Path::new("/").to_path_buf(), |file| {
1049                file.abs_path(cx).unwrap()
1050            });
1051
1052        let version = post_inc(&mut language_server.next_version);
1053        let snapshot = LanguageServerSnapshot {
1054            buffer_snapshot: self.text.snapshot(),
1055            version,
1056            path: Arc::from(abs_path),
1057        };
1058        language_server
1059            .pending_snapshots
1060            .insert(version, snapshot.clone());
1061        let _ = language_server
1062            .latest_snapshot
1063            .blocking_send(Some(snapshot));
1064    }
1065
1066    pub fn edit<I, S, T>(&mut self, ranges_iter: I, new_text: T, cx: &mut ModelContext<Self>)
1067    where
1068        I: IntoIterator<Item = Range<S>>,
1069        S: ToOffset,
1070        T: Into<String>,
1071    {
1072        self.edit_internal(ranges_iter, new_text, false, cx)
1073    }
1074
1075    pub fn edit_with_autoindent<I, S, T>(
1076        &mut self,
1077        ranges_iter: I,
1078        new_text: T,
1079        cx: &mut ModelContext<Self>,
1080    ) where
1081        I: IntoIterator<Item = Range<S>>,
1082        S: ToOffset,
1083        T: Into<String>,
1084    {
1085        self.edit_internal(ranges_iter, new_text, true, cx)
1086    }
1087
1088    pub fn edit_internal<I, S, T>(
1089        &mut self,
1090        ranges_iter: I,
1091        new_text: T,
1092        autoindent: bool,
1093        cx: &mut ModelContext<Self>,
1094    ) where
1095        I: IntoIterator<Item = Range<S>>,
1096        S: ToOffset,
1097        T: Into<String>,
1098    {
1099        let new_text = new_text.into();
1100
1101        // Skip invalid ranges and coalesce contiguous ones.
1102        let mut ranges: Vec<Range<usize>> = Vec::new();
1103        for range in ranges_iter {
1104            let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
1105            if !new_text.is_empty() || !range.is_empty() {
1106                if let Some(prev_range) = ranges.last_mut() {
1107                    if prev_range.end >= range.start {
1108                        prev_range.end = cmp::max(prev_range.end, range.end);
1109                    } else {
1110                        ranges.push(range);
1111                    }
1112                } else {
1113                    ranges.push(range);
1114                }
1115            }
1116        }
1117        if ranges.is_empty() {
1118            return;
1119        }
1120
1121        self.start_transaction(None).unwrap();
1122        self.pending_autoindent.take();
1123        let autoindent_request = if autoindent && self.language.is_some() {
1124            let before_edit = self.snapshot();
1125            let edited = self.content().anchor_set(ranges.iter().filter_map(|range| {
1126                let start = range.start.to_point(&*self);
1127                if new_text.starts_with('\n') && start.column == self.line_len(start.row) {
1128                    None
1129                } else {
1130                    Some((range.start, Bias::Left))
1131                }
1132            }));
1133            Some((before_edit, edited))
1134        } else {
1135            None
1136        };
1137
1138        let first_newline_ix = new_text.find('\n');
1139        let new_text_len = new_text.len();
1140
1141        let edit = self.text.edit(ranges.iter().cloned(), new_text);
1142
1143        if let Some((before_edit, edited)) = autoindent_request {
1144            let mut inserted = None;
1145            if let Some(first_newline_ix) = first_newline_ix {
1146                let mut delta = 0isize;
1147                inserted = Some(self.content().anchor_range_set(ranges.iter().map(|range| {
1148                    let start = (delta + range.start as isize) as usize + first_newline_ix + 1;
1149                    let end = (delta + range.start as isize) as usize + new_text_len;
1150                    delta += (range.end as isize - range.start as isize) + new_text_len as isize;
1151                    (start, Bias::Left)..(end, Bias::Right)
1152                })));
1153            }
1154
1155            let selection_set_ids = self
1156                .text
1157                .peek_undo_stack()
1158                .unwrap()
1159                .starting_selection_set_ids()
1160                .collect();
1161            self.autoindent_requests.push(Arc::new(AutoindentRequest {
1162                selection_set_ids,
1163                before_edit,
1164                edited,
1165                inserted,
1166            }));
1167        }
1168
1169        self.end_transaction(None, cx).unwrap();
1170        self.send_operation(Operation::Edit(edit), cx);
1171    }
1172
1173    fn did_edit(
1174        &mut self,
1175        old_version: clock::Global,
1176        was_dirty: bool,
1177        cx: &mut ModelContext<Self>,
1178    ) {
1179        if self.edits_since(old_version).next().is_none() {
1180            return;
1181        }
1182
1183        self.reparse(cx);
1184        self.update_language_server(cx);
1185
1186        cx.emit(Event::Edited);
1187        if !was_dirty {
1188            cx.emit(Event::Dirtied);
1189        }
1190        cx.notify();
1191    }
1192
1193    pub fn add_selection_set(
1194        &mut self,
1195        selections: impl Into<Arc<[Selection]>>,
1196        cx: &mut ModelContext<Self>,
1197    ) -> SelectionSetId {
1198        let operation = self.text.add_selection_set(selections);
1199        if let Operation::UpdateSelections { set_id, .. } = &operation {
1200            let set_id = *set_id;
1201            cx.notify();
1202            self.send_operation(operation, cx);
1203            set_id
1204        } else {
1205            unreachable!()
1206        }
1207    }
1208
1209    pub fn update_selection_set(
1210        &mut self,
1211        set_id: SelectionSetId,
1212        selections: impl Into<Arc<[Selection]>>,
1213        cx: &mut ModelContext<Self>,
1214    ) -> Result<()> {
1215        let operation = self.text.update_selection_set(set_id, selections)?;
1216        cx.notify();
1217        self.send_operation(operation, cx);
1218        Ok(())
1219    }
1220
1221    pub fn set_active_selection_set(
1222        &mut self,
1223        set_id: Option<SelectionSetId>,
1224        cx: &mut ModelContext<Self>,
1225    ) -> Result<()> {
1226        let operation = self.text.set_active_selection_set(set_id)?;
1227        self.send_operation(operation, cx);
1228        Ok(())
1229    }
1230
1231    pub fn remove_selection_set(
1232        &mut self,
1233        set_id: SelectionSetId,
1234        cx: &mut ModelContext<Self>,
1235    ) -> Result<()> {
1236        let operation = self.text.remove_selection_set(set_id)?;
1237        cx.notify();
1238        self.send_operation(operation, cx);
1239        Ok(())
1240    }
1241
1242    pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1243        &mut self,
1244        ops: I,
1245        cx: &mut ModelContext<Self>,
1246    ) -> Result<()> {
1247        self.pending_autoindent.take();
1248        let was_dirty = self.is_dirty();
1249        let old_version = self.version.clone();
1250        self.text.apply_ops(ops)?;
1251        self.did_edit(old_version, was_dirty, cx);
1252        Ok(())
1253    }
1254
1255    #[cfg(not(test))]
1256    pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1257        if let Some(file) = &self.file {
1258            file.buffer_updated(self.remote_id(), operation, cx.as_mut());
1259        }
1260    }
1261
1262    #[cfg(test)]
1263    pub fn send_operation(&mut self, operation: Operation, _: &mut ModelContext<Self>) {
1264        self.operations.push(operation);
1265    }
1266
1267    pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1268        self.text.remove_peer(replica_id);
1269        cx.notify();
1270    }
1271
1272    pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
1273        let was_dirty = self.is_dirty();
1274        let old_version = self.version.clone();
1275
1276        for operation in self.text.undo() {
1277            self.send_operation(operation, cx);
1278        }
1279
1280        self.did_edit(old_version, was_dirty, cx);
1281    }
1282
1283    pub fn redo(&mut self, cx: &mut ModelContext<Self>) {
1284        let was_dirty = self.is_dirty();
1285        let old_version = self.version.clone();
1286
1287        for operation in self.text.redo() {
1288            self.send_operation(operation, cx);
1289        }
1290
1291        self.did_edit(old_version, was_dirty, cx);
1292    }
1293}
1294
1295#[cfg(any(test, feature = "test-support"))]
1296impl Buffer {
1297    pub fn randomly_edit<T>(&mut self, rng: &mut T, old_range_count: usize)
1298    where
1299        T: rand::Rng,
1300    {
1301        self.text.randomly_edit(rng, old_range_count);
1302    }
1303
1304    pub fn randomly_mutate<T>(&mut self, rng: &mut T)
1305    where
1306        T: rand::Rng,
1307    {
1308        self.text.randomly_mutate(rng);
1309    }
1310}
1311
1312impl Entity for Buffer {
1313    type Event = Event;
1314
1315    fn release(&mut self, cx: &mut gpui::MutableAppContext) {
1316        if let Some(file) = self.file.as_ref() {
1317            file.buffer_removed(self.remote_id(), cx);
1318        }
1319    }
1320}
1321
1322// TODO: Do we need to clone a buffer?
1323impl Clone for Buffer {
1324    fn clone(&self) -> Self {
1325        Self {
1326            text: self.text.clone(),
1327            saved_version: self.saved_version.clone(),
1328            saved_mtime: self.saved_mtime,
1329            file: self.file.as_ref().map(|f| f.boxed_clone()),
1330            language: self.language.clone(),
1331            syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
1332            parsing_in_background: false,
1333            sync_parse_timeout: self.sync_parse_timeout,
1334            parse_count: self.parse_count,
1335            autoindent_requests: Default::default(),
1336            pending_autoindent: Default::default(),
1337            diagnostics: self.diagnostics.clone(),
1338            language_server: None,
1339            #[cfg(test)]
1340            operations: self.operations.clone(),
1341        }
1342    }
1343}
1344
1345impl Deref for Buffer {
1346    type Target = TextBuffer;
1347
1348    fn deref(&self) -> &Self::Target {
1349        &self.text
1350    }
1351}
1352
1353impl<'a> From<&'a Buffer> for Content<'a> {
1354    fn from(buffer: &'a Buffer) -> Self {
1355        Self::from(&buffer.text)
1356    }
1357}
1358
1359impl<'a> From<&'a mut Buffer> for Content<'a> {
1360    fn from(buffer: &'a mut Buffer) -> Self {
1361        Self::from(&buffer.text)
1362    }
1363}
1364
1365impl<'a> From<&'a Snapshot> for Content<'a> {
1366    fn from(snapshot: &'a Snapshot) -> Self {
1367        Self::from(&snapshot.text)
1368    }
1369}
1370
1371impl Snapshot {
1372    fn suggest_autoindents<'a>(
1373        &'a self,
1374        row_range: Range<u32>,
1375    ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
1376        let mut query_cursor = QueryCursorHandle::new();
1377        if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
1378            let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
1379
1380            // Get the "indentation ranges" that intersect this row range.
1381            let indent_capture_ix = language.indents_query.capture_index_for_name("indent");
1382            let end_capture_ix = language.indents_query.capture_index_for_name("end");
1383            query_cursor.set_point_range(
1384                Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point()
1385                    ..Point::new(row_range.end, 0).to_ts_point(),
1386            );
1387            let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
1388            for mat in query_cursor.matches(
1389                &language.indents_query,
1390                tree.root_node(),
1391                TextProvider(self.as_rope()),
1392            ) {
1393                let mut node_kind = "";
1394                let mut start: Option<Point> = None;
1395                let mut end: Option<Point> = None;
1396                for capture in mat.captures {
1397                    if Some(capture.index) == indent_capture_ix {
1398                        node_kind = capture.node.kind();
1399                        start.get_or_insert(Point::from_ts_point(capture.node.start_position()));
1400                        end.get_or_insert(Point::from_ts_point(capture.node.end_position()));
1401                    } else if Some(capture.index) == end_capture_ix {
1402                        end = Some(Point::from_ts_point(capture.node.start_position().into()));
1403                    }
1404                }
1405
1406                if let Some((start, end)) = start.zip(end) {
1407                    if start.row == end.row {
1408                        continue;
1409                    }
1410
1411                    let range = start..end;
1412                    match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
1413                        Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
1414                        Ok(ix) => {
1415                            let prev_range = &mut indentation_ranges[ix];
1416                            prev_range.0.end = prev_range.0.end.max(range.end);
1417                        }
1418                    }
1419                }
1420            }
1421
1422            let mut prev_row = prev_non_blank_row.unwrap_or(0);
1423            Some(row_range.map(move |row| {
1424                let row_start = Point::new(row, self.indent_column_for_line(row));
1425
1426                let mut indent_from_prev_row = false;
1427                let mut outdent_to_row = u32::MAX;
1428                for (range, _node_kind) in &indentation_ranges {
1429                    if range.start.row >= row {
1430                        break;
1431                    }
1432
1433                    if range.start.row == prev_row && range.end > row_start {
1434                        indent_from_prev_row = true;
1435                    }
1436                    if range.end.row >= prev_row && range.end <= row_start {
1437                        outdent_to_row = outdent_to_row.min(range.start.row);
1438                    }
1439                }
1440
1441                let suggestion = if outdent_to_row == prev_row {
1442                    IndentSuggestion {
1443                        basis_row: prev_row,
1444                        indent: false,
1445                    }
1446                } else if indent_from_prev_row {
1447                    IndentSuggestion {
1448                        basis_row: prev_row,
1449                        indent: true,
1450                    }
1451                } else if outdent_to_row < prev_row {
1452                    IndentSuggestion {
1453                        basis_row: outdent_to_row,
1454                        indent: false,
1455                    }
1456                } else {
1457                    IndentSuggestion {
1458                        basis_row: prev_row,
1459                        indent: false,
1460                    }
1461                };
1462
1463                prev_row = row;
1464                suggestion
1465            }))
1466        } else {
1467            None
1468        }
1469    }
1470
1471    fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
1472        while row > 0 {
1473            row -= 1;
1474            if !self.is_line_blank(row) {
1475                return Some(row);
1476            }
1477        }
1478        None
1479    }
1480
1481    fn is_line_blank(&self, row: u32) -> bool {
1482        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1483            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1484    }
1485
1486    pub fn highlighted_text_for_range<T: ToOffset>(
1487        &mut self,
1488        range: Range<T>,
1489    ) -> HighlightedChunks {
1490        let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
1491
1492        let mut diagnostic_endpoints = Vec::<DiagnosticEndpoint>::new();
1493        for (_, range, (severity, _)) in
1494            self.diagnostics
1495                .intersecting_ranges(range.clone(), self.content(), true)
1496        {
1497            diagnostic_endpoints.push(DiagnosticEndpoint {
1498                offset: range.start,
1499                is_start: true,
1500                severity: *severity,
1501            });
1502            diagnostic_endpoints.push(DiagnosticEndpoint {
1503                offset: range.end,
1504                is_start: false,
1505                severity: *severity,
1506            });
1507        }
1508        diagnostic_endpoints.sort_unstable_by_key(|endpoint| endpoint.offset);
1509        let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
1510
1511        let chunks = self.text.as_rope().chunks_in_range(range.clone());
1512        let highlights =
1513            if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
1514                let captures = self.query_cursor.set_byte_range(range.clone()).captures(
1515                    &language.highlights_query,
1516                    tree.root_node(),
1517                    TextProvider(self.text.as_rope()),
1518                );
1519
1520                Some(Highlights {
1521                    captures,
1522                    next_capture: None,
1523                    stack: Default::default(),
1524                    highlight_map: language.highlight_map(),
1525                })
1526            } else {
1527                None
1528            };
1529
1530        HighlightedChunks {
1531            range,
1532            chunks,
1533            diagnostic_endpoints,
1534            error_depth: 0,
1535            warning_depth: 0,
1536            information_depth: 0,
1537            hint_depth: 0,
1538            highlights,
1539        }
1540    }
1541}
1542
1543impl Clone for Snapshot {
1544    fn clone(&self) -> Self {
1545        Self {
1546            text: self.text.clone(),
1547            tree: self.tree.clone(),
1548            diagnostics: self.diagnostics.clone(),
1549            is_parsing: self.is_parsing,
1550            language: self.language.clone(),
1551            query_cursor: QueryCursorHandle::new(),
1552        }
1553    }
1554}
1555
1556impl Deref for Snapshot {
1557    type Target = buffer::Snapshot;
1558
1559    fn deref(&self) -> &Self::Target {
1560        &self.text
1561    }
1562}
1563
1564impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
1565    type I = ByteChunks<'a>;
1566
1567    fn text(&mut self, node: tree_sitter::Node) -> Self::I {
1568        ByteChunks(self.0.chunks_in_range(node.byte_range()))
1569    }
1570}
1571
1572struct ByteChunks<'a>(rope::Chunks<'a>);
1573
1574impl<'a> Iterator for ByteChunks<'a> {
1575    type Item = &'a [u8];
1576
1577    fn next(&mut self) -> Option<Self::Item> {
1578        self.0.next().map(str::as_bytes)
1579    }
1580}
1581
1582impl<'a> HighlightedChunks<'a> {
1583    pub fn seek(&mut self, offset: usize) {
1584        self.range.start = offset;
1585        self.chunks.seek(self.range.start);
1586        if let Some(highlights) = self.highlights.as_mut() {
1587            highlights
1588                .stack
1589                .retain(|(end_offset, _)| *end_offset > offset);
1590            if let Some((mat, capture_ix)) = &highlights.next_capture {
1591                let capture = mat.captures[*capture_ix as usize];
1592                if offset >= capture.node.start_byte() {
1593                    let next_capture_end = capture.node.end_byte();
1594                    if offset < next_capture_end {
1595                        highlights.stack.push((
1596                            next_capture_end,
1597                            highlights.highlight_map.get(capture.index),
1598                        ));
1599                    }
1600                    highlights.next_capture.take();
1601                }
1602            }
1603            highlights.captures.set_byte_range(self.range.clone());
1604        }
1605    }
1606
1607    pub fn offset(&self) -> usize {
1608        self.range.start
1609    }
1610
1611    fn update_diagnostic_depths(&mut self, endpoint: DiagnosticEndpoint) {
1612        let depth = match endpoint.severity {
1613            DiagnosticSeverity::ERROR => &mut self.error_depth,
1614            DiagnosticSeverity::WARNING => &mut self.warning_depth,
1615            DiagnosticSeverity::INFORMATION => &mut self.information_depth,
1616            DiagnosticSeverity::HINT => &mut self.hint_depth,
1617            _ => return,
1618        };
1619        if endpoint.is_start {
1620            *depth += 1;
1621        } else {
1622            *depth -= 1;
1623        }
1624    }
1625
1626    fn current_diagnostic_severity(&mut self) -> Option<DiagnosticSeverity> {
1627        if self.error_depth > 0 {
1628            Some(DiagnosticSeverity::ERROR)
1629        } else if self.warning_depth > 0 {
1630            Some(DiagnosticSeverity::WARNING)
1631        } else if self.information_depth > 0 {
1632            Some(DiagnosticSeverity::INFORMATION)
1633        } else if self.hint_depth > 0 {
1634            Some(DiagnosticSeverity::HINT)
1635        } else {
1636            None
1637        }
1638    }
1639}
1640
1641impl<'a> Iterator for HighlightedChunks<'a> {
1642    type Item = HighlightedChunk<'a>;
1643
1644    fn next(&mut self) -> Option<Self::Item> {
1645        let mut next_capture_start = usize::MAX;
1646        let mut next_diagnostic_endpoint = usize::MAX;
1647
1648        if let Some(highlights) = self.highlights.as_mut() {
1649            while let Some((parent_capture_end, _)) = highlights.stack.last() {
1650                if *parent_capture_end <= self.range.start {
1651                    highlights.stack.pop();
1652                } else {
1653                    break;
1654                }
1655            }
1656
1657            if highlights.next_capture.is_none() {
1658                highlights.next_capture = highlights.captures.next();
1659            }
1660
1661            while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
1662                let capture = mat.captures[*capture_ix as usize];
1663                if self.range.start < capture.node.start_byte() {
1664                    next_capture_start = capture.node.start_byte();
1665                    break;
1666                } else {
1667                    let highlight_id = highlights.highlight_map.get(capture.index);
1668                    highlights
1669                        .stack
1670                        .push((capture.node.end_byte(), highlight_id));
1671                    highlights.next_capture = highlights.captures.next();
1672                }
1673            }
1674        }
1675
1676        while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
1677            if endpoint.offset <= self.range.start {
1678                self.update_diagnostic_depths(endpoint);
1679                self.diagnostic_endpoints.next();
1680            } else {
1681                next_diagnostic_endpoint = endpoint.offset;
1682                break;
1683            }
1684        }
1685
1686        if let Some(chunk) = self.chunks.peek() {
1687            let chunk_start = self.range.start;
1688            let mut chunk_end = (self.chunks.offset() + chunk.len())
1689                .min(next_capture_start)
1690                .min(next_diagnostic_endpoint);
1691            let mut highlight_id = HighlightId::default();
1692            if let Some((parent_capture_end, parent_highlight_id)) =
1693                self.highlights.as_ref().and_then(|h| h.stack.last())
1694            {
1695                chunk_end = chunk_end.min(*parent_capture_end);
1696                highlight_id = *parent_highlight_id;
1697            }
1698
1699            let slice =
1700                &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
1701            self.range.start = chunk_end;
1702            if self.range.start == self.chunks.offset() + chunk.len() {
1703                self.chunks.next().unwrap();
1704            }
1705
1706            Some(HighlightedChunk {
1707                text: slice,
1708                highlight_id,
1709                diagnostic: self.current_diagnostic_severity(),
1710            })
1711        } else {
1712            None
1713        }
1714    }
1715}
1716
1717impl QueryCursorHandle {
1718    fn new() -> Self {
1719        QueryCursorHandle(Some(
1720            QUERY_CURSORS
1721                .lock()
1722                .pop()
1723                .unwrap_or_else(|| QueryCursor::new()),
1724        ))
1725    }
1726}
1727
1728impl Deref for QueryCursorHandle {
1729    type Target = QueryCursor;
1730
1731    fn deref(&self) -> &Self::Target {
1732        self.0.as_ref().unwrap()
1733    }
1734}
1735
1736impl DerefMut for QueryCursorHandle {
1737    fn deref_mut(&mut self) -> &mut Self::Target {
1738        self.0.as_mut().unwrap()
1739    }
1740}
1741
1742impl Drop for QueryCursorHandle {
1743    fn drop(&mut self) {
1744        let mut cursor = self.0.take().unwrap();
1745        cursor.set_byte_range(0..usize::MAX);
1746        cursor.set_point_range(Point::zero().to_ts_point()..Point::MAX.to_ts_point());
1747        QUERY_CURSORS.lock().push(cursor)
1748    }
1749}
1750
1751trait ToTreeSitterPoint {
1752    fn to_ts_point(self) -> tree_sitter::Point;
1753    fn from_ts_point(point: tree_sitter::Point) -> Self;
1754}
1755
1756impl ToTreeSitterPoint for Point {
1757    fn to_ts_point(self) -> tree_sitter::Point {
1758        tree_sitter::Point::new(self.row as usize, self.column as usize)
1759    }
1760
1761    fn from_ts_point(point: tree_sitter::Point) -> Self {
1762        Point::new(point.row as u32, point.column as u32)
1763    }
1764}
1765
1766fn contiguous_ranges(
1767    values: impl IntoIterator<Item = u32>,
1768    max_len: usize,
1769) -> impl Iterator<Item = Range<u32>> {
1770    let mut values = values.into_iter();
1771    let mut current_range: Option<Range<u32>> = None;
1772    std::iter::from_fn(move || loop {
1773        if let Some(value) = values.next() {
1774            if let Some(range) = &mut current_range {
1775                if value == range.end && range.len() < max_len {
1776                    range.end += 1;
1777                    continue;
1778                }
1779            }
1780
1781            let prev_range = current_range.clone();
1782            current_range = Some(value..(value + 1));
1783            if prev_range.is_some() {
1784                return prev_range;
1785            }
1786        } else {
1787            return current_range.take();
1788        }
1789    })
1790}