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;pub use environment::EnvironmentErrorMessage;pub mod search_history;mod yarn; use crate::git::GitState;use anyhow::{anyhow, Context as _, Result};use buffer_store::{BufferChangeSet, BufferStore, BufferStoreEvent};use client::{proto, Client, Collaborator, PendingEntitySubscription, 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}, status::FileStatus,};use gpui::{ AnyModel, AppContext, AsyncAppContext, BorrowAppContext, Context as _, EventEmitter, Hsla, Model, ModelContext, SharedString, Task, WeakModel, WindowContext,};use itertools::Itertools;use language::{ language_settings::InlayHintKind, proto::split_operations, Buffer, BufferEvent, CachedLspAdapter, Capability, CodeLabel, Documentation, 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: &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>; 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: Model<TaskStore>, user_store: Model<UserStore>, fs: Arc<dyn Fs>, ssh_client: Option<Model<SshRemoteClient>>, client_state: ProjectClientState, git_state: Option<Model<GitState>>, collaborators: HashMap<proto::PeerId, Collaborator>, client_subscriptions: Vec<client::Subscription>, worktree_store: Model<WorktreeStore>, buffer_store: Model<BufferStore>, image_store: Model<ImageStore>, lsp_store: Model<LspStore>, _subscriptions: Vec<gpui::Subscription>, buffers_needing_diff: HashSet<WeakModel<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: Model<SnippetProvider>, environment: Model<ProjectEnvironment>, settings_observer: Model<SettingsObserver>, toolchain_store: Option<Model<ToolchainStore>>,} #[derive(Default)]struct RemotelyCreatedModels { worktrees: Vec<Model<Worktree>>, buffers: Vec<Model<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(Model<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)>),} #[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<Documentation>, /// 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 WindowContext) -> 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 },} #[derive(Debug, Clone)]pub struct Hover { pub contents: Vec<HoverBlock>, pub range: Option<Range<language::Anchor>>,Lines 1–500 of 4453. Load more
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; pub use environment::EnvironmentErrorMessage; pub mod search_history; mod yarn; use crate::git::GitState; use anyhow::{anyhow, Context as _, Result}; use buffer_store::{BufferChangeSet, BufferStore, BufferStoreEvent}; use client::{proto, Client, Collaborator, PendingEntitySubscription, 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}, status::FileStatus, }; use gpui::{ AnyModel, AppContext, AsyncAppContext, BorrowAppContext, Context as _, EventEmitter, Hsla, Model, ModelContext, SharedString, Task, WeakModel, WindowContext, }; use itertools::Itertools; use language::{ language_settings::InlayHintKind, proto::split_operations, Buffer, BufferEvent, CachedLspAdapter, Capability, CodeLabel, Documentation, 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: &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>; 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: Model<TaskStore>, user_store: Model<UserStore>, fs: Arc<dyn Fs>, ssh_client: Option<Model<SshRemoteClient>>, client_state: ProjectClientState, git_state: Option<Model<GitState>>, collaborators: HashMap<proto::PeerId, Collaborator>, client_subscriptions: Vec<client::Subscription>, worktree_store: Model<WorktreeStore>, buffer_store: Model<BufferStore>, image_store: Model<ImageStore>, lsp_store: Model<LspStore>, _subscriptions: Vec<gpui::Subscription>, buffers_needing_diff: HashSet<WeakModel<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: Model<SnippetProvider>, environment: Model<ProjectEnvironment>, settings_observer: Model<SettingsObserver>, toolchain_store: Option<Model<ToolchainStore>>, } #[derive(Default)] struct RemotelyCreatedModels { worktrees: Vec<Model<Worktree>>, buffers: Vec<Model<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(Model<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)>), } #[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<Documentation>, /// 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 WindowContext) -> 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 }, } #[derive(Debug, Clone)] pub struct Hover { pub contents: Vec<HoverBlock>, pub range: Option<Range<language::Anchor>>,