4506 lines · 162.7 KB · Rust
RawDownload
pub use crate::{    diagnostic_set::DiagnosticSet,    highlight_map::{HighlightId, HighlightMap},    markdown::ParsedMarkdown,    proto, Grammar, Language, LanguageRegistry,};use crate::{    diagnostic_set::{DiagnosticEntry, DiagnosticGroup},    language_settings::{language_settings, IndentGuideSettings, LanguageSettings},    markdown::parse_markdown,    outline::OutlineItem,    syntax_map::{        SyntaxLayer, SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures, SyntaxMapMatch,        SyntaxMapMatches, SyntaxSnapshot, ToTreeSitterPoint,    },    task_context::RunnableRange,    LanguageScope, Outline, OutlineConfig, RunnableCapture, RunnableTag,};use anyhow::{anyhow, Context, Result};use async_watch as watch;use clock::Lamport;pub use clock::ReplicaId;use collections::HashMap;use futures::channel::oneshot;use gpui::{    AnyElement, AppContext, Context as _, EventEmitter, HighlightStyle, Model, ModelContext,    Pixels, Task, TaskLabel, WindowContext,};use lsp::LanguageServerId;use parking_lot::Mutex;use schemars::JsonSchema;use serde::{Deserialize, Serialize};use serde_json::Value;use settings::WorktreeId;use similar::{ChangeTag, TextDiff};use smallvec::SmallVec;use smol::future::yield_now;use std::{    any::Any,    borrow::Cow,    cell::Cell,    cmp::{self, Ordering, Reverse},    collections::BTreeMap,    ffi::OsStr,    fmt,    future::Future,    iter::{self, Iterator, Peekable},    mem,    ops::{Deref, DerefMut, Range},    path::{Path, PathBuf},    str,    sync::{Arc, LazyLock},    time::{Duration, Instant, SystemTime},    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::SyntaxTheme;#[cfg(any(test, feature = "test-support"))]use util::RandomCharIter;use util::{debug_panic, 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; #[derive(Clone)]enum BufferDiffBase {    Git(Rope),    PastBufferVersion {        buffer: Model<Buffer>,        rope: Rope,        merged_operations: Vec<Lamport>,    },} /// An in-memory representation of a source code file, including its text,/// syntax trees, git status, and diagnostics.pub struct Buffer {    text: TextBuffer,    diff_base: Option<BufferDiffBase>,    git_diff: git::diff::BufferDiff,    file: Option<Arc<dyn File>>,    /// The mtime of the file when this buffer was last loaded from    /// or saved to disk.    saved_mtime: Option<SystemTime>,    /// 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>,    parsing_in_background: bool,    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: Vec<String>,    completion_triggers_timestamp: clock::Lamport,    deferred_ops: OperationQueue<Operation>,    capability: Capability,    has_conflict: bool,    diff_base_version: usize,    /// 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,} /// An immutable, cheaply cloneable representation of a fixed/// state of a buffer.pub struct BufferSnapshot {    text: text::BufferSnapshot,    git_diff: git::diff::BufferDiff,    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)]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<String>,    /// 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>,} /// TODO - move this into the `project` crate and make it private.pub async fn prepare_completion_documentation(    documentation: &lsp::Documentation,    language_registry: &Arc<LanguageRegistry>,    language: Option<Arc<Language>>,) -> Documentation {    match documentation {        lsp::Documentation::String(text) => {            if text.lines().count() <= 1 {                Documentation::SingleLine(text.clone())            } else {                Documentation::MultiLinePlainText(text.clone())            }        }         lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value }) => match kind {            lsp::MarkupKind::PlainText => {                if value.lines().count() <= 1 {                    Documentation::SingleLine(value.clone())                } else {                    Documentation::MultiLinePlainText(value.clone())                }            }             lsp::MarkupKind::Markdown => {                let parsed = parse_markdown(value, language_registry, language).await;                Documentation::MultiLineMarkdown(parsed)            }        },    }} /// Documentation associated with a [`Completion`].#[derive(Clone, Debug)]pub enum Documentation {    /// There is no documentation for this completion.    Undocumented,    /// A single line of documentation.    SingleLine(String),    /// Multiple lines of plain text documentation.    MultiLinePlainText(String),    /// Markdown documentation.    MultiLineMarkdown(ParsedMarkdown),} /// 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,    },} /// 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 diff_base changed.    DiffBaseChanged,    /// Buffer's excerpts for a certain diff base were recalculated.    DiffUpdated,    /// 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 the file's mtime.    fn mtime(&self) -> Option<SystemTime>;     /// 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: &AppContext) -> 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 AppContext) -> &'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: &AppContext) -> WorktreeId;     /// Returns whether the file has been deleted.    fn is_deleted(&self) -> bool;     /// Returns whether the file existed on disk at one point    fn is_created(&self) -> bool {        self.mtime().is_some()    }     /// 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: &AppContext) -> rpc::proto::File;     /// Return whether Zed considers this to be a private file.    fn is_private(&self) -> bool;} /// 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: &AppContext) -> PathBuf;     /// Loads the file's contents from disk.    fn load(&self, cx: &AppContext) -> Task<Result<String>>;     /// Returns true if the file should not be shared with collaborators.    fn is_private(&self, _: &AppContext) -> bool {        false    }} /// 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 indentation level of the first line of each        /// insertion, if it has been copied.        original_indent_columns: Vec<u32>,    },} #[derive(Clone)]struct AutoindentRequest {    before_edit: BufferSnapshot,    entries: Vec<AutoindentRequestEntry>,    is_block_mode: 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.

Lines 1–500 of 4506.