1use super::latest;
2use crate::wasm_host::wit::since_v0_0_4;
3use crate::wasm_host::WasmState;
4use anyhow::Result;
5use async_trait::async_trait;
6use extension::{ExtensionLanguageServerProxy, WorktreeDelegate};
7use language::LanguageServerBinaryStatus;
8use semantic_version::SemanticVersion;
9use std::sync::{Arc, OnceLock};
10use wasmtime::component::{Linker, Resource};
11
12pub const MIN_VERSION: SemanticVersion = SemanticVersion::new(0, 0, 1);
13
14wasmtime::component::bindgen!({
15 async: true,
16 trappable_imports: true,
17 path: "../extension_api/wit/since_v0.0.1",
18 with: {
19 "worktree": ExtensionWorktree,
20 "zed:extension/github": latest::zed::extension::github,
21 "zed:extension/platform": latest::zed::extension::platform,
22 },
23});
24
25pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
26
27pub fn linker() -> &'static Linker<WasmState> {
28 static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
29 LINKER.get_or_init(|| super::new_linker(Extension::add_to_linker))
30}
31
32impl From<DownloadedFileType> for latest::DownloadedFileType {
33 fn from(value: DownloadedFileType) -> Self {
34 match value {
35 DownloadedFileType::Gzip => latest::DownloadedFileType::Gzip,
36 DownloadedFileType::GzipTar => latest::DownloadedFileType::GzipTar,
37 DownloadedFileType::Zip => latest::DownloadedFileType::Zip,
38 DownloadedFileType::Uncompressed => latest::DownloadedFileType::Uncompressed,
39 }
40 }
41}
42
43impl From<since_v0_0_4::LanguageServerConfig> for LanguageServerConfig {
44 fn from(value: since_v0_0_4::LanguageServerConfig) -> Self {
45 Self {
46 name: value.name,
47 language_name: value.language_name,
48 }
49 }
50}
51
52impl From<Command> for latest::Command {
53 fn from(value: Command) -> Self {
54 Self {
55 command: value.command,
56 args: value.args,
57 env: value.env,
58 }
59 }
60}
61
62#[async_trait]
63impl HostWorktree for WasmState {
64 async fn read_text_file(
65 &mut self,
66 delegate: Resource<Arc<dyn WorktreeDelegate>>,
67 path: String,
68 ) -> wasmtime::Result<Result<String, String>> {
69 latest::HostWorktree::read_text_file(self, delegate, path).await
70 }
71
72 async fn shell_env(
73 &mut self,
74 delegate: Resource<Arc<dyn WorktreeDelegate>>,
75 ) -> wasmtime::Result<EnvVars> {
76 latest::HostWorktree::shell_env(self, delegate).await
77 }
78
79 async fn which(
80 &mut self,
81 delegate: Resource<Arc<dyn WorktreeDelegate>>,
82 binary_name: String,
83 ) -> wasmtime::Result<Option<String>> {
84 latest::HostWorktree::which(self, delegate, binary_name).await
85 }
86
87 fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
88 Ok(())
89 }
90}
91
92#[async_trait]
93impl ExtensionImports for WasmState {
94 async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {
95 latest::nodejs::Host::node_binary_path(self).await
96 }
97
98 async fn npm_package_latest_version(
99 &mut self,
100 package_name: String,
101 ) -> wasmtime::Result<Result<String, String>> {
102 latest::nodejs::Host::npm_package_latest_version(self, package_name).await
103 }
104
105 async fn npm_package_installed_version(
106 &mut self,
107 package_name: String,
108 ) -> wasmtime::Result<Result<Option<String>, String>> {
109 latest::nodejs::Host::npm_package_installed_version(self, package_name).await
110 }
111
112 async fn npm_install_package(
113 &mut self,
114 package_name: String,
115 version: String,
116 ) -> wasmtime::Result<Result<(), String>> {
117 latest::nodejs::Host::npm_install_package(self, package_name, version).await
118 }
119
120 async fn latest_github_release(
121 &mut self,
122 repo: String,
123 options: GithubReleaseOptions,
124 ) -> wasmtime::Result<Result<GithubRelease, String>> {
125 latest::zed::extension::github::Host::latest_github_release(self, repo, options).await
126 }
127
128 async fn current_platform(&mut self) -> Result<(Os, Architecture)> {
129 latest::zed::extension::platform::Host::current_platform(self).await
130 }
131
132 async fn set_language_server_installation_status(
133 &mut self,
134 server_name: String,
135 status: LanguageServerInstallationStatus,
136 ) -> wasmtime::Result<()> {
137 let status = match status {
138 LanguageServerInstallationStatus::CheckingForUpdate => {
139 LanguageServerBinaryStatus::CheckingForUpdate
140 }
141 LanguageServerInstallationStatus::Downloading => {
142 LanguageServerBinaryStatus::Downloading
143 }
144 LanguageServerInstallationStatus::Cached
145 | LanguageServerInstallationStatus::Downloaded => LanguageServerBinaryStatus::None,
146 LanguageServerInstallationStatus::Failed(error) => {
147 LanguageServerBinaryStatus::Failed { error }
148 }
149 };
150
151 self.host
152 .proxy
153 .update_language_server_status(lsp::LanguageServerName(server_name.into()), status);
154
155 Ok(())
156 }
157
158 async fn download_file(
159 &mut self,
160 url: String,
161 path: String,
162 file_type: DownloadedFileType,
163 ) -> wasmtime::Result<Result<(), String>> {
164 latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
165 }
166}