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