6062 lines · 220.1 KB · Rust
RawDownload
pub mod row_chunk; use crate::{    DebuggerTextObject, LanguageScope, Outline, OutlineConfig, PLAIN_TEXT, RunnableCapture,    RunnableTag, TextObject, TreeSitterOptions,    diagnostic_set::{DiagnosticEntry, DiagnosticEntryRef, DiagnosticGroup},    language_settings::{AutoIndentMode, LanguageSettings, language_settings},    outline::OutlineItem,    row_chunk::RowChunks,    syntax_map::{        MAX_BYTES_TO_QUERY, SyntaxLayer, SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures,        SyntaxMapMatch, SyntaxMapMatches, SyntaxSnapshot, ToTreeSitterPoint,    },    task_context::RunnableRange,    text_diff::text_diff,    unified_diff_with_offsets,};pub use crate::{    Grammar, Language, LanguageRegistry,    diagnostic_set::DiagnosticSet,    highlight_map::{HighlightId, HighlightMap},    proto,};use anyhow::{Context as _, Result};use clock::Lamport;pub use clock::ReplicaId;use collections::{HashMap, HashSet};use encoding_rs::Encoding;use fs::MTime;use futures::channel::oneshot;use gpui::{    App, AppContext as _, Context, Entity, EventEmitter, HighlightStyle, SharedString, StyledText,    Task, TextStyle,}; use lsp::{LanguageServerId, NumberOrString};use parking_lot::Mutex;use serde::{Deserialize, Serialize};use serde_json::Value;use settings::WorktreeId;use smallvec::SmallVec;use smol::future::yield_now;use std::{    any::Any,    borrow::Cow,    cell::Cell,    cmp::{self, Ordering, Reverse},    collections::{BTreeMap, BTreeSet},    future::Future,    iter::{self, Iterator, Peekable},    mem,    num::NonZeroU32,    ops::{Deref, Range},    path::PathBuf,    rc,    sync::Arc,    time::{Duration, Instant},    vec,};use sum_tree::TreeMap;use text::operation_queue::OperationQueue;use text::*;pub use text::{    Anchor, Bias, Buffer as TextBuffer, BufferId, BufferSnapshot as TextBufferSnapshot, Edit,    LineIndent, OffsetRangeExt, OffsetUtf16, Patch, Point, PointUtf16, Rope, Selection,    SelectionGoal, Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint,    ToPointUtf16, Transaction, TransactionId, Unclipped,};use theme::{ActiveTheme as _, SyntaxTheme};#[cfg(any(test, feature = "test-support"))]use util::RandomCharIter;use util::{RangeExt, debug_panic, maybe, paths::PathStyle, rel_path::RelPath}; #[cfg(any(test, feature = "test-support"))]pub use {tree_sitter_python, tree_sitter_rust, tree_sitter_typescript}; pub use lsp::DiagnosticSeverity; /// Indicate whether a [`Buffer`] has permissions to edit.#[derive(PartialEq, Clone, Copy, Debug)]pub enum Capability {    /// The buffer is a mutable replica.    ReadWrite,    /// The buffer is a mutable replica, but toggled to be only readable.    Read,    /// The buffer is a read-only replica.    ReadOnly,} impl Capability {    /// Returns `true` if the capability is `ReadWrite`.    pub fn editable(self) -> bool {        matches!(self, Capability::ReadWrite)    }} pub type BufferRow = u32; /// An in-memory representation of a source code file, including its text,/// syntax trees, git status, and diagnostics.pub struct Buffer {    text: TextBuffer,    branch_state: Option<BufferBranchState>,    /// Filesystem state, `None` when there is no path.    file: Option<Arc<dyn File>>,    /// The mtime of the file when this buffer was last loaded from    /// or saved to disk.    saved_mtime: Option<MTime>,    /// The version vector when this buffer was last loaded from    /// or saved to disk.    saved_version: clock::Global,    preview_version: clock::Global,    transaction_depth: usize,    was_dirty_before_starting_transaction: Option<bool>,    reload_task: Option<Task<Result<()>>>,    language: Option<Arc<Language>>,    autoindent_requests: Vec<Arc<AutoindentRequest>>,    wait_for_autoindent_txs: Vec<oneshot::Sender<()>>,    pending_autoindent: Option<Task<()>>,    sync_parse_timeout: Option<Duration>,    syntax_map: Mutex<SyntaxMap>,    reparse: Option<Task<()>>,    parse_status: (watch::Sender<ParseStatus>, watch::Receiver<ParseStatus>),    non_text_state_update_count: usize,    diagnostics: TreeMap<LanguageServerId, DiagnosticSet>,    remote_selections: TreeMap<ReplicaId, SelectionSet>,    diagnostics_timestamp: clock::Lamport,    completion_triggers: BTreeSet<String>,    completion_triggers_per_language_server: HashMap<LanguageServerId, BTreeSet<String>>,    completion_triggers_timestamp: clock::Lamport,    deferred_ops: OperationQueue<Operation>,    capability: Capability,    has_conflict: bool,    /// Memoize calls to has_changes_since(saved_version).    /// The contents of a cell are (self.version, has_changes) at the time of a last call.    has_unsaved_edits: Cell<(clock::Global, bool)>,    change_bits: Vec<rc::Weak<Cell<bool>>>,    _subscriptions: Vec<gpui::Subscription>,    tree_sitter_data: Arc<TreeSitterData>,    encoding: &'static Encoding,    has_bom: bool,    reload_with_encoding_txns: HashMap<TransactionId, (&'static Encoding, bool)>,} #[derive(Debug)]pub struct TreeSitterData {    chunks: RowChunks,    brackets_by_chunks: Mutex<Vec<Option<Vec<BracketMatch<usize>>>>>,} const MAX_ROWS_IN_A_CHUNK: u32 = 50; impl TreeSitterData {    fn clear(&mut self, snapshot: &text::BufferSnapshot) {        self.chunks = RowChunks::new(&snapshot, MAX_ROWS_IN_A_CHUNK);        self.brackets_by_chunks.get_mut().clear();        self.brackets_by_chunks            .get_mut()            .resize(self.chunks.len(), None);    }     fn new(snapshot: &text::BufferSnapshot) -> Self {        let chunks = RowChunks::new(&snapshot, MAX_ROWS_IN_A_CHUNK);        Self {            brackets_by_chunks: Mutex::new(vec![None; chunks.len()]),            chunks,        }    }     fn version(&self) -> &clock::Global {        self.chunks.version()    }} #[derive(Copy, Clone, Debug, PartialEq, Eq)]pub enum ParseStatus {    Idle,    Parsing,} struct BufferBranchState {    base_buffer: Entity<Buffer>,    merged_operations: Vec<Lamport>,} /// An immutable, cheaply cloneable representation of a fixed/// state of a buffer.pub struct BufferSnapshot {    pub text: text::BufferSnapshot,    pub(crate) syntax: SyntaxSnapshot,    tree_sitter_data: Arc<TreeSitterData>,    diagnostics: TreeMap<LanguageServerId, DiagnosticSet>,    remote_selections: TreeMap<ReplicaId, SelectionSet>,    language: Option<Arc<Language>>,    file: Option<Arc<dyn File>>,    non_text_state_update_count: usize,    pub capability: Capability,} /// The kind and amount of indentation in a particular line. For now,/// assumes that indentation is all the same character.#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]pub struct IndentSize {    /// The number of bytes that comprise the indentation.    pub len: u32,    /// The kind of whitespace used for indentation.    pub kind: IndentKind,} /// A whitespace character that's used for indentation.#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]pub enum IndentKind {    /// An ASCII space character.    #[default]    Space,    /// An ASCII tab character.    Tab,} /// The shape of a selection cursor.#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]pub enum CursorShape {    /// A vertical bar    #[default]    Bar,    /// A block that surrounds the following character    Block,    /// An underline that runs along the following character    Underline,    /// A box drawn around the following character    Hollow,} impl From<settings::CursorShape> for CursorShape {    fn from(shape: settings::CursorShape) -> Self {        match shape {            settings::CursorShape::Bar => CursorShape::Bar,            settings::CursorShape::Block => CursorShape::Block,            settings::CursorShape::Underline => CursorShape::Underline,            settings::CursorShape::Hollow => CursorShape::Hollow,        }    }} #[derive(Clone, Debug)]struct SelectionSet {    line_mode: bool,    cursor_shape: CursorShape,    selections: Arc<[Selection<Anchor>]>,    lamport_timestamp: clock::Lamport,} /// A diagnostic associated with a certain range of a buffer.#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]pub struct Diagnostic {    /// The name of the service that produced this diagnostic.    pub source: Option<String>,    /// The ID provided by the dynamic registration that produced this diagnostic.    pub registration_id: Option<SharedString>,    /// A machine-readable code that identifies this diagnostic.    pub code: Option<NumberOrString>,    pub code_description: Option<lsp::Uri>,    /// Whether this diagnostic is a hint, warning, or error.    pub severity: DiagnosticSeverity,    /// The human-readable message associated with this diagnostic.    pub message: String,    /// The human-readable message (in markdown format)    pub markdown: Option<String>,    /// An id that identifies the group to which this diagnostic belongs.    ///    /// When a language server produces a diagnostic with    /// one or more associated diagnostics, those diagnostics are all    /// assigned a single group ID.    pub group_id: usize,    /// Whether this diagnostic is the primary diagnostic for its group.    ///    /// In a given group, the primary diagnostic is the top-level diagnostic    /// returned by the language server. The non-primary diagnostics are the    /// associated diagnostics.    pub is_primary: bool,    /// Whether this diagnostic is considered to originate from an analysis of    /// files on disk, as opposed to any unsaved buffer contents. This is a    /// property of a given diagnostic source, and is configured for a given    /// language server via the [`LspAdapter::disk_based_diagnostic_sources`](crate::LspAdapter::disk_based_diagnostic_sources) method    /// for the language server.    pub is_disk_based: bool,    /// Whether this diagnostic marks unnecessary code.    pub is_unnecessary: bool,    /// Quick separation of diagnostics groups based by their source.    pub source_kind: DiagnosticSourceKind,    /// Data from language server that produced this diagnostic. Passed back to the LS when we request code actions for this diagnostic.    pub data: Option<Value>,    /// Whether to underline the corresponding text range in the editor.    pub underline: bool,} #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]pub enum DiagnosticSourceKind {    Pulled,    Pushed,    Other,} /// An operation used to synchronize this buffer with its other replicas.#[derive(Clone, Debug, PartialEq)]pub enum Operation {    /// A text operation.    Buffer(text::Operation),     /// An update to the buffer's diagnostics.    UpdateDiagnostics {        /// The id of the language server that produced the new diagnostics.        server_id: LanguageServerId,        /// The diagnostics.        diagnostics: Arc<[DiagnosticEntry<Anchor>]>,        /// The buffer's lamport timestamp.        lamport_timestamp: clock::Lamport,    },     /// An update to the most recent selections in this buffer.    UpdateSelections {        /// The selections.        selections: Arc<[Selection<Anchor>]>,        /// The buffer's lamport timestamp.        lamport_timestamp: clock::Lamport,        /// Whether the selections are in 'line mode'.        line_mode: bool,        /// The [`CursorShape`] associated with these selections.        cursor_shape: CursorShape,    },     /// An update to the characters that should trigger autocompletion    /// for this buffer.    UpdateCompletionTriggers {        /// The characters that trigger autocompletion.        triggers: Vec<String>,        /// The buffer's lamport timestamp.        lamport_timestamp: clock::Lamport,        /// The language server ID.        server_id: LanguageServerId,    },     /// An update to the line ending type of this buffer.    UpdateLineEnding {        /// The line ending type.        line_ending: LineEnding,        /// The buffer's lamport timestamp.        lamport_timestamp: clock::Lamport,    },} /// An event that occurs in a buffer.#[derive(Clone, Debug, PartialEq)]pub enum BufferEvent {    /// The buffer was changed in a way that must be    /// propagated to its other replicas.    Operation {        operation: Operation,        is_local: bool,    },    /// The buffer was edited.    Edited { is_local: bool },    /// The buffer's `dirty` bit changed.    DirtyChanged,    /// The buffer was saved.    Saved,    /// The buffer's file was changed on disk.    FileHandleChanged,    /// The buffer was reloaded.    Reloaded,    /// The buffer is in need of a reload    ReloadNeeded,    /// The buffer's language was changed.    /// The boolean indicates whether this buffer did not have a language before, but does now.    LanguageChanged(bool),    /// The buffer's syntax trees were updated.    Reparsed,    /// The buffer's diagnostics were updated.    DiagnosticsUpdated,    /// The buffer gained or lost editing capabilities.    CapabilityChanged,} /// The file associated with a buffer.pub trait File: Send + Sync + Any {    /// Returns the [`LocalFile`] associated with this file, if the    /// file is local.    fn as_local(&self) -> Option<&dyn LocalFile>;     /// Returns whether this file is local.    fn is_local(&self) -> bool {        self.as_local().is_some()    }     /// Returns whether the file is new, exists in storage, or has been deleted. Includes metadata    /// only available in some states, such as modification time.    fn disk_state(&self) -> DiskState;     /// Returns the path of this file relative to the worktree's root directory.    fn path(&self) -> &Arc<RelPath>;     /// Returns the path of this file relative to the worktree's parent directory (this means it    /// includes the name of the worktree's root folder).    fn full_path(&self, cx: &App) -> PathBuf;     /// Returns the path style of this file.    fn path_style(&self, cx: &App) -> PathStyle;     /// Returns the last component of this handle's absolute path. If this handle refers to the root    /// of its worktree, then this method will return the name of the worktree itself.    fn file_name<'a>(&'a self, cx: &'a App) -> &'a str;     /// Returns the id of the worktree to which this file belongs.    ///    /// This is needed for looking up project-specific settings.    fn worktree_id(&self, cx: &App) -> WorktreeId;     /// Converts this file into a protobuf message.    fn to_proto(&self, cx: &App) -> rpc::proto::File;     /// Return whether Zed considers this to be a private file.    fn is_private(&self) -> bool;     fn can_open(&self) -> bool {        !self.is_local()    }} /// The file's storage status - whether it's stored (`Present`), and if so when it was last/// modified. In the case where the file is not stored, it can be either `New` or `Deleted`. In the/// UI these two states are distinguished. For example, the buffer tab does not display a deletion/// indicator for new files.#[derive(Copy, Clone, Debug, PartialEq)]pub enum DiskState {    /// File created in Zed that has not been saved.    New,    /// File present on the filesystem.    Present { mtime: MTime, size: u64 },    /// Deleted file that was previously present.    Deleted,    /// An old version of a file that was previously present    /// usually from a version control system. e.g. A git blob    Historic { was_deleted: bool },} impl DiskState {    /// Returns the file's last known modification time on disk.    pub fn mtime(self) -> Option<MTime> {        match self {            DiskState::New => None,            DiskState::Present { mtime, .. } => Some(mtime),            DiskState::Deleted => None,            DiskState::Historic { .. } => None,        }    }     /// Returns the file's size on disk in bytes.    pub fn size(self) -> Option<u64> {        match self {            DiskState::New => None,            DiskState::Present { size, .. } => Some(size),            DiskState::Deleted => None,            DiskState::Historic { .. } => None,        }    }     pub fn exists(&self) -> bool {        match self {            DiskState::New => false,            DiskState::Present { .. } => true,            DiskState::Deleted => false,            DiskState::Historic { .. } => false,        }    }     /// Returns true if this state represents a deleted file.    pub fn is_deleted(&self) -> bool {        match self {            DiskState::Deleted => true,            DiskState::Historic { was_deleted } => *was_deleted,            _ => false,        }    }} /// The file associated with a buffer, in the case where the file is on the local disk.pub trait LocalFile: File {    /// Returns the absolute path of this file    fn abs_path(&self, cx: &App) -> PathBuf;     /// Loads the file contents from disk and returns them as a UTF-8 encoded string.    fn load(&self, cx: &App) -> Task<Result<String>>;     /// Loads the file's contents from disk.    fn load_bytes(&self, cx: &App) -> Task<Result<Vec<u8>>>;} /// The auto-indent behavior associated with an editing operation./// For some editing operations, each affected line of text has its/// indentation recomputed. For other operations, the entire block

Lines 1–500 of 6062.