5887 lines · 198.1 KB · Rust
RawDownload
pub mod agent_server_store;pub mod buffer_store;mod color_extractor;pub mod connection_manager;pub mod context_server_store;pub mod debounced_delay;pub mod debugger;pub mod git_store;pub mod image_store;pub mod lsp_command;pub mod lsp_store;mod manifest_tree;pub mod prettier_store;mod project_search;pub mod project_settings;pub mod search;mod task_inventory;pub mod task_store;pub mod telemetry_snapshot;pub mod terminals;pub mod toolchain_store;pub mod trusted_worktrees;pub mod worktree_store; #[cfg(test)]mod project_tests; mod environment;use buffer_diff::BufferDiff;use context_server_store::ContextServerStore;pub use environment::ProjectEnvironmentEvent;use git::repository::get_git_committer;use git_store::{Repository, RepositoryId};pub mod search_history;mod yarn; use dap::inline_value::{InlineValueLocation, VariableLookupKind, VariableScope}; use crate::{    git_store::GitStore,    lsp_store::{SymbolLocation, log_store::LogKind},    project_search::SearchResultsHandle,    trusted_worktrees::{PathTrust, RemoteHostLocation, TrustedWorktrees},};pub use agent_server_store::{AgentServerStore, AgentServersUpdated, ExternalAgentServerName};pub use git_store::{    ConflictRegion, ConflictSet, ConflictSetSnapshot, ConflictSetUpdate,    git_traversal::{ChildEntriesGitIter, GitEntry, GitEntryRef, GitTraversal},};pub use manifest_tree::ManifestTree;pub use project_search::{Search, SearchResults}; use anyhow::{Context as _, Result, anyhow};use buffer_store::{BufferStore, BufferStoreEvent};use client::{    Client, Collaborator, PendingEntitySubscription, ProjectId, TypedEnvelope, UserStore, proto,};use clock::ReplicaId; use dap::client::DebugAdapterClient; use collections::{BTreeSet, HashMap, HashSet, IndexSet};use debounced_delay::DebouncedDelay;pub use debugger::breakpoint_store::BreakpointWithPosition;use debugger::{    breakpoint_store::{ActiveStackFrame, BreakpointStore},    dap_store::{DapStore, DapStoreEvent},    session::Session,};use encoding_rs;pub use environment::ProjectEnvironment;#[cfg(test)]use futures::future::join_all;use futures::{    StreamExt,    channel::mpsc::{self, UnboundedReceiver},    future::try_join_all,};pub use image_store::{ImageItem, ImageStore};use image_store::{ImageItemEvent, ImageStoreEvent}; use ::git::{blame::Blame, status::FileStatus};use gpui::{    App, AppContext, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Hsla, SharedString,    Task, WeakEntity, Window,};use language::{    Buffer, BufferEvent, Capability, CodeLabel, CursorShape, DiskState, Language, LanguageName,    LanguageRegistry, PointUtf16, ToOffset, ToPointUtf16, Toolchain, ToolchainMetadata,    ToolchainScope, Transaction, Unclipped, language_settings::InlayHintKind,    proto::split_operations,};use lsp::{    CodeActionKind, CompletionContext, CompletionItemKind, DocumentHighlightKind, InsertTextMode,    LanguageServerBinary, LanguageServerId, LanguageServerName, LanguageServerSelector,    MessageActionItem,};use lsp_command::*;use lsp_store::{CompletionDocumentation, LspFormatTarget, OpenLspBufferHandle};pub use manifest_tree::ManifestProvidersStore;use node_runtime::NodeRuntime;use parking_lot::Mutex;pub use prettier_store::PrettierStore;use project_settings::{ProjectSettings, SettingsObserver, SettingsObserverEvent};use remote::{RemoteClient, RemoteConnectionOptions};use rpc::{    AnyProtoClient, ErrorCode,    proto::{LanguageServerPromptResponse, REMOTE_SERVER_PROJECT_ID},};use search::{SearchInputKind, SearchQuery, SearchResult};use search_history::SearchHistory;use settings::{InvalidSettingsError, RegisterSetting, Settings, SettingsLocation, SettingsStore};use snippet::Snippet;pub use snippet_provider;use snippet_provider::SnippetProvider;use std::{    borrow::Cow,    collections::BTreeMap,    ffi::OsString,    ops::{Not as _, Range},    path::{Path, PathBuf},    pin::pin,    str::{self, FromStr},    sync::Arc,    time::Duration,}; use task_store::TaskStore;use terminals::Terminals;use text::{Anchor, BufferId, OffsetRangeExt, Point, Rope};use toolchain_store::EmptyToolchainStore;use util::{    ResultExt as _, maybe,    paths::{PathStyle, SanitizedPath, is_absolute},    rel_path::RelPath,};use worktree::{CreatedEntry, Snapshot, Traversal};pub use worktree::{    Entry, EntryKind, FS_WATCH_LATENCY, File, LocalWorktree, PathChange, ProjectEntryId,    UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings,};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, DebugScenarioContext, Inventory, TaskContexts,    TaskSourceKind,}; pub use buffer_store::ProjectTransaction;pub use lsp_store::{    DiagnosticSummary, InvalidationStrategy, LanguageServerLogType, LanguageServerProgress,    LanguageServerPromptRequest, LanguageServerStatus, LanguageServerToQuery, LspStore,    LspStoreEvent, ProgressToken, SERVER_PROGRESS_THROTTLE_TIMEOUT,};pub use toolchain_store::{ToolchainStore, Toolchains};const MAX_PROJECT_SEARCH_HISTORY_SIZE: usize = 500; pub trait ProjectItem: 'static {    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>,    dap_store: Entity<DapStore>,    agent_server_store: Entity<AgentServerStore>,     breakpoint_store: Entity<BreakpointStore>,    collab_client: Arc<client::Client>,    join_project_response_message_id: u32,    task_store: Entity<TaskStore>,    user_store: Entity<UserStore>,    fs: Arc<dyn Fs>,    remote_client: Option<Entity<RemoteClient>>,    client_state: ProjectClientState,    git_store: Entity<GitStore>,    collaborators: HashMap<proto::PeerId, Collaborator>,    client_subscriptions: Vec<client::Subscription>,    worktree_store: Entity<WorktreeStore>,    buffer_store: Entity<BufferStore>,    context_server_store: Entity<ContextServerStore>,    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>>,    agent_location: Option<AgentLocation>,} #[derive(Clone, Debug, PartialEq, Eq)]pub struct AgentLocation {    pub buffer: WeakEntity<Buffer>,    pub position: Anchor,} #[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,        name: Option<LanguageServerName>,    },    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),    // [`lsp::notification::DidOpenTextDocument`] was sent to this server using the buffer data.    // Zed's buffer-related data is updated accordingly.    LanguageServerBufferRegistered {        server_id: LanguageServerId,        buffer_id: BufferId,        buffer_abs_path: PathBuf,        name: Option<LanguageServerName>,    },    ToggleLspLogs {        server_id: LanguageServerId,        enabled: bool,        toggled_log_kind: LogKind,    },    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),    DiskBasedDiagnosticsStarted {        language_server_id: LanguageServerId,    },    DiskBasedDiagnosticsFinished {        language_server_id: LanguageServerId,    },    DiagnosticsUpdated {        paths: Vec<ProjectPath>,        language_server_id: LanguageServerId,    },    RemoteIdChanged(Option<u64>),    DisconnectedFromHost,    DisconnectedFromRemote,    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 {        server_id: LanguageServerId,        request_id: Option<usize>,    },    RefreshCodeLens,    RevealInProjectPanel(ProjectEntryId),    SnippetEdit(BufferId, Vec<(lsp::Range, Snippet)>),    ExpandedAllForEntry(WorktreeId, ProjectEntryId),    EntryRenamed(ProjectTransaction, ProjectPath, PathBuf),    WorkspaceEditApplied(ProjectTransaction),    AgentLocationChanged,} pub struct AgentLocationChanged; pub enum DebugAdapterClientState {    Starting(Task<Option<Arc<DebugAdapterClient>>>),    Running(Arc<DebugAdapterClient>),} #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]pub struct ProjectPath {    pub worktree_id: WorktreeId,    pub path: Arc<RelPath>,} impl ProjectPath {    pub fn from_file(value: &dyn language::File, cx: &App) -> Self {        ProjectPath {            worktree_id: value.worktree_id(cx),            path: value.path().clone(),        }    }     pub fn from_proto(p: proto::ProjectPath) -> Option<Self> {        Some(Self {            worktree_id: WorktreeId::from_proto(p.worktree_id),            path: RelPath::from_proto(&p.path).log_err()?,        })    }     pub fn to_proto(&self) -> proto::ProjectPath {        proto::ProjectPath {            worktree_id: self.worktree_id.to_proto(),            path: self.path.as_ref().to_proto(),        }    }     pub fn root_path(worktree_id: WorktreeId) -> Self {        Self {            worktree_id,            path: RelPath::empty().into(),        }    }     pub fn starts_with(&self, other: &ProjectPath) -> bool {        self.worktree_id == other.worktree_id && self.path.starts_with(&other.path)    }} #[derive(Debug, Default)]pub enum PrepareRenameResponse {    Success(Range<Anchor>),    OnlyUnpreparedRenameSupported,    #[default]    InvalidPosition,} #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]pub enum InlayId {    EditPrediction(usize),    DebuggerValue(usize),    // LSP    Hint(usize),    Color(usize),} impl InlayId {    pub fn id(&self) -> usize {        match self {            Self::EditPrediction(id) => *id,            Self::DebuggerValue(id) => *id,            Self::Hint(id) => *id,            Self::Color(id) => *id,        }    }} #[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.    ///    /// For LSP completions, will respect the setting `completions.lsp_insert_mode`.    Complete,    /// Similar to [Self::Complete], but behaves like `lsp_insert_mode` is set to `insert`.    CompleteWithInsert,    /// Similar to [Self::Complete], but behaves like `lsp_insert_mode` is set to `replace`.    CompleteWithReplace,    /// 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    }} /// Similar to `CoreCompletion`, but with extra metadata attached.#[derive(Clone)]pub struct Completion {    /// The range of text that will be replaced by this completion.    pub replace_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 documentation for this completion.    pub documentation: Option<CompletionDocumentation>,    /// Completion data source which it was constructed from.    pub source: CompletionSource,    /// A path to an icon for this completion that is shown in the menu.    pub icon_path: Option<SharedString>,    /// Text starting here and ending at the cursor will be used as the query for filtering this completion.    ///    /// If None, the start of the surrounding word is used.    pub match_start: Option<text::Anchor>,    /// Key used for de-duplicating snippets. If None, always considered unique.    pub snippet_deduplication_key: Option<(usize, usize)>,    /// Whether to adjust indentation (the default) or not.    pub insert_text_mode: Option<InsertTextMode>,    /// 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>>,

Lines 1–500 of 5887.