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 language::{LanguageServerBinaryStatus, LspAdapterDelegate};
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 LspAdapterDelegate>;
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
61#[async_trait]
62impl HostWorktree for WasmState {
63 async fn read_text_file(
64 &mut self,
65 delegate: Resource<Arc<dyn LspAdapterDelegate>>,
66 path: String,
67 ) -> wasmtime::Result<Result<String, String>> {
68 latest::HostWorktree::read_text_file(self, delegate, path).await
69 }
70
71 async fn shell_env(
72 &mut self,
73 delegate: Resource<Arc<dyn LspAdapterDelegate>>,
74 ) -> wasmtime::Result<EnvVars> {
75 latest::HostWorktree::shell_env(self, delegate).await
76 }
77
78 async fn which(
79 &mut self,
80 delegate: Resource<Arc<dyn LspAdapterDelegate>>,
81 binary_name: String,
82 ) -> wasmtime::Result<Option<String>> {
83 latest::HostWorktree::which(self, delegate, binary_name).await
84 }
85
86 fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
87 Ok(())
88 }
89}
90
91#[async_trait]
92impl ExtensionImports for WasmState {
93 async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {
94 latest::nodejs::Host::node_binary_path(self).await
95 }
96
97 async fn npm_package_latest_version(
98 &mut self,
99 package_name: String,
100 ) -> wasmtime::Result<Result<String, String>> {
101 latest::nodejs::Host::npm_package_latest_version(self, package_name).await
102 }
103
104 async fn npm_package_installed_version(
105 &mut self,
106 package_name: String,
107 ) -> wasmtime::Result<Result<Option<String>, String>> {
108 latest::nodejs::Host::npm_package_installed_version(self, package_name).await
109 }
110
111 async fn npm_install_package(
112 &mut self,
113 package_name: String,
114 version: String,
115 ) -> wasmtime::Result<Result<(), String>> {
116 latest::nodejs::Host::npm_install_package(self, package_name, version).await
117 }
118
119 async fn latest_github_release(
120 &mut self,
121 repo: String,
122 options: GithubReleaseOptions,
123 ) -> wasmtime::Result<Result<GithubRelease, String>> {
124 latest::zed::extension::github::Host::latest_github_release(self, repo, options).await
125 }
126
127 async fn current_platform(&mut self) -> Result<(Os, Architecture)> {
128 latest::zed::extension::platform::Host::current_platform(self).await
129 }
130
131 async fn set_language_server_installation_status(
132 &mut self,
133 server_name: String,
134 status: LanguageServerInstallationStatus,
135 ) -> wasmtime::Result<()> {
136 let status = match status {
137 LanguageServerInstallationStatus::CheckingForUpdate => {
138 LanguageServerBinaryStatus::CheckingForUpdate
139 }
140 LanguageServerInstallationStatus::Downloading => {
141 LanguageServerBinaryStatus::Downloading
142 }
143 LanguageServerInstallationStatus::Cached
144 | LanguageServerInstallationStatus::Downloaded => LanguageServerBinaryStatus::None,
145 LanguageServerInstallationStatus::Failed(error) => {
146 LanguageServerBinaryStatus::Failed { error }
147 }
148 };
149
150 self.host
151 .language_registry
152 .update_lsp_status(language::LanguageServerName(server_name.into()), status);
153 Ok(())
154 }
155
156 async fn download_file(
157 &mut self,
158 url: String,
159 path: String,
160 file_type: DownloadedFileType,
161 ) -> wasmtime::Result<Result<(), String>> {
162 latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
163 }
164}