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