11077 lines · 417.0 KB · Rust
RawDownload
pub mod connection_manager;pub mod debounced_delay;pub mod lsp_command;pub mod lsp_ext_command;mod prettier_support;pub mod project_settings;pub mod search;mod task_inventory;pub mod terminals; #[cfg(test)]mod project_tests;pub mod search_history; use anyhow::{anyhow, bail, Context as _, Result};use async_trait::async_trait;use client::{    proto, Client, Collaborator, DevServerProjectId, PendingEntitySubscription, ProjectId,    TypedEnvelope, UserStore,};use clock::ReplicaId;use collections::{hash_map, BTreeMap, HashMap, HashSet, VecDeque};use debounced_delay::DebouncedDelay;use futures::{    channel::{        mpsc::{self, UnboundedReceiver},        oneshot,    },    future::{join_all, try_join_all, Shared},    select,    stream::FuturesUnordered,    AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt,};use fuzzy::CharBag;use git::{blame::Blame, repository::GitRepository};use globset::{Glob, GlobSet, GlobSetBuilder};use gpui::{    AnyModel, AppContext, AsyncAppContext, BackgroundExecutor, BorrowAppContext, Context, Entity,    EventEmitter, Model, ModelContext, PromptLevel, Task, WeakModel,};use itertools::Itertools;use language::{    language_settings::{language_settings, FormatOnSave, Formatter, InlayHintKind},    markdown, point_to_lsp, prepare_completion_documentation,    proto::{        deserialize_anchor, deserialize_line_ending, deserialize_version, serialize_anchor,        serialize_version, split_operations,    },    range_from_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, Capability, CodeLabel,    Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Documentation, Event as BufferEvent,    File as _, Language, LanguageRegistry, LanguageServerName, LocalFile, LspAdapterDelegate,    Operation, Patch, PendingLanguageServer, PointUtf16, TextBufferSnapshot, ToOffset,    ToPointUtf16, Transaction, Unclipped,};use log::error;use lsp::{    DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions,    DocumentHighlightKind, Edit, LanguageServer, LanguageServerBinary, LanguageServerId,    LspRequestFuture, MessageActionItem, OneOf, ServerCapabilities, ServerHealthStatus,    ServerStatus, TextEdit,};use lsp_command::*;use node_runtime::NodeRuntime;use parking_lot::{Mutex, RwLock};use postage::watch;use prettier_support::{DefaultPrettier, PrettierInstance};use project_settings::{LspSettings, ProjectSettings};use rand::prelude::*;use search_history::SearchHistory;use snippet::Snippet;use worktree::LocalSnapshot; use http::{HttpClient, Url};use rpc::{ErrorCode, ErrorExt as _};use search::SearchQuery;use serde::Serialize;use settings::{watch_config_file, Settings, SettingsLocation, SettingsStore};use sha2::{Digest, Sha256};use similar::{ChangeTag, TextDiff};use smol::channel::{Receiver, Sender};use smol::lock::Semaphore;use std::{    cmp::{self, Ordering},    convert::TryInto,    env,    ffi::OsStr,    hash::Hash,    io, iter, mem,    num::NonZeroU32,    ops::Range,    path::{self, Component, Path, PathBuf},    process::Stdio,    str::{self, FromStr},    sync::{        atomic::{AtomicUsize, Ordering::SeqCst},        Arc,    },    time::{Duration, Instant},};use task::static_source::{StaticSource, TrackedFile};use terminals::Terminals;use text::{Anchor, BufferId, LineEnding};use util::{    debug_panic, defer, maybe, merge_json_value_into, parse_env_output,    paths::{        LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH, LOCAL_VSCODE_TASKS_RELATIVE_PATH,    },    post_inc, ResultExt, TryFutureExt as _,};use worktree::{Snapshot, Traversal}; 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::{Inventory, TaskSourceKind};pub use worktree::{    DiagnosticSummary, Entry, EntryKind, File, LocalWorktree, PathChange, ProjectEntryId,    RepositoryEntry, UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId,    WorktreeSettings, FS_WATCH_LATENCY,}; const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4;const SERVER_REINSTALL_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);pub const SERVER_PROGRESS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(100); const MAX_PROJECT_SEARCH_HISTORY_SIZE: usize = 500; pub trait Item {    fn try_open(        project: &Model<Project>,        path: &ProjectPath,        cx: &mut AppContext,    ) -> Option<Task<Result<Model<Self>>>>    where        Self: Sized;    fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId>;    fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;} #[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 {    worktrees: Vec<WorktreeHandle>,    active_entry: Option<ProjectEntryId>,    buffer_ordered_messages_tx: mpsc::UnboundedSender<BufferOrderedMessage>,    pending_language_server_update: Option<BufferOrderedMessage>,    flush_language_server_update: Option<Task<()>>,     languages: Arc<LanguageRegistry>,    supplementary_language_servers:        HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,    language_servers: HashMap<LanguageServerId, LanguageServerState>,    language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,    language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,    last_formatting_failure: Option<String>,    last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,    language_server_watched_paths: HashMap<LanguageServerId, HashMap<WorktreeId, GlobSet>>,    client: Arc<client::Client>,    next_entry_id: Arc<AtomicUsize>,    join_project_response_message_id: u32,    next_diagnostic_group_id: usize,    user_store: Model<UserStore>,    fs: Arc<dyn Fs>,    client_state: ProjectClientState,    collaborators: HashMap<proto::PeerId, Collaborator>,    client_subscriptions: Vec<client::Subscription>,    _subscriptions: Vec<gpui::Subscription>,    loading_buffers: HashMap<BufferId, Vec<oneshot::Sender<Result<Model<Buffer>, anyhow::Error>>>>,    incomplete_remote_buffers: HashMap<BufferId, Model<Buffer>>,    shared_buffers: HashMap<proto::PeerId, HashSet<BufferId>>,    #[allow(clippy::type_complexity)]    loading_buffers_by_path: HashMap<        ProjectPath,        postage::watch::Receiver<Option<Result<Model<Buffer>, Arc<anyhow::Error>>>>,    >,    #[allow(clippy::type_complexity)]    loading_local_worktrees:        HashMap<Arc<Path>, Shared<Task<Result<Model<Worktree>, Arc<anyhow::Error>>>>>,    opened_buffers: HashMap<BufferId, OpenBuffer>,    local_buffer_ids_by_path: HashMap<ProjectPath, BufferId>,    local_buffer_ids_by_entry_id: HashMap<ProjectEntryId, BufferId>,    buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots    buffers_being_formatted: HashSet<BufferId>,    buffers_needing_diff: HashSet<WeakModel<Buffer>>,    git_diff_debouncer: DebouncedDelay,    nonce: u128,    _maintain_buffer_languages: Task<()>,    _maintain_workspace_config: Task<Result<()>>,    terminals: Terminals,    current_lsp_settings: HashMap<Arc<str>, LspSettings>,    node: Option<Arc<dyn NodeRuntime>>,    default_prettier: DefaultPrettier,    prettiers_per_worktree: HashMap<WorktreeId, HashSet<Option<PathBuf>>>,    prettier_instances: HashMap<PathBuf, PrettierInstance>,    tasks: Model<Inventory>,    hosted_project_id: Option<ProjectId>,    dev_server_project_id: Option<client::DevServerProjectId>,    search_history: SearchHistory,} pub enum LanguageServerToQuery {    Primary,    Other(LanguageServerId),} struct LspBufferSnapshot {    version: i32,    snapshot: TextBufferSnapshot,} /// 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 LocalProjectUpdate {    WorktreesChanged,    CreateBufferForPeer {        peer_id: proto::PeerId,        buffer_id: BufferId,    },} enum OpenBuffer {    Strong(Model<Buffer>),    Weak(WeakModel<Buffer>),    Operations(Vec<Operation>),} #[derive(Clone)]enum WorktreeHandle {    Strong(Model<Worktree>),    Weak(WeakModel<Worktree>),} #[derive(Debug)]enum ProjectClientState {    Local,    Shared {        remote_id: u64,        updates_tx: mpsc::UnboundedSender<LocalProjectUpdate>,        _send_updates: Task<Result<()>>,    },    Remote {        sharing_has_stopped: bool,        capability: Capability,        remote_id: u64,        replica_id: ReplicaId,        in_room: bool,    },} /// A prompt requested by LSP server.#[derive(Clone, Debug)]pub struct LanguageServerPromptRequest {    pub level: PromptLevel,    pub message: String,    pub actions: Vec<MessageActionItem>,    pub lsp_name: String,    response_channel: Sender<MessageActionItem>,} impl LanguageServerPromptRequest {    pub async fn respond(self, index: usize) -> Option<()> {        if let Some(response) = self.actions.into_iter().nth(index) {            self.response_channel.send(response).await.ok()        } else {            None        }    }}impl PartialEq for LanguageServerPromptRequest {    fn eq(&self, other: &Self) -> bool {        self.message == other.message && self.actions == other.actions    }} #[derive(Clone, Debug, PartialEq)]pub enum Event {    LanguageServerAdded(LanguageServerId),    LanguageServerRemoved(LanguageServerId),    LanguageServerLog(LanguageServerId, String),    Notification(String),    LanguageServerPrompt(LanguageServerPromptRequest),    LanguageNotFound(Model<Buffer>),    ActiveEntryChanged(Option<ProjectEntryId>),    ActivateProjectPanel,    WorktreeAdded,    WorktreeRemoved(WorktreeId),    WorktreeUpdatedEntries(WorktreeId, UpdatedEntriesSet),    WorktreeUpdatedGitRepositories,    DiskBasedDiagnosticsStarted {        language_server_id: LanguageServerId,    },    DiskBasedDiagnosticsFinished {        language_server_id: LanguageServerId,    },    DiagnosticsUpdated {        path: ProjectPath,        language_server_id: LanguageServerId,    },    RemoteIdChanged(Option<u64>),    DisconnectedFromHost,    Closed,    DeletedEntry(ProjectEntryId),    CollaboratorUpdated {        old_peer_id: proto::PeerId,        new_peer_id: proto::PeerId,    },    CollaboratorJoined(proto::PeerId),    CollaboratorLeft(proto::PeerId),    RefreshInlayHints,    RevealInProjectPanel(ProjectEntryId),    SnippetEdit(BufferId, Vec<(lsp::Range, Snippet)>),} pub enum LanguageServerState {    Starting(Task<Option<Arc<LanguageServer>>>),     Running {        language: Arc<Language>,        adapter: Arc<CachedLspAdapter>,        server: Arc<LanguageServer>,        simulate_disk_based_diagnostics_completion: Option<Task<()>>,    },} #[derive(Clone, Debug, Serialize)]pub struct LanguageServerStatus {    pub name: String,    pub pending_work: BTreeMap<String, LanguageServerProgress>,    pub has_pending_diagnostic_updates: bool,    progress_tokens: HashSet<String>,} #[derive(Clone, Debug, Serialize)]pub struct LanguageServerProgress {    pub message: Option<String>,    pub percentage: Option<usize>,    #[serde(skip_serializing)]    pub last_update_at: Instant,} #[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(),        }    }} #[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,} /// 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 completion provided by a language server#[derive(Clone, Debug)]struct CoreCompletion {    old_range: Range<Anchor>,    new_text: String,    server_id: LanguageServerId,    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,} #[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,

Lines 1–500 of 11077.