4589 lines · 152.5 KB · Rust
RawDownload
pub mod buffer_store;mod color_extractor;pub mod connection_manager;pub mod debounced_delay;pub mod git;pub mod image_store;pub mod lsp_command;pub mod lsp_ext_command;pub mod lsp_store;pub mod prettier_store;pub mod project_settings;pub mod search;mod task_inventory;pub mod task_store;pub mod terminals;pub mod toolchain_store;pub mod worktree_store; #[cfg(test)]mod project_tests; mod direnv;mod environment;use diff::BufferDiff;pub use environment::EnvironmentErrorMessage;use git::Repository;pub mod search_history;mod yarn; use crate::git::GitState;use anyhow::{anyhow, Context as _, Result};use buffer_store::{BufferStore, BufferStoreEvent};use client::{    proto, Client, Collaborator, PendingEntitySubscription, ProjectId, TypedEnvelope, UserStore,};use clock::ReplicaId;use collections::{BTreeSet, HashMap, HashSet};use debounced_delay::DebouncedDelay;pub use environment::ProjectEnvironment;use futures::{    channel::mpsc::{self, UnboundedReceiver},    future::try_join_all,    StreamExt,};pub use image_store::{ImageItem, ImageStore};use image_store::{ImageItemEvent, ImageStoreEvent}; use ::git::{    blame::Blame,    repository::{Branch, GitRepository, RepoPath},    status::FileStatus,};use gpui::{    AnyEntity, App, AppContext as _, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter,    Hsla, SharedString, Task, WeakEntity, Window,};use itertools::Itertools;use language::{    language_settings::InlayHintKind, proto::split_operations, Buffer, BufferEvent,    CachedLspAdapter, Capability, CodeLabel, CompletionDocumentation, File as _, Language,    LanguageName, LanguageRegistry, PointUtf16, ToOffset, ToPointUtf16, Toolchain, ToolchainList,    Transaction, Unclipped,};use lsp::{    CodeActionKind, CompletionContext, CompletionItemKind, DocumentHighlightKind, LanguageServer,    LanguageServerId, LanguageServerName, MessageActionItem,};use lsp_command::*;use lsp_store::LspFormatTarget;use node_runtime::NodeRuntime;use parking_lot::Mutex;pub use prettier_store::PrettierStore;use project_settings::{ProjectSettings, SettingsObserver, SettingsObserverEvent};use remote::{SshConnectionOptions, SshRemoteClient};use rpc::{    proto::{LanguageServerPromptResponse, SSH_PROJECT_ID},    AnyProtoClient, ErrorCode,};use search::{SearchInputKind, SearchQuery, SearchResult};use search_history::SearchHistory;use settings::{InvalidSettingsError, Settings, SettingsLocation, SettingsStore};use smol::channel::Receiver;use snippet::Snippet;use snippet_provider::SnippetProvider;use std::{    borrow::Cow,    ops::Range,    path::{Component, Path, PathBuf},    pin::pin,    str,    sync::Arc,    time::Duration,};use task_store::TaskStore;use terminals::Terminals;use text::{Anchor, BufferId};use toolchain_store::EmptyToolchainStore;use util::{paths::compare_paths, ResultExt as _};use worktree::{CreatedEntry, Snapshot, Traversal};use worktree_store::{WorktreeStore, WorktreeStoreEvent}; pub use fs::*;pub use language::Location;#[cfg(any(test, feature = "test-support"))]pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;pub use task_inventory::{    BasicContextProvider, ContextProviderWithTasks, Inventory, TaskSourceKind,};pub use worktree::{    Entry, EntryKind, File, LocalWorktree, PathChange, ProjectEntryId, UpdatedEntriesSet,    UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings, FS_WATCH_LATENCY,}; pub use buffer_store::ProjectTransaction;pub use lsp_store::{    DiagnosticSummary, LanguageServerLogType, LanguageServerProgress, LanguageServerPromptRequest,    LanguageServerStatus, LanguageServerToQuery, LspStore, LspStoreEvent,    SERVER_PROGRESS_THROTTLE_TIMEOUT,};pub use toolchain_store::ToolchainStore;const MAX_PROJECT_SEARCH_HISTORY_SIZE: usize = 500;const MAX_SEARCH_RESULT_FILES: usize = 5_000;const MAX_SEARCH_RESULT_RANGES: usize = 10_000; pub trait ProjectItem {    fn try_open(        project: &Entity<Project>,        path: &ProjectPath,        cx: &mut App,    ) -> Option<Task<Result<Entity<Self>>>>    where        Self: Sized;    fn entry_id(&self, cx: &App) -> Option<ProjectEntryId>;    fn project_path(&self, cx: &App) -> Option<ProjectPath>;    fn is_dirty(&self) -> bool;} #[derive(Clone)]pub enum OpenedBufferEvent {    Disconnected,    Ok(BufferId),    Err(BufferId, Arc<anyhow::Error>),} /// Semantics-aware entity that is relevant to one or more [`Worktree`] with the files./// `Project` is responsible for tasks, LSP and collab queries, synchronizing worktree states accordingly./// Maps [`Worktree`] entries with its own logic using [`ProjectEntryId`] and [`ProjectPath`] structs.////// Can be either local (for the project opened on the same host) or remote.(for collab projects, browsed by multiple remote users).pub struct Project {    active_entry: Option<ProjectEntryId>,    buffer_ordered_messages_tx: mpsc::UnboundedSender<BufferOrderedMessage>,    languages: Arc<LanguageRegistry>,    client: Arc<client::Client>,    join_project_response_message_id: u32,    task_store: Entity<TaskStore>,    user_store: Entity<UserStore>,    fs: Arc<dyn Fs>,    ssh_client: Option<Entity<SshRemoteClient>>,    client_state: ProjectClientState,    git_state: Entity<GitState>,    collaborators: HashMap<proto::PeerId, Collaborator>,    client_subscriptions: Vec<client::Subscription>,    worktree_store: Entity<WorktreeStore>,    buffer_store: Entity<BufferStore>,    image_store: Entity<ImageStore>,    lsp_store: Entity<LspStore>,    _subscriptions: Vec<gpui::Subscription>,    buffers_needing_diff: HashSet<WeakEntity<Buffer>>,    git_diff_debouncer: DebouncedDelay<Self>,    remotely_created_models: Arc<Mutex<RemotelyCreatedModels>>,    terminals: Terminals,    node: Option<NodeRuntime>,    search_history: SearchHistory,    search_included_history: SearchHistory,    search_excluded_history: SearchHistory,    snippets: Entity<SnippetProvider>,    environment: Entity<ProjectEnvironment>,    settings_observer: Entity<SettingsObserver>,    toolchain_store: Option<Entity<ToolchainStore>>,} #[derive(Default)]struct RemotelyCreatedModels {    worktrees: Vec<Entity<Worktree>>,    buffers: Vec<Entity<Buffer>>,    retain_count: usize,} struct RemotelyCreatedModelGuard {    remote_models: std::sync::Weak<Mutex<RemotelyCreatedModels>>,} impl Drop for RemotelyCreatedModelGuard {    fn drop(&mut self) {        if let Some(remote_models) = self.remote_models.upgrade() {            let mut remote_models = remote_models.lock();            assert!(                remote_models.retain_count > 0,                "RemotelyCreatedModelGuard dropped too many times"            );            remote_models.retain_count -= 1;            if remote_models.retain_count == 0 {                remote_models.buffers.clear();                remote_models.worktrees.clear();            }        }    }}/// Message ordered with respect to buffer operations#[derive(Debug)]enum BufferOrderedMessage {    Operation {        buffer_id: BufferId,        operation: proto::Operation,    },    LanguageServerUpdate {        language_server_id: LanguageServerId,        message: proto::update_language_server::Variant,    },    Resync,} #[derive(Debug)]enum ProjectClientState {    /// Single-player mode.    Local,    /// Multi-player mode but still a local project.    Shared { remote_id: u64 },    /// Multi-player mode but working on a remote project.    Remote {        sharing_has_stopped: bool,        capability: Capability,        remote_id: u64,        replica_id: ReplicaId,    },} #[derive(Clone, Debug, PartialEq)]pub enum Event {    LanguageServerAdded(LanguageServerId, LanguageServerName, Option<WorktreeId>),    LanguageServerRemoved(LanguageServerId),    LanguageServerLog(LanguageServerId, LanguageServerLogType, String),    Toast {        notification_id: SharedString,        message: String,    },    HideToast {        notification_id: SharedString,    },    LanguageServerPrompt(LanguageServerPromptRequest),    LanguageNotFound(Entity<Buffer>),    ActiveEntryChanged(Option<ProjectEntryId>),    ActivateProjectPanel,    WorktreeAdded(WorktreeId),    WorktreeOrderChanged,    WorktreeRemoved(WorktreeId),    WorktreeUpdatedEntries(WorktreeId, UpdatedEntriesSet),    WorktreeUpdatedGitRepositories(WorktreeId),    DiskBasedDiagnosticsStarted {        language_server_id: LanguageServerId,    },    DiskBasedDiagnosticsFinished {        language_server_id: LanguageServerId,    },    DiagnosticsUpdated {        path: ProjectPath,        language_server_id: LanguageServerId,    },    RemoteIdChanged(Option<u64>),    DisconnectedFromHost,    DisconnectedFromSshRemote,    Closed,    DeletedEntry(WorktreeId, ProjectEntryId),    CollaboratorUpdated {        old_peer_id: proto::PeerId,        new_peer_id: proto::PeerId,    },    CollaboratorJoined(proto::PeerId),    CollaboratorLeft(proto::PeerId),    HostReshared,    Reshared,    Rejoined,    RefreshInlayHints,    RevealInProjectPanel(ProjectEntryId),    SnippetEdit(BufferId, Vec<(lsp::Range, Snippet)>),    ExpandedAllForEntry(WorktreeId, ProjectEntryId),} #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]pub struct ProjectPath {    pub worktree_id: WorktreeId,    pub path: Arc<Path>,} impl ProjectPath {    pub fn from_proto(p: proto::ProjectPath) -> Self {        Self {            worktree_id: WorktreeId::from_proto(p.worktree_id),            path: Arc::from(PathBuf::from(p.path)),        }    }     pub fn to_proto(&self) -> proto::ProjectPath {        proto::ProjectPath {            worktree_id: self.worktree_id.to_proto(),            path: self.path.to_string_lossy().to_string(),        }    }     pub fn root_path(worktree_id: WorktreeId) -> Self {        Self {            worktree_id,            path: Path::new("").into(),        }    }} #[derive(Debug, Default)]pub enum PrepareRenameResponse {    Success(Range<Anchor>),    OnlyUnpreparedRenameSupported,    #[default]    InvalidPosition,} #[derive(Debug, Clone, PartialEq, Eq)]pub struct InlayHint {    pub position: language::Anchor,    pub label: InlayHintLabel,    pub kind: Option<InlayHintKind>,    pub padding_left: bool,    pub padding_right: bool,    pub tooltip: Option<InlayHintTooltip>,    pub resolve_state: ResolveState,} /// The user's intent behind a given completion confirmation#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]pub enum CompletionIntent {    /// The user intends to 'commit' this result, if possible    /// completion confirmations should run side effects    Complete,    /// The user intends to continue 'composing' this completion    /// completion confirmations should not run side effects and    /// let the user continue composing their action    Compose,} impl CompletionIntent {    pub fn is_complete(&self) -> bool {        self == &Self::Complete    }     pub fn is_compose(&self) -> bool {        self == &Self::Compose    }} /// A completion provided by a language server#[derive(Clone)]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<CompletionDocumentation>,    /// The raw completion provided by the language server.    pub lsp_completion: lsp::CompletionItem,    /// Whether this completion has been resolved, to ensure it happens once per completion.    pub resolved: bool,    /// An optional callback to invoke when this completion is confirmed.    /// Returns, whether new completions should be retriggered after the current one.    /// If `true` is returned, the editor will show a new completion menu after this completion is confirmed.    /// if no confirmation is provided or `false` is returned, the completion will be committed.    pub confirm: Option<Arc<dyn Send + Sync + Fn(CompletionIntent, &mut Window, &mut App) -> bool>>,} impl std::fmt::Debug for Completion {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        f.debug_struct("Completion")            .field("old_range", &self.old_range)            .field("new_text", &self.new_text)            .field("label", &self.label)            .field("server_id", &self.server_id)            .field("documentation", &self.documentation)            .field("lsp_completion", &self.lsp_completion)            .finish()    }} /// A completion provided by a language server#[derive(Clone, Debug)]pub(crate) struct CoreCompletion {    old_range: Range<Anchor>,    new_text: String,    server_id: LanguageServerId,    lsp_completion: lsp::CompletionItem,    resolved: bool,} /// 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,} #[derive(Debug, Clone, PartialEq, Eq)]pub enum ResolveState {    Resolved,    CanResolve(LanguageServerId, Option<lsp::LSPAny>),    Resolving,} impl InlayHint {    pub fn text(&self) -> String {        match &self.label {            InlayHintLabel::String(s) => s.to_owned(),            InlayHintLabel::LabelParts(parts) => parts.iter().map(|part| &part.value).join(""),        }    }} #[derive(Debug, Clone, PartialEq, Eq)]pub enum InlayHintLabel {    String(String),    LabelParts(Vec<InlayHintLabelPart>),} #[derive(Debug, Clone, PartialEq, Eq)]pub struct InlayHintLabelPart {    pub value: String,    pub tooltip: Option<InlayHintLabelPartTooltip>,    pub location: Option<(LanguageServerId, lsp::Location)>,} #[derive(Debug, Clone, PartialEq, Eq)]pub enum InlayHintTooltip {    String(String),    MarkupContent(MarkupContent),} #[derive(Debug, Clone, PartialEq, Eq)]pub enum InlayHintLabelPartTooltip {    String(String),    MarkupContent(MarkupContent),} #[derive(Debug, Clone, PartialEq, Eq)]pub struct MarkupContent {    pub kind: HoverBlockKind,    pub value: String,} #[derive(Debug, Clone)]pub struct LocationLink {    pub origin: Option<Location>,    pub target: Location,} #[derive(Debug)]pub struct DocumentHighlight {    pub range: Range<language::Anchor>,    pub kind: DocumentHighlightKind,} #[derive(Clone, Debug)]pub struct Symbol {    pub language_server_name: LanguageServerName,    pub source_worktree_id: WorktreeId,    pub path: ProjectPath,    pub label: CodeLabel,    pub name: String,    pub kind: lsp::SymbolKind,    pub range: Range<Unclipped<PointUtf16>>,    pub signature: [u8; 32],} #[derive(Clone, Debug, PartialEq)]pub struct HoverBlock {    pub text: String,    pub kind: HoverBlockKind,} #[derive(Clone, Debug, PartialEq, Eq)]pub enum HoverBlockKind {    PlainText,    Markdown,    Code { language: String },}

Lines 1–500 of 4589.