3541 lines · 128.2 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, LanguageSettings},    markdown::parse_markdown,    outline::OutlineItem,    syntax_map::{        SyntaxLayer, SyntaxMap, SyntaxMapCapture, SyntaxMapCaptures, SyntaxMapMatches,        SyntaxSnapshot, ToTreeSitterPoint,    },    CodeLabel, LanguageScope, Outline,};use anyhow::{anyhow, Context, Result};pub use clock::ReplicaId;use futures::channel::oneshot;use gpui::{AppContext, EventEmitter, HighlightStyle, ModelContext, Task, TaskLabel};use lazy_static::lazy_static;use lsp::LanguageServerId;use parking_lot::Mutex;use similar::{ChangeTag, TextDiff};use smallvec::SmallVec;use smol::future::yield_now;use std::{    any::Any,    cmp::{self, Ordering},    collections::BTreeMap,    ffi::OsStr,    future::Future,    iter::{self, Iterator, Peekable},    mem,    ops::{Deref, Range},    path::{Path, PathBuf},    str,    sync::Arc,    time::{Duration, Instant, SystemTime, UNIX_EPOCH},    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, RopeFingerprint, 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::RangeExt; #[cfg(any(test, feature = "test-support"))]pub use {tree_sitter_rust, tree_sitter_typescript}; pub use lsp::DiagnosticSeverity; lazy_static! {    /// A label for the background task spawned by the buffer to compute    /// a diff against the contents of its file.    pub static ref BUFFER_DIFF_TASK: TaskLabel = 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,} /// 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<String>,    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: SystemTime,    /// The version vector when this buffer was last loaded from    /// or saved to disk.    saved_version: clock::Global,    /// A hash of the current contents of the buffer's file.    file_fingerprint: RopeFingerprint,    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_count: usize,    diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,    remote_selections: TreeMap<ReplicaId, SelectionSet>,    selections_update_count: usize,    diagnostics_update_count: usize,    diagnostics_timestamp: clock::Lamport,    file_update_count: usize,    git_diff_update_count: usize,    completion_triggers: Vec<String>,    completion_triggers_timestamp: clock::Lamport,    deferred_ops: OperationQueue<Operation>,    capability: Capability,} /// 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]>,    diagnostics_update_count: usize,    file_update_count: usize,    git_diff_update_count: usize,    remote_selections: TreeMap<ReplicaId, SelectionSet>,    selections_update_count: usize,    language: Option<Arc<Language>>,    parse_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, 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, Default)]pub enum IndentKind {    /// An ASCII space character.    #[default]    Space,    /// An ASCII tab character.    Tab,} /// The shape of a selection cursor.#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]pub enum CursorShape {    /// A vertical bar    #[default]    Bar,    /// A block that surrounds the following character    Block,    /// An underline that runs along the following character    Underscore,    /// 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,} /// 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),} /// A completion provided by a language server#[derive(Clone, Debug)]pub struct Completion {    /// The range of the buffer that will be replaced.    pub old_range: Range<Anchor>,    /// The new text that will be inserted.    pub new_text: String,    /// A label for this completion that is shown in the menu.    pub label: CodeLabel,    /// The id of the language server that produced this completion.    pub server_id: LanguageServerId,    /// The documentation for this completion.    pub documentation: Option<Documentation>,    /// The raw completion provided by the language server.    pub lsp_completion: lsp::CompletionItem,} /// A code action provided by a language server.#[derive(Clone, Debug)]pub struct CodeAction {    /// The id of the language server that produced this code action.    pub server_id: LanguageServerId,    /// The range of the buffer where this code action is applicable.    pub range: Range<Anchor>,    /// The raw code action provided by the language server.    pub lsp_action: lsp::CodeAction,} /// 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 Event {    /// The buffer was changed in a way that must be    /// propagated to its other replicas.    Operation(Operation),    /// 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's diff_base changed.    DiffBaseChanged,    /// 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 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) -> 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) -> usize;     /// Returns whether the file has been deleted.    fn is_deleted(&self) -> bool;     /// 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) -> 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>>;     /// Called when the buffer is reloaded from disk.    fn buffer_reloaded(        &self,        buffer_id: BufferId,        version: &clock::Global,        fingerprint: RopeFingerprint,        line_ending: LineEnding,        mtime: SystemTime,        cx: &mut AppContext,    );     /// 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(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> {    range: Range<usize>,    chunks: text::Chunks<'a>,    diagnostic_endpoints: 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, Copy, 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,} /// A set of edits to a given version of a buffer, computed asynchronously.

Lines 1–500 of 3541.