1110 lines · 36.7 KB · Rust
RawDownload
pub mod wit; use crate::capability_granter::CapabilityGranter;use crate::{ExtensionManifest, ExtensionSettings};use anyhow::{Context as _, Result, anyhow, bail};use async_trait::async_trait;use dap::{DebugRequest, StartDebuggingRequestArgumentsRequest};use extension::{    CodeLabel, Command, Completion, ContextServerConfiguration, DebugAdapterBinary,    DebugTaskDefinition, ExtensionCapability, ExtensionHostProxy, KeyValueStoreDelegate,    ProjectDelegate, SlashCommand, SlashCommandArgumentCompletion, SlashCommandOutput, Symbol,    WorktreeDelegate,};use fs::Fs;use futures::future::LocalBoxFuture;use futures::{    Future, FutureExt, StreamExt as _,    channel::{        mpsc::{self, UnboundedSender},        oneshot,    },    future::BoxFuture,};use gpui::{App, AsyncApp, BackgroundExecutor, Task};use http_client::HttpClient;use language::LanguageName;use lsp::LanguageServerName;use moka::sync::Cache;use node_runtime::NodeRuntime;use release_channel::ReleaseChannel;use semver::Version;use settings::Settings;use std::{    borrow::Cow,    path::{Path, PathBuf},    sync::{Arc, LazyLock, OnceLock},    time::Duration,};use task::{DebugScenario, SpawnInTerminal, TaskTemplate, ZedDebugConfig};use util::paths::SanitizedPath;use wasmtime::{    CacheStore, Engine, Store,    component::{Component, ResourceTable},};use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};use wit::Extension; pub struct WasmHost {    engine: Engine,    release_channel: ReleaseChannel,    http_client: Arc<dyn HttpClient>,    node_runtime: NodeRuntime,    pub(crate) proxy: Arc<ExtensionHostProxy>,    fs: Arc<dyn Fs>,    pub work_dir: PathBuf,    /// The capabilities granted to extensions running on the host.    pub(crate) granted_capabilities: Vec<ExtensionCapability>,    _main_thread_message_task: Task<()>,    main_thread_message_tx: mpsc::UnboundedSender<MainThreadCall>,} #[derive(Clone, Debug)]pub struct WasmExtension {    tx: UnboundedSender<ExtensionCall>,    pub manifest: Arc<ExtensionManifest>,    pub work_dir: Arc<Path>,    #[allow(unused)]    pub zed_api_version: Version,    _task: Arc<Task<Result<(), gpui_tokio::JoinError>>>,} impl Drop for WasmExtension {    fn drop(&mut self) {        self.tx.close_channel();    }} #[async_trait]impl extension::Extension for WasmExtension {    fn manifest(&self) -> Arc<ExtensionManifest> {        self.manifest.clone()    }     fn work_dir(&self) -> Arc<Path> {        self.work_dir.clone()    }     async fn language_server_command(        &self,        language_server_id: LanguageServerName,        language_name: LanguageName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Command> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                let command = extension                    .call_language_server_command(                        store,                        &language_server_id,                        &language_name,                        resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 Ok(command.into())            }            .boxed()        })        .await?    }     async fn language_server_initialization_options(        &self,        language_server_id: LanguageServerName,        language_name: LanguageName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Option<String>> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                let options = extension                    .call_language_server_initialization_options(                        store,                        &language_server_id,                        &language_name,                        resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                anyhow::Ok(options)            }            .boxed()        })        .await?    }     async fn language_server_workspace_configuration(        &self,        language_server_id: LanguageServerName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Option<String>> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                let options = extension                    .call_language_server_workspace_configuration(                        store,                        &language_server_id,                        resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                anyhow::Ok(options)            }            .boxed()        })        .await?    }     async fn language_server_initialization_options_schema(        &self,        language_server_id: LanguageServerName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Option<String>> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                extension                    .call_language_server_initialization_options_schema(                        store,                        &language_server_id,                        resource,                    )                    .await            }            .boxed()        })        .await?    }     async fn language_server_workspace_configuration_schema(        &self,        language_server_id: LanguageServerName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Option<String>> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                extension                    .call_language_server_workspace_configuration_schema(                        store,                        &language_server_id,                        resource,                    )                    .await            }            .boxed()        })        .await?    }     async fn language_server_additional_initialization_options(        &self,        language_server_id: LanguageServerName,        target_language_server_id: LanguageServerName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Option<String>> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                let options = extension                    .call_language_server_additional_initialization_options(                        store,                        &language_server_id,                        &target_language_server_id,                        resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                anyhow::Ok(options)            }            .boxed()        })        .await?    }     async fn language_server_additional_workspace_configuration(        &self,        language_server_id: LanguageServerName,        target_language_server_id: LanguageServerName,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<Option<String>> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                let options = extension                    .call_language_server_additional_workspace_configuration(                        store,                        &language_server_id,                        &target_language_server_id,                        resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                anyhow::Ok(options)            }            .boxed()        })        .await?    }     async fn labels_for_completions(        &self,        language_server_id: LanguageServerName,        completions: Vec<Completion>,    ) -> Result<Vec<Option<CodeLabel>>> {        self.call(|extension, store| {            async move {                let labels = extension                    .call_labels_for_completions(                        store,                        &language_server_id,                        completions.into_iter().map(Into::into).collect(),                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 Ok(labels                    .into_iter()                    .map(|label| label.map(Into::into))                    .collect())            }            .boxed()        })        .await?    }     async fn labels_for_symbols(        &self,        language_server_id: LanguageServerName,        symbols: Vec<Symbol>,    ) -> Result<Vec<Option<CodeLabel>>> {        self.call(|extension, store| {            async move {                let labels = extension                    .call_labels_for_symbols(                        store,                        &language_server_id,                        symbols.into_iter().map(Into::into).collect(),                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 Ok(labels                    .into_iter()                    .map(|label| label.map(Into::into))                    .collect())            }            .boxed()        })        .await?    }     async fn complete_slash_command_argument(        &self,        command: SlashCommand,        arguments: Vec<String>,    ) -> Result<Vec<SlashCommandArgumentCompletion>> {        self.call(|extension, store| {            async move {                let completions = extension                    .call_complete_slash_command_argument(store, &command.into(), &arguments)                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 Ok(completions.into_iter().map(Into::into).collect())            }            .boxed()        })        .await?    }     async fn run_slash_command(        &self,        command: SlashCommand,        arguments: Vec<String>,        delegate: Option<Arc<dyn WorktreeDelegate>>,    ) -> Result<SlashCommandOutput> {        self.call(|extension, store| {            async move {                let resource = if let Some(delegate) = delegate {                    Some(store.data_mut().table.push(delegate)?)                } else {                    None                };                 let output = extension                    .call_run_slash_command(store, &command.into(), &arguments, resource)                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 Ok(output.into())            }            .boxed()        })        .await?    }     async fn context_server_command(        &self,        context_server_id: Arc<str>,        project: Arc<dyn ProjectDelegate>,    ) -> Result<Command> {        self.call(|extension, store| {            async move {                let project_resource = store.data_mut().table.push(project)?;                let command = extension                    .call_context_server_command(store, context_server_id.clone(), project_resource)                    .await?                    .map_err(|err| store.data().extension_error(err))?;                anyhow::Ok(command.into())            }            .boxed()        })        .await?    }     async fn context_server_configuration(        &self,        context_server_id: Arc<str>,        project: Arc<dyn ProjectDelegate>,    ) -> Result<Option<ContextServerConfiguration>> {        self.call(|extension, store| {            async move {                let project_resource = store.data_mut().table.push(project)?;                let Some(configuration) = extension                    .call_context_server_configuration(                        store,                        context_server_id.clone(),                        project_resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?                else {                    return Ok(None);                };                 Ok(Some(configuration.try_into()?))            }            .boxed()        })        .await?    }     async fn suggest_docs_packages(&self, provider: Arc<str>) -> Result<Vec<String>> {        self.call(|extension, store| {            async move {                let packages = extension                    .call_suggest_docs_packages(store, provider.as_ref())                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 Ok(packages)            }            .boxed()        })        .await?    }     async fn index_docs(        &self,        provider: Arc<str>,        package_name: Arc<str>,        kv_store: Arc<dyn KeyValueStoreDelegate>,    ) -> Result<()> {        self.call(|extension, store| {            async move {                let kv_store_resource = store.data_mut().table.push(kv_store)?;                extension                    .call_index_docs(                        store,                        provider.as_ref(),                        package_name.as_ref(),                        kv_store_resource,                    )                    .await?                    .map_err(|err| store.data().extension_error(err))?;                 anyhow::Ok(())            }            .boxed()        })        .await?    }     async fn get_dap_binary(        &self,        dap_name: Arc<str>,        config: DebugTaskDefinition,        user_installed_path: Option<PathBuf>,        worktree: Arc<dyn WorktreeDelegate>,    ) -> Result<DebugAdapterBinary> {        self.call(|extension, store| {            async move {                let resource = store.data_mut().table.push(worktree)?;                let dap_binary = extension                    .call_get_dap_binary(store, dap_name, config, user_installed_path, resource)                    .await?                    .map_err(|err| store.data().extension_error(err))?;                let dap_binary = dap_binary.try_into()?;                Ok(dap_binary)            }            .boxed()        })        .await?    }    async fn dap_request_kind(        &self,        dap_name: Arc<str>,        config: serde_json::Value,    ) -> Result<StartDebuggingRequestArgumentsRequest> {        self.call(|extension, store| {            async move {                let kind = extension                    .call_dap_request_kind(store, dap_name, config)                    .await?                    .map_err(|err| store.data().extension_error(err))?;                Ok(kind.into())            }            .boxed()        })        .await?    }     async fn dap_config_to_scenario(&self, config: ZedDebugConfig) -> Result<DebugScenario> {        self.call(|extension, store| {            async move {                let kind = extension                    .call_dap_config_to_scenario(store, config)                    .await?                    .map_err(|err| store.data().extension_error(err))?;                Ok(kind)            }            .boxed()        })        .await?    }     async fn dap_locator_create_scenario(        &self,        locator_name: String,        build_config_template: TaskTemplate,        resolved_label: String,        debug_adapter_name: String,    ) -> Result<Option<DebugScenario>> {        self.call(|extension, store| {            async move {                extension

Lines 1–500 of 1110.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t