4677 lines · 167.9 KB · Rust
RawDownload
pub use crate::{    diagnostic_set::DiagnosticSet,    highlight_map::{HighlightId, HighlightMap},    proto, Grammar, Language, LanguageRegistry,};use crate::{    diagnostic_set::{DiagnosticEntry, DiagnosticGroup},    language_settings::{language_settings, LanguageSettings},    outline::OutlineItem,    syntax_map::{        SyntaxLayer, SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures, SyntaxMapMatch,        SyntaxMapMatches, SyntaxSnapshot, ToTreeSitterPoint,    },    task_context::RunnableRange,    text_diff::text_diff,    LanguageScope, Outline, OutlineConfig, RunnableCapture, RunnableTag, TextObject,    TreeSitterOptions,};use anyhow::{anyhow, Context as _, Result};use async_watch as watch;use clock::Lamport;pub use clock::ReplicaId;use collections::HashMap;use fs::MTime;use futures::channel::oneshot;use gpui::{    AnyElement, App, AppContext as _, Context, Entity, EventEmitter, HighlightStyle, Pixels,    SharedString, StyledText, Task, TaskLabel, TextStyle, Window,};use lsp::{LanguageServerId, NumberOrString};use parking_lot::Mutex;use schemars::JsonSchema;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},    ffi::OsStr,    fmt,    future::Future,    iter::{self, Iterator, Peekable},    mem,    num::NonZeroU32,    ops::{Deref, DerefMut, Range},    path::{Path, PathBuf},    str,    sync::{Arc, LazyLock},    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,    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::{debug_panic, maybe, RangeExt}; #[cfg(any(test, feature = "test-support"))]pub use {tree_sitter_rust, tree_sitter_typescript}; pub use lsp::DiagnosticSeverity; /// A label for the background task spawned by the buffer to compute/// a diff against the contents of its file.pub static BUFFER_DIFF_TASK: LazyLock<TaskLabel> = LazyLock::new(TaskLabel::new); /// 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 read-only replica.    ReadOnly,} 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>>,    pending_autoindent: Option<Task<()>>,    sync_parse_timeout: Duration,    syntax_map: Mutex<SyntaxMap>,    reparse: Option<Task<()>>,    parse_status: (watch::Sender<ParseStatus>, watch::Receiver<ParseStatus>),    non_text_state_update_count: usize,    diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,    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)>,    _subscriptions: Vec<gpui::Subscription>,} #[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,    file: Option<Arc<dyn File>>,    diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,    remote_selections: TreeMap<ReplicaId, SelectionSet>,    language: Option<Arc<Language>>,    non_text_state_update_count: usize,} /// 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, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]#[serde(rename_all = "snake_case")]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,} #[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>,    /// A machine-readable code that identifies this diagnostic.    pub code: Option<NumberOrString>,    /// Whether this diagnostic is a hint, warning, or error.    pub severity: DiagnosticSeverity,    /// The human-readable message associated with this diagnostic.    pub message: 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,    /// 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>,} /// 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 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,    /// 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.    LanguageChanged,    /// The buffer's syntax trees were updated.    Reparsed,    /// The buffer's diagnostics were updated.    DiagnosticsUpdated,    /// The buffer gained or lost editing capabilities.    CapabilityChanged,    /// The buffer was explicitly requested to close.    Closed,    /// The buffer was discarded when closing.    Discarded,} /// The file associated with a buffer.pub trait File: Send + Sync {    /// 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<Path>;     /// 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 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 OsStr;     /// 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 an [`Any`] trait object.    fn as_any(&self) -> &dyn Any;     /// 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;} /// 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 },    /// Deleted file that was previously present.    Deleted,} 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,        }    }     pub fn exists(&self) -> bool {        match self {            DiskState::New => false,            DiskState::Present { .. } => true,            DiskState::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/// of edited text is adjusted uniformly.#[derive(Clone, Debug)]pub enum AutoindentMode {    /// Indent each line of inserted text.    EachLine,    /// Apply the same indentation adjustment to all of the lines    /// in a given insertion.    Block {        /// The original start column of each insertion, if it was        /// copied from elsewhere.        ///        /// Knowing this start column makes it possible to preserve the        /// relative indentation of every line in the insertion from        /// when it was copied.        ///        /// If the start column is `a`, and the first line of insertion        /// is then auto-indented to column `b`, then every other line of        /// the insertion will be auto-indented to column `b - a`        original_start_columns: Vec<u32>,    },} #[derive(Clone)]struct AutoindentRequest {    before_edit: BufferSnapshot,    entries: Vec<AutoindentRequestEntry>,    is_block_mode: bool,    ignore_empty_lines: bool,} #[derive(Debug, Clone)]struct AutoindentRequestEntry {    /// A range of the buffer whose indentation should be adjusted.    range: Range<Anchor>,    /// Whether or not these lines should be considered brand new, for the    /// purpose of auto-indent. When text is not new, its indentation will    /// only be adjusted if the suggested indentation level has *changed*    /// since the edit was made.    first_line_is_new: bool,    indent_size: IndentSize,    original_indent_column: Option<u32>,} #[derive(Debug)]struct IndentSuggestion {    basis_row: u32,    delta: Ordering,    within_error: bool,} struct BufferChunkHighlights<'a> {    captures: SyntaxMapCaptures<'a>,    next_capture: Option<SyntaxMapCapture<'a>>,    stack: Vec<(usize, HighlightId)>,    highlight_maps: Vec<HighlightMap>,} /// An iterator that yields chunks of a buffer's text, along with their/// syntax highlights and diagnostic status.pub struct BufferChunks<'a> {    buffer_snapshot: Option<&'a BufferSnapshot>,    range: Range<usize>,    chunks: text::Chunks<'a>,    diagnostic_endpoints: Option<Peekable<vec::IntoIter<DiagnosticEndpoint>>>,    error_depth: usize,    warning_depth: usize,    information_depth: usize,    hint_depth: usize,    unnecessary_depth: usize,    highlights: Option<BufferChunkHighlights<'a>>,} /// A chunk of a buffer's text, along with its syntax highlight and/// diagnostic status.#[derive(Clone, Debug, Default)]pub struct Chunk<'a> {    /// The text of the chunk.    pub text: &'a str,    /// The syntax highlighting style of the chunk.    pub syntax_highlight_id: Option<HighlightId>,    /// The highlight style that has been applied to this chunk in    /// the editor.    pub highlight_style: Option<HighlightStyle>,    /// The severity of diagnostic associated with this chunk, if any.    pub diagnostic_severity: Option<DiagnosticSeverity>,    /// Whether this chunk of text is marked as unnecessary.    pub is_unnecessary: bool,    /// Whether this chunk of text was originally a tab character.    pub is_tab: bool,    /// An optional recipe for how the chunk should be presented.    pub renderer: Option<ChunkRenderer>,} /// A recipe for how the chunk should be presented.#[derive(Clone)]pub struct ChunkRenderer {    /// creates a custom element to represent this chunk.    pub render: Arc<dyn Send + Sync + Fn(&mut ChunkRendererContext) -> AnyElement>,    /// If true, the element is constrained to the shaped width of the text.    pub constrain_width: bool,} pub struct ChunkRendererContext<'a, 'b> {    pub window: &'a mut Window,    pub context: &'b mut App,

Lines 1–500 of 4677.