since_v0_6_0.rs

  1use crate::wasm_host::WasmState;
  2use anyhow::Result;
  3use extension::{KeyValueStoreDelegate, ProjectDelegate, WorktreeDelegate};
  4use gpui::BackgroundExecutor;
  5use semver::Version;
  6use std::sync::{Arc, OnceLock};
  7use wasmtime::component::{Linker, Resource};
  8
  9use super::latest;
 10
 11pub const MIN_VERSION: Version = Version::new(0, 6, 0);
 12pub const MAX_VERSION: Version = Version::new(0, 7, 0);
 13
 14wasmtime::component::bindgen!({
 15    async: true,
 16    trappable_imports: true,
 17    path: "../extension_api/wit/since_v0.6.0",
 18    with: {
 19        "worktree": ExtensionWorktree,
 20        "project": ExtensionProject,
 21        "key-value-store": ExtensionKeyValueStore,
 22        "zed:extension/common": latest::zed::extension::common,
 23        "zed:extension/github": latest::zed::extension::github,
 24        "zed:extension/http-client": latest::zed::extension::http_client,
 25        "zed:extension/lsp": latest::zed::extension::lsp,
 26        "zed:extension/nodejs": latest::zed::extension::nodejs,
 27        "zed:extension/platform": latest::zed::extension::platform,
 28        "zed:extension/process": latest::zed::extension::process,
 29        "zed:extension/slash-command": latest::zed::extension::slash_command,
 30        "zed:extension/context-server": latest::zed::extension::context_server,
 31        "zed:extension/dap": latest::zed::extension::dap,
 32    },
 33});
 34
 35pub use self::zed::extension::*;
 36
 37mod settings {
 38    #![allow(dead_code)]
 39    include!(concat!(env!("OUT_DIR"), "/since_v0.6.0/settings.rs"));
 40}
 41
 42pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
 43pub type ExtensionProject = Arc<dyn ProjectDelegate>;
 44pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
 45
 46pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
 47    static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
 48    LINKER.get_or_init(|| super::new_linker(executor, Extension::add_to_linker))
 49}
 50
 51impl From<CodeLabel> for latest::CodeLabel {
 52    fn from(value: CodeLabel) -> Self {
 53        Self {
 54            code: value.code,
 55            spans: value.spans.into_iter().map(Into::into).collect(),
 56            filter_range: value.filter_range,
 57        }
 58    }
 59}
 60
 61impl From<CodeLabelSpan> for latest::CodeLabelSpan {
 62    fn from(value: CodeLabelSpan) -> Self {
 63        match value {
 64            CodeLabelSpan::CodeRange(range) => Self::CodeRange(range),
 65            CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
 66        }
 67    }
 68}
 69
 70impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
 71    fn from(value: CodeLabelSpanLiteral) -> Self {
 72        Self {
 73            text: value.text,
 74            highlight_name: value.highlight_name,
 75        }
 76    }
 77}
 78
 79impl From<SettingsLocation> for latest::SettingsLocation {
 80    fn from(value: SettingsLocation) -> Self {
 81        Self {
 82            worktree_id: value.worktree_id,
 83            path: value.path,
 84        }
 85    }
 86}
 87
 88impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
 89    fn from(value: LanguageServerInstallationStatus) -> Self {
 90        match value {
 91            LanguageServerInstallationStatus::None => Self::None,
 92            LanguageServerInstallationStatus::Downloading => Self::Downloading,
 93            LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
 94            LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
 95        }
 96    }
 97}
 98
 99impl From<DownloadedFileType> for latest::DownloadedFileType {
100    fn from(value: DownloadedFileType) -> Self {
101        match value {
102            DownloadedFileType::Gzip => Self::Gzip,
103            DownloadedFileType::GzipTar => Self::GzipTar,
104            DownloadedFileType::Zip => Self::Zip,
105            DownloadedFileType::Uncompressed => Self::Uncompressed,
106        }
107    }
108}
109
110impl HostKeyValueStore for WasmState {
111    async fn insert(
112        &mut self,
113        kv_store: Resource<ExtensionKeyValueStore>,
114        key: String,
115        value: String,
116    ) -> wasmtime::Result<Result<(), String>> {
117        latest::HostKeyValueStore::insert(self, kv_store, key, value).await
118    }
119
120    async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
121        // We only ever hand out borrows of key-value stores.
122        Ok(())
123    }
124}
125
126impl HostProject for WasmState {
127    async fn worktree_ids(
128        &mut self,
129        project: Resource<ExtensionProject>,
130    ) -> wasmtime::Result<Vec<u64>> {
131        latest::HostProject::worktree_ids(self, project).await
132    }
133
134    async fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
135        // We only ever hand out borrows of projects.
136        Ok(())
137    }
138}
139
140impl HostWorktree for WasmState {
141    async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
142        latest::HostWorktree::id(self, delegate).await
143    }
144
145    async fn root_path(
146        &mut self,
147        delegate: Resource<Arc<dyn WorktreeDelegate>>,
148    ) -> wasmtime::Result<String> {
149        latest::HostWorktree::root_path(self, delegate).await
150    }
151
152    async fn read_text_file(
153        &mut self,
154        delegate: Resource<Arc<dyn WorktreeDelegate>>,
155        path: String,
156    ) -> wasmtime::Result<Result<String, String>> {
157        latest::HostWorktree::read_text_file(self, delegate, path).await
158    }
159
160    async fn shell_env(
161        &mut self,
162        delegate: Resource<Arc<dyn WorktreeDelegate>>,
163    ) -> wasmtime::Result<EnvVars> {
164        latest::HostWorktree::shell_env(self, delegate).await
165    }
166
167    async fn which(
168        &mut self,
169        delegate: Resource<Arc<dyn WorktreeDelegate>>,
170        binary_name: String,
171    ) -> wasmtime::Result<Option<String>> {
172        latest::HostWorktree::which(self, delegate, binary_name).await
173    }
174
175    async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
176        // We only ever hand out borrows of worktrees.
177        Ok(())
178    }
179}
180
181impl ExtensionImports for WasmState {
182    async fn get_settings(
183        &mut self,
184        location: Option<self::SettingsLocation>,
185        category: String,
186        key: Option<String>,
187    ) -> wasmtime::Result<Result<String, String>> {
188        latest::ExtensionImports::get_settings(
189            self,
190            location.map(|location| location.into()),
191            category,
192            key,
193        )
194        .await
195    }
196
197    async fn set_language_server_installation_status(
198        &mut self,
199        server_name: String,
200        status: LanguageServerInstallationStatus,
201    ) -> wasmtime::Result<()> {
202        latest::ExtensionImports::set_language_server_installation_status(
203            self,
204            server_name,
205            status.into(),
206        )
207        .await
208    }
209
210    async fn download_file(
211        &mut self,
212        url: String,
213        path: String,
214        file_type: DownloadedFileType,
215    ) -> wasmtime::Result<Result<(), String>> {
216        latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
217    }
218
219    async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
220        latest::ExtensionImports::make_file_executable(self, path).await
221    }
222}