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