logiguard fork: GPUI xdg-activation keyboard-focus serial fix
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
Single-commit orphan branch: full zed-industries/zed @ 8c74db0 source tree with a 3-file patch applied (no upstream history). Patch (crates/gpui_linux/src/linux/wayland/): - serial.rs: add SerialKind::KeyboardEnter - client.rs: store wl_keyboard.enter serial; add latest_serial_of() - window.rs: activate() uses keyboard-enter serial (Mutter focus gate) Mutter honors window activation only when the token carries the keyboard- focus serial from wl_keyboard.enter; GPUI used a stale mouse-press serial. See docs/tray-window-focus-wayland.md in logiguard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1281
crates/extension_host/src/wasm_host/wit.rs
Normal file
1281
crates/extension_host/src/wasm_host/wit.rs
Normal file
File diff suppressed because it is too large
Load Diff
166
crates/extension_host/src/wasm_host/wit/since_v0_0_1.rs
Normal file
166
crates/extension_host/src/wasm_host/wit/since_v0_0_1.rs
Normal file
@@ -0,0 +1,166 @@
|
||||
use super::{latest, since_v0_6_0};
|
||||
use crate::wasm_host::WasmState;
|
||||
use crate::wasm_host::wit::since_v0_0_4;
|
||||
use anyhow::Result;
|
||||
use extension::{ExtensionLanguageServerProxy, WorktreeDelegate};
|
||||
use gpui::BackgroundExecutor;
|
||||
use language::BinaryStatus;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 0, 1);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.0.1",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
},
|
||||
});
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => latest::DownloadedFileType::Gzip,
|
||||
DownloadedFileType::GzipTar => latest::DownloadedFileType::GzipTar,
|
||||
DownloadedFileType::Zip => latest::DownloadedFileType::Zip,
|
||||
DownloadedFileType::Uncompressed => latest::DownloadedFileType::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<since_v0_0_4::LanguageServerConfig> for LanguageServerConfig {
|
||||
fn from(value: since_v0_0_4::LanguageServerConfig) -> Self {
|
||||
Self {
|
||||
name: value.name,
|
||||
language_name: value.language_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Command> for latest::Command {
|
||||
fn from(value: Command) -> Self {
|
||||
Self {
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::nodejs::Host::node_binary_path(self).await
|
||||
}
|
||||
|
||||
async fn npm_package_latest_version(
|
||||
&mut self,
|
||||
package_name: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::nodejs::Host::npm_package_latest_version(self, package_name).await
|
||||
}
|
||||
|
||||
async fn npm_package_installed_version(
|
||||
&mut self,
|
||||
package_name: String,
|
||||
) -> wasmtime::Result<Result<Option<String>, String>> {
|
||||
latest::nodejs::Host::npm_package_installed_version(self, package_name).await
|
||||
}
|
||||
|
||||
async fn npm_install_package(
|
||||
&mut self,
|
||||
package_name: String,
|
||||
version: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::nodejs::Host::npm_install_package(self, package_name, version).await
|
||||
}
|
||||
|
||||
async fn latest_github_release(
|
||||
&mut self,
|
||||
repo: String,
|
||||
options: GithubReleaseOptions,
|
||||
) -> wasmtime::Result<Result<GithubRelease, String>> {
|
||||
since_v0_6_0::zed::extension::github::Host::latest_github_release(self, repo, options).await
|
||||
}
|
||||
|
||||
async fn current_platform(&mut self) -> Result<(Os, Architecture)> {
|
||||
latest::zed::extension::platform::Host::current_platform(self).await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
let status = match status {
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => BinaryStatus::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Downloading => BinaryStatus::Downloading,
|
||||
LanguageServerInstallationStatus::Cached
|
||||
| LanguageServerInstallationStatus::Downloaded => BinaryStatus::None,
|
||||
LanguageServerInstallationStatus::Failed(error) => BinaryStatus::Failed { error },
|
||||
};
|
||||
|
||||
self.host
|
||||
.proxy
|
||||
.update_language_server_status(lsp::LanguageServerName(server_name.into()), status);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
}
|
||||
172
crates/extension_host/src/wasm_host/wit/since_v0_0_4.rs
Normal file
172
crates/extension_host/src/wasm_host/wit/since_v0_0_4.rs
Normal file
@@ -0,0 +1,172 @@
|
||||
use super::{latest, since_v0_6_0};
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::WorktreeDelegate;
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 0, 4);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.0.4",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
},
|
||||
});
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => latest::DownloadedFileType::Gzip,
|
||||
DownloadedFileType::GzipTar => latest::DownloadedFileType::GzipTar,
|
||||
DownloadedFileType::Zip => latest::DownloadedFileType::Zip,
|
||||
DownloadedFileType::Uncompressed => latest::DownloadedFileType::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => {
|
||||
latest::LanguageServerInstallationStatus::None
|
||||
}
|
||||
LanguageServerInstallationStatus::Downloading => {
|
||||
latest::LanguageServerInstallationStatus::Downloading
|
||||
}
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => {
|
||||
latest::LanguageServerInstallationStatus::CheckingForUpdate
|
||||
}
|
||||
LanguageServerInstallationStatus::Failed(error) => {
|
||||
latest::LanguageServerInstallationStatus::Failed(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Command> for latest::Command {
|
||||
fn from(value: Command) -> Self {
|
||||
Self {
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::nodejs::Host::node_binary_path(self).await
|
||||
}
|
||||
|
||||
async fn npm_package_latest_version(
|
||||
&mut self,
|
||||
package_name: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::nodejs::Host::npm_package_latest_version(self, package_name).await
|
||||
}
|
||||
|
||||
async fn npm_package_installed_version(
|
||||
&mut self,
|
||||
package_name: String,
|
||||
) -> wasmtime::Result<Result<Option<String>, String>> {
|
||||
latest::nodejs::Host::npm_package_installed_version(self, package_name).await
|
||||
}
|
||||
|
||||
async fn npm_install_package(
|
||||
&mut self,
|
||||
package_name: String,
|
||||
version: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::nodejs::Host::npm_install_package(self, package_name, version).await
|
||||
}
|
||||
|
||||
async fn latest_github_release(
|
||||
&mut self,
|
||||
repo: String,
|
||||
options: GithubReleaseOptions,
|
||||
) -> wasmtime::Result<Result<GithubRelease, String>> {
|
||||
since_v0_6_0::zed::extension::github::Host::latest_github_release(self, repo, options).await
|
||||
}
|
||||
|
||||
async fn current_platform(&mut self) -> Result<(Os, Architecture)> {
|
||||
latest::zed::extension::platform::Host::current_platform(self).await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
205
crates/extension_host/src/wasm_host/wit/since_v0_0_6.rs
Normal file
205
crates/extension_host/src/wasm_host/wit/since_v0_0_6.rs
Normal file
@@ -0,0 +1,205 @@
|
||||
use super::{latest, since_v0_1_0, since_v0_6_0};
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::WorktreeDelegate;
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 0, 6);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.0.6",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/lsp": since_v0_1_0::zed::extension::lsp,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
},
|
||||
});
|
||||
|
||||
mod settings {
|
||||
#![allow(dead_code)]
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.0.6/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<Command> for latest::Command {
|
||||
fn from(value: Command) -> Self {
|
||||
Self {
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Range> for latest::Range {
|
||||
fn from(value: Range) -> Self {
|
||||
Self {
|
||||
start: value.start,
|
||||
end: value.end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range.into()),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::ExtensionImports::get_settings(
|
||||
self,
|
||||
location.map(|location| location.into()),
|
||||
category,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
588
crates/extension_host/src/wasm_host/wit/since_v0_1_0.rs
Normal file
588
crates/extension_host/src/wasm_host/wit/since_v0_1_0.rs
Normal file
@@ -0,0 +1,588 @@
|
||||
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
|
||||
use ::http_client::{AsyncBody, HttpRequestExt};
|
||||
use ::settings::{Settings, WorktreeId};
|
||||
use anyhow::{Context as _, Result, bail};
|
||||
use async_compression::futures::bufread::GzipDecoder;
|
||||
use async_tar::Archive;
|
||||
use extension::{ExtensionLanguageServerProxy, KeyValueStoreDelegate, WorktreeDelegate};
|
||||
use futures::{AsyncReadExt, lock::Mutex};
|
||||
use futures::{FutureExt as _, io::BufReader};
|
||||
use gpui::BackgroundExecutor;
|
||||
use language::LanguageName;
|
||||
use language::{BinaryStatus, language_settings::AllLanguageSettings};
|
||||
use project::project_settings::ProjectSettings;
|
||||
use semver::Version;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
use util::paths::PathStyle;
|
||||
use util::rel_path::RelPath;
|
||||
use util::{archive::extract_zip, fs::make_file_executable, maybe};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
use super::{latest, since_v0_6_0};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 1, 0);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.1.0",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"key-value-store": ExtensionKeyValueStore,
|
||||
"zed:extension/http-client/http-response-stream": ExtensionHttpResponseStream,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
"zed:extension/slash-command": latest::zed::extension::slash_command,
|
||||
},
|
||||
});
|
||||
|
||||
pub use self::zed::extension::*;
|
||||
|
||||
mod settings {
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.1.0/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
|
||||
pub type ExtensionHttpResponseStream = Arc<Mutex<::http_client::Response<AsyncBody>>>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<Command> for latest::Command {
|
||||
fn from(value: Command) -> Self {
|
||||
Self {
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Range> for latest::Range {
|
||||
fn from(value: Range) -> Self {
|
||||
Self {
|
||||
start: value.start,
|
||||
end: value.end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range.into()),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::Completion> for Completion {
|
||||
fn from(value: latest::Completion) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
detail: value.detail,
|
||||
kind: value.kind.map(Into::into),
|
||||
insert_text_format: value.insert_text_format.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::CompletionKind> for lsp::CompletionKind {
|
||||
fn from(value: latest::lsp::CompletionKind) -> Self {
|
||||
match value {
|
||||
latest::lsp::CompletionKind::Text => Self::Text,
|
||||
latest::lsp::CompletionKind::Method => Self::Method,
|
||||
latest::lsp::CompletionKind::Function => Self::Function,
|
||||
latest::lsp::CompletionKind::Constructor => Self::Constructor,
|
||||
latest::lsp::CompletionKind::Field => Self::Field,
|
||||
latest::lsp::CompletionKind::Variable => Self::Variable,
|
||||
latest::lsp::CompletionKind::Class => Self::Class,
|
||||
latest::lsp::CompletionKind::Interface => Self::Interface,
|
||||
latest::lsp::CompletionKind::Module => Self::Module,
|
||||
latest::lsp::CompletionKind::Property => Self::Property,
|
||||
latest::lsp::CompletionKind::Unit => Self::Unit,
|
||||
latest::lsp::CompletionKind::Value => Self::Value,
|
||||
latest::lsp::CompletionKind::Enum => Self::Enum,
|
||||
latest::lsp::CompletionKind::Keyword => Self::Keyword,
|
||||
latest::lsp::CompletionKind::Snippet => Self::Snippet,
|
||||
latest::lsp::CompletionKind::Color => Self::Color,
|
||||
latest::lsp::CompletionKind::File => Self::File,
|
||||
latest::lsp::CompletionKind::Reference => Self::Reference,
|
||||
latest::lsp::CompletionKind::Folder => Self::Folder,
|
||||
latest::lsp::CompletionKind::EnumMember => Self::EnumMember,
|
||||
latest::lsp::CompletionKind::Constant => Self::Constant,
|
||||
latest::lsp::CompletionKind::Struct => Self::Struct,
|
||||
latest::lsp::CompletionKind::Event => Self::Event,
|
||||
latest::lsp::CompletionKind::Operator => Self::Operator,
|
||||
latest::lsp::CompletionKind::TypeParameter => Self::TypeParameter,
|
||||
latest::lsp::CompletionKind::Other(kind) => Self::Other(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::InsertTextFormat> for lsp::InsertTextFormat {
|
||||
fn from(value: latest::lsp::InsertTextFormat) -> Self {
|
||||
match value {
|
||||
latest::lsp::InsertTextFormat::PlainText => Self::PlainText,
|
||||
latest::lsp::InsertTextFormat::Snippet => Self::Snippet,
|
||||
latest::lsp::InsertTextFormat::Other(value) => Self::Other(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::Symbol> for lsp::Symbol {
|
||||
fn from(value: latest::lsp::Symbol) -> Self {
|
||||
Self {
|
||||
name: value.name,
|
||||
kind: value.kind.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::SymbolKind> for lsp::SymbolKind {
|
||||
fn from(value: latest::lsp::SymbolKind) -> Self {
|
||||
match value {
|
||||
latest::lsp::SymbolKind::File => Self::File,
|
||||
latest::lsp::SymbolKind::Module => Self::Module,
|
||||
latest::lsp::SymbolKind::Namespace => Self::Namespace,
|
||||
latest::lsp::SymbolKind::Package => Self::Package,
|
||||
latest::lsp::SymbolKind::Class => Self::Class,
|
||||
latest::lsp::SymbolKind::Method => Self::Method,
|
||||
latest::lsp::SymbolKind::Property => Self::Property,
|
||||
latest::lsp::SymbolKind::Field => Self::Field,
|
||||
latest::lsp::SymbolKind::Constructor => Self::Constructor,
|
||||
latest::lsp::SymbolKind::Enum => Self::Enum,
|
||||
latest::lsp::SymbolKind::Interface => Self::Interface,
|
||||
latest::lsp::SymbolKind::Function => Self::Function,
|
||||
latest::lsp::SymbolKind::Variable => Self::Variable,
|
||||
latest::lsp::SymbolKind::Constant => Self::Constant,
|
||||
latest::lsp::SymbolKind::String => Self::String,
|
||||
latest::lsp::SymbolKind::Number => Self::Number,
|
||||
latest::lsp::SymbolKind::Boolean => Self::Boolean,
|
||||
latest::lsp::SymbolKind::Array => Self::Array,
|
||||
latest::lsp::SymbolKind::Object => Self::Object,
|
||||
latest::lsp::SymbolKind::Key => Self::Key,
|
||||
latest::lsp::SymbolKind::Null => Self::Null,
|
||||
latest::lsp::SymbolKind::EnumMember => Self::EnumMember,
|
||||
latest::lsp::SymbolKind::Struct => Self::Struct,
|
||||
latest::lsp::SymbolKind::Event => Self::Event,
|
||||
latest::lsp::SymbolKind::Operator => Self::Operator,
|
||||
latest::lsp::SymbolKind::TypeParameter => Self::TypeParameter,
|
||||
latest::lsp::SymbolKind::Other(kind) => Self::Other(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostKeyValueStore for WasmState {
|
||||
async fn insert(
|
||||
&mut self,
|
||||
kv_store: Resource<ExtensionKeyValueStore>,
|
||||
key: String,
|
||||
value: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
let kv_store = self.table.get(&kv_store)?;
|
||||
kv_store.insert(key, value).await.to_wasmtime_result()
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
|
||||
// We only ever hand out borrows of key-value stores.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl common::Host for WasmState {}
|
||||
|
||||
impl http_client::Host for WasmState {
|
||||
async fn fetch(
|
||||
&mut self,
|
||||
request: http_client::HttpRequest,
|
||||
) -> wasmtime::Result<Result<http_client::HttpResponse, String>> {
|
||||
maybe!(async {
|
||||
let url = &request.url;
|
||||
let request = convert_request(&request)?;
|
||||
let mut response = self.host.http_client.send(request).await?;
|
||||
|
||||
if response.status().is_client_error() || response.status().is_server_error() {
|
||||
bail!("failed to fetch '{url}': status code {}", response.status())
|
||||
}
|
||||
convert_response(&mut response).await
|
||||
})
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
|
||||
async fn fetch_stream(
|
||||
&mut self,
|
||||
request: http_client::HttpRequest,
|
||||
) -> wasmtime::Result<Result<Resource<ExtensionHttpResponseStream>, String>> {
|
||||
let request = convert_request(&request)?;
|
||||
let response = self.host.http_client.send(request);
|
||||
maybe!(async {
|
||||
let response = response.await?;
|
||||
let stream = Arc::new(Mutex::new(response));
|
||||
let resource = self.table.push(stream)?;
|
||||
Ok(resource)
|
||||
})
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
}
|
||||
|
||||
impl http_client::HostHttpResponseStream for WasmState {
|
||||
async fn next_chunk(
|
||||
&mut self,
|
||||
resource: Resource<ExtensionHttpResponseStream>,
|
||||
) -> wasmtime::Result<Result<Option<Vec<u8>>, String>> {
|
||||
let stream = self.table.get(&resource)?.clone();
|
||||
maybe!(async move {
|
||||
let mut response = stream.lock().await;
|
||||
let mut buffer = vec![0; 8192]; // 8KB buffer
|
||||
let bytes_read = response.body_mut().read(&mut buffer).await?;
|
||||
if bytes_read == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
buffer.truncate(bytes_read);
|
||||
Ok(Some(buffer))
|
||||
}
|
||||
})
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _resource: Resource<ExtensionHttpResponseStream>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<http_client::HttpMethod> for ::http_client::Method {
|
||||
fn from(value: http_client::HttpMethod) -> Self {
|
||||
match value {
|
||||
http_client::HttpMethod::Get => Self::GET,
|
||||
http_client::HttpMethod::Post => Self::POST,
|
||||
http_client::HttpMethod::Put => Self::PUT,
|
||||
http_client::HttpMethod::Delete => Self::DELETE,
|
||||
http_client::HttpMethod::Head => Self::HEAD,
|
||||
http_client::HttpMethod::Options => Self::OPTIONS,
|
||||
http_client::HttpMethod::Patch => Self::PATCH,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_request(
|
||||
extension_request: &http_client::HttpRequest,
|
||||
) -> anyhow::Result<::http_client::Request<AsyncBody>> {
|
||||
let mut request = ::http_client::Request::builder()
|
||||
.method(::http_client::Method::from(extension_request.method))
|
||||
.uri(&extension_request.url)
|
||||
.follow_redirects(match extension_request.redirect_policy {
|
||||
http_client::RedirectPolicy::NoFollow => ::http_client::RedirectPolicy::NoFollow,
|
||||
http_client::RedirectPolicy::FollowLimit(limit) => {
|
||||
::http_client::RedirectPolicy::FollowLimit(limit)
|
||||
}
|
||||
http_client::RedirectPolicy::FollowAll => ::http_client::RedirectPolicy::FollowAll,
|
||||
});
|
||||
for (key, value) in &extension_request.headers {
|
||||
request = request.header(key, value);
|
||||
}
|
||||
let body = extension_request
|
||||
.body
|
||||
.clone()
|
||||
.map(AsyncBody::from)
|
||||
.unwrap_or_default();
|
||||
request.body(body).map_err(anyhow::Error::from)
|
||||
}
|
||||
|
||||
async fn convert_response(
|
||||
response: &mut ::http_client::Response<AsyncBody>,
|
||||
) -> anyhow::Result<http_client::HttpResponse> {
|
||||
let mut extension_response = http_client::HttpResponse {
|
||||
body: Vec::new(),
|
||||
headers: Vec::new(),
|
||||
};
|
||||
|
||||
for (key, value) in response.headers() {
|
||||
extension_response
|
||||
.headers
|
||||
.push((key.to_string(), value.to_str().unwrap_or("").to_string()));
|
||||
}
|
||||
|
||||
response
|
||||
.body_mut()
|
||||
.read_to_end(&mut extension_response.body)
|
||||
.await?;
|
||||
|
||||
Ok(extension_response)
|
||||
}
|
||||
|
||||
impl lsp::Host for WasmState {}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
self.on_main_thread(|cx| {
|
||||
async move {
|
||||
let path = location.as_ref().and_then(|location| {
|
||||
RelPath::new(Path::new(&location.path), PathStyle::Posix).ok()
|
||||
});
|
||||
let location = path
|
||||
.as_ref()
|
||||
.zip(location.as_ref())
|
||||
.map(|(path, location)| ::settings::SettingsLocation {
|
||||
worktree_id: WorktreeId::from_proto(location.worktree_id),
|
||||
path,
|
||||
});
|
||||
|
||||
cx.update(|cx| match category.as_str() {
|
||||
"language" => {
|
||||
let key = key.map(|k| LanguageName::new(&k));
|
||||
let settings = AllLanguageSettings::get(location, cx).language(
|
||||
location,
|
||||
key.as_ref(),
|
||||
cx,
|
||||
);
|
||||
Ok(serde_json::to_string(&settings::LanguageSettings {
|
||||
tab_size: settings.tab_size,
|
||||
})?)
|
||||
}
|
||||
"lsp" => {
|
||||
let settings = key
|
||||
.and_then(|key| {
|
||||
ProjectSettings::get(location, cx)
|
||||
.lsp
|
||||
.get(&::lsp::LanguageServerName(key.into()))
|
||||
})
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
Ok(serde_json::to_string(&settings::LspSettings {
|
||||
binary: settings.binary.map(|binary| settings::BinarySettings {
|
||||
path: binary.path,
|
||||
arguments: binary.arguments,
|
||||
}),
|
||||
settings: settings.settings,
|
||||
initialization_options: settings.initialization_options,
|
||||
})?)
|
||||
}
|
||||
_ => {
|
||||
bail!("Unknown settings category: {}", category);
|
||||
}
|
||||
})
|
||||
}
|
||||
.boxed_local()
|
||||
})
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
let status = match status {
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => BinaryStatus::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Downloading => BinaryStatus::Downloading,
|
||||
LanguageServerInstallationStatus::None => BinaryStatus::None,
|
||||
LanguageServerInstallationStatus::Failed(error) => BinaryStatus::Failed { error },
|
||||
};
|
||||
|
||||
self.host
|
||||
.proxy
|
||||
.update_language_server_status(::lsp::LanguageServerName(server_name.into()), status);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
maybe!(async {
|
||||
let path = PathBuf::from(path);
|
||||
let extension_work_dir = self.host.work_dir.join(self.manifest.id.as_ref());
|
||||
|
||||
self.host.fs.create_dir(&extension_work_dir).await?;
|
||||
|
||||
let destination_path = self
|
||||
.host
|
||||
.writeable_path_from_extension(&self.manifest.id, &path)
|
||||
.await?;
|
||||
|
||||
let mut response = self
|
||||
.host
|
||||
.http_client
|
||||
.get(&url, Default::default(), true)
|
||||
.await
|
||||
.context("downloading release")?;
|
||||
|
||||
anyhow::ensure!(
|
||||
response.status().is_success(),
|
||||
"download failed with status {}",
|
||||
response.status()
|
||||
);
|
||||
let mut body = BufReader::new(response.body_mut());
|
||||
|
||||
match file_type {
|
||||
DownloadedFileType::Uncompressed => {
|
||||
futures::pin_mut!(body);
|
||||
self.host
|
||||
.fs
|
||||
.create_file_with(&destination_path, body)
|
||||
.await?;
|
||||
}
|
||||
DownloadedFileType::Gzip => {
|
||||
let body = GzipDecoder::new(body);
|
||||
futures::pin_mut!(body);
|
||||
self.host
|
||||
.fs
|
||||
.create_file_with(&destination_path, body)
|
||||
.await?;
|
||||
}
|
||||
DownloadedFileType::GzipTar => {
|
||||
let mut tar_gz_bytes = Vec::new();
|
||||
body.read_to_end(&mut tar_gz_bytes).await?;
|
||||
let decompressed_bytes =
|
||||
GzipDecoder::new(BufReader::new(tar_gz_bytes.as_slice()));
|
||||
futures::pin_mut!(decompressed_bytes);
|
||||
self.host
|
||||
.fs
|
||||
.extract_tar_file(&destination_path, Archive::new(decompressed_bytes))
|
||||
.await?;
|
||||
}
|
||||
DownloadedFileType::Zip => {
|
||||
futures::pin_mut!(body);
|
||||
extract_zip(&destination_path, body)
|
||||
.await
|
||||
.with_context(|| format!("unzipping {path:?} archive"))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
let path = self
|
||||
.host
|
||||
.writeable_path_from_extension(&self.manifest.id, Path::new(&path))
|
||||
.await?;
|
||||
|
||||
make_file_executable(&path)
|
||||
.await
|
||||
.with_context(|| format!("setting permissions for path {path:?}"))
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
}
|
||||
246
crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs
Normal file
246
crates/extension_host/src/wasm_host/wit/since_v0_2_0.rs
Normal file
@@ -0,0 +1,246 @@
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::{KeyValueStoreDelegate, ProjectDelegate, WorktreeDelegate};
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
use super::{latest, since_v0_6_0};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 2, 0);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.2.0",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"project": ExtensionProject,
|
||||
"key-value-store": ExtensionKeyValueStore,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/http-client": latest::zed::extension::http_client,
|
||||
"zed:extension/lsp": since_v0_6_0::zed::extension::lsp,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
"zed:extension/slash-command": latest::zed::extension::slash_command,
|
||||
},
|
||||
});
|
||||
|
||||
pub use self::zed::extension::*;
|
||||
|
||||
mod settings {
|
||||
#![allow(dead_code)]
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.2.0/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
pub type ExtensionProject = Arc<dyn ProjectDelegate>;
|
||||
pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<Command> for latest::Command {
|
||||
fn from(value: Command) -> Self {
|
||||
Self {
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Range> for latest::Range {
|
||||
fn from(value: Range) -> Self {
|
||||
Self {
|
||||
start: value.start,
|
||||
end: value.end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range.into()),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostKeyValueStore for WasmState {
|
||||
async fn insert(
|
||||
&mut self,
|
||||
kv_store: Resource<ExtensionKeyValueStore>,
|
||||
key: String,
|
||||
value: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::HostKeyValueStore::insert(self, kv_store, key, value).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
|
||||
// We only ever hand out borrows of key-value stores.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostProject for WasmState {
|
||||
async fn worktree_ids(
|
||||
&mut self,
|
||||
project: Resource<ExtensionProject>,
|
||||
) -> wasmtime::Result<Vec<u64>> {
|
||||
latest::HostProject::worktree_ids(self, project).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
|
||||
// We only ever hand out borrows of projects.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl common::Host for WasmState {}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::ExtensionImports::get_settings(
|
||||
self,
|
||||
location.map(|location| location.into()),
|
||||
category,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
225
crates/extension_host/src/wasm_host/wit/since_v0_3_0.rs
Normal file
225
crates/extension_host/src/wasm_host/wit/since_v0_3_0.rs
Normal file
@@ -0,0 +1,225 @@
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::{KeyValueStoreDelegate, ProjectDelegate, WorktreeDelegate};
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
use super::{latest, since_v0_6_0};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 3, 0);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.3.0",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"project": ExtensionProject,
|
||||
"key-value-store": ExtensionKeyValueStore,
|
||||
"zed:extension/common": latest::zed::extension::common,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/http-client": latest::zed::extension::http_client,
|
||||
"zed:extension/lsp": since_v0_6_0::zed::extension::lsp,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
"zed:extension/process": latest::zed::extension::process,
|
||||
"zed:extension/slash-command": latest::zed::extension::slash_command,
|
||||
},
|
||||
});
|
||||
|
||||
mod settings {
|
||||
#![allow(dead_code)]
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.3.0/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
pub type ExtensionProject = Arc<dyn ProjectDelegate>;
|
||||
pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostKeyValueStore for WasmState {
|
||||
async fn insert(
|
||||
&mut self,
|
||||
kv_store: Resource<ExtensionKeyValueStore>,
|
||||
key: String,
|
||||
value: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::HostKeyValueStore::insert(self, kv_store, key, value).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
|
||||
// We only ever hand out borrows of key-value stores.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostProject for WasmState {
|
||||
async fn worktree_ids(
|
||||
&mut self,
|
||||
project: Resource<ExtensionProject>,
|
||||
) -> wasmtime::Result<Vec<u64>> {
|
||||
latest::HostProject::worktree_ids(self, project).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
|
||||
// We only ever hand out borrows of projects.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::ExtensionImports::get_settings(
|
||||
self,
|
||||
location.map(|location| location.into()),
|
||||
category,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
225
crates/extension_host/src/wasm_host/wit/since_v0_4_0.rs
Normal file
225
crates/extension_host/src/wasm_host/wit/since_v0_4_0.rs
Normal file
@@ -0,0 +1,225 @@
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::{KeyValueStoreDelegate, ProjectDelegate, WorktreeDelegate};
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
use super::{latest, since_v0_6_0};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 4, 0);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.4.0",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"project": ExtensionProject,
|
||||
"key-value-store": ExtensionKeyValueStore,
|
||||
"zed:extension/common": latest::zed::extension::common,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/http-client": latest::zed::extension::http_client,
|
||||
"zed:extension/lsp": since_v0_6_0::zed::extension::lsp,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
"zed:extension/process": latest::zed::extension::process,
|
||||
"zed:extension/slash-command": latest::zed::extension::slash_command,
|
||||
},
|
||||
});
|
||||
|
||||
mod settings {
|
||||
#![allow(dead_code)]
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.4.0/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
pub type ExtensionProject = Arc<dyn ProjectDelegate>;
|
||||
pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostKeyValueStore for WasmState {
|
||||
async fn insert(
|
||||
&mut self,
|
||||
kv_store: Resource<ExtensionKeyValueStore>,
|
||||
key: String,
|
||||
value: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::HostKeyValueStore::insert(self, kv_store, key, value).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
|
||||
// We only ever hand out borrows of key-value stores.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostProject for WasmState {
|
||||
async fn worktree_ids(
|
||||
&mut self,
|
||||
project: Resource<ExtensionProject>,
|
||||
) -> wasmtime::Result<Vec<u64>> {
|
||||
latest::HostProject::worktree_ids(self, project).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
|
||||
// We only ever hand out borrows of projects.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::ExtensionImports::get_settings(
|
||||
self,
|
||||
location.map(|location| location.into()),
|
||||
category,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
226
crates/extension_host/src/wasm_host/wit/since_v0_5_0.rs
Normal file
226
crates/extension_host/src/wasm_host/wit/since_v0_5_0.rs
Normal file
@@ -0,0 +1,226 @@
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::{KeyValueStoreDelegate, ProjectDelegate, WorktreeDelegate};
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
use super::{latest, since_v0_6_0};
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 5, 0);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.5.0",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"project": ExtensionProject,
|
||||
"key-value-store": ExtensionKeyValueStore,
|
||||
"zed:extension/common": latest::zed::extension::common,
|
||||
"zed:extension/github": since_v0_6_0::zed::extension::github,
|
||||
"zed:extension/http-client": latest::zed::extension::http_client,
|
||||
"zed:extension/lsp": since_v0_6_0::zed::extension::lsp,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
"zed:extension/process": latest::zed::extension::process,
|
||||
"zed:extension/slash-command": latest::zed::extension::slash_command,
|
||||
"zed:extension/context-server": latest::zed::extension::context_server,
|
||||
},
|
||||
});
|
||||
|
||||
mod settings {
|
||||
#![allow(dead_code)]
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.5.0/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
pub type ExtensionProject = Arc<dyn ProjectDelegate>;
|
||||
pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HostKeyValueStore for WasmState {
|
||||
async fn insert(
|
||||
&mut self,
|
||||
kv_store: Resource<ExtensionKeyValueStore>,
|
||||
key: String,
|
||||
value: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::HostKeyValueStore::insert(self, kv_store, key, value).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
|
||||
// We only ever hand out borrows of key-value stores.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostProject for WasmState {
|
||||
async fn worktree_ids(
|
||||
&mut self,
|
||||
project: Resource<ExtensionProject>,
|
||||
) -> wasmtime::Result<Vec<u64>> {
|
||||
latest::HostProject::worktree_ids(self, project).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
|
||||
// We only ever hand out borrows of projects.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::ExtensionImports::get_settings(
|
||||
self,
|
||||
location.map(|location| location.into()),
|
||||
category,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
710
crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs
Normal file
710
crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs
Normal file
@@ -0,0 +1,710 @@
|
||||
use crate::wasm_host::WasmState;
|
||||
use anyhow::Result;
|
||||
use extension::{KeyValueStoreDelegate, ProjectDelegate, WorktreeDelegate};
|
||||
use gpui::BackgroundExecutor;
|
||||
use semver::Version;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
use super::latest;
|
||||
|
||||
pub const MIN_VERSION: Version = Version::new(0, 6, 0);
|
||||
pub const MAX_VERSION: Version = Version::new(0, 7, 0);
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
imports: {
|
||||
default: async | trappable,
|
||||
},
|
||||
exports: {
|
||||
default: async,
|
||||
},
|
||||
path: "../extension_api/wit/since_v0.6.0",
|
||||
with: {
|
||||
"worktree": ExtensionWorktree,
|
||||
"project": ExtensionProject,
|
||||
"key-value-store": ExtensionKeyValueStore,
|
||||
"zed:extension/common": latest::zed::extension::common,
|
||||
"zed:extension/http-client": latest::zed::extension::http_client,
|
||||
"zed:extension/nodejs": latest::zed::extension::nodejs,
|
||||
"zed:extension/platform": latest::zed::extension::platform,
|
||||
"zed:extension/process": latest::zed::extension::process,
|
||||
"zed:extension/slash-command": latest::zed::extension::slash_command,
|
||||
"zed:extension/context-server": latest::zed::extension::context_server,
|
||||
},
|
||||
});
|
||||
|
||||
pub use self::zed::extension::*;
|
||||
|
||||
mod settings {
|
||||
#![allow(dead_code)]
|
||||
include!(concat!(env!("OUT_DIR"), "/since_v0.6.0/settings.rs"));
|
||||
}
|
||||
|
||||
pub type ExtensionWorktree = Arc<dyn WorktreeDelegate>;
|
||||
pub type ExtensionProject = Arc<dyn ProjectDelegate>;
|
||||
pub type ExtensionKeyValueStore = Arc<dyn KeyValueStoreDelegate>;
|
||||
|
||||
pub fn linker(executor: &BackgroundExecutor) -> &'static Linker<WasmState> {
|
||||
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
|
||||
LINKER.get_or_init(|| {
|
||||
super::new_linker(executor, |linker| {
|
||||
Extension::add_to_linker::<_, WasmState>(linker, |s| s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
impl From<CodeLabel> for latest::CodeLabel {
|
||||
fn from(value: CodeLabel) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
spans: value.spans.into_iter().map(Into::into).collect(),
|
||||
filter_range: value.filter_range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpan> for latest::CodeLabelSpan {
|
||||
fn from(value: CodeLabelSpan) -> Self {
|
||||
match value {
|
||||
CodeLabelSpan::CodeRange(range) => Self::CodeRange(range),
|
||||
CodeLabelSpan::Literal(literal) => Self::Literal(literal.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodeLabelSpanLiteral> for latest::CodeLabelSpanLiteral {
|
||||
fn from(value: CodeLabelSpanLiteral) -> Self {
|
||||
Self {
|
||||
text: value.text,
|
||||
highlight_name: value.highlight_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SettingsLocation> for latest::SettingsLocation {
|
||||
fn from(value: SettingsLocation) -> Self {
|
||||
Self {
|
||||
worktree_id: value.worktree_id,
|
||||
path: value.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LanguageServerInstallationStatus> for latest::LanguageServerInstallationStatus {
|
||||
fn from(value: LanguageServerInstallationStatus) -> Self {
|
||||
match value {
|
||||
LanguageServerInstallationStatus::None => Self::None,
|
||||
LanguageServerInstallationStatus::Downloading => Self::Downloading,
|
||||
LanguageServerInstallationStatus::CheckingForUpdate => Self::CheckingForUpdate,
|
||||
LanguageServerInstallationStatus::Failed(message) => Self::Failed(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadedFileType> for latest::DownloadedFileType {
|
||||
fn from(value: DownloadedFileType) -> Self {
|
||||
match value {
|
||||
DownloadedFileType::Gzip => Self::Gzip,
|
||||
DownloadedFileType::GzipTar => Self::GzipTar,
|
||||
DownloadedFileType::Zip => Self::Zip,
|
||||
DownloadedFileType::Uncompressed => Self::Uncompressed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::github::GithubReleaseAsset> for github::GithubReleaseAsset {
|
||||
fn from(value: latest::github::GithubReleaseAsset) -> Self {
|
||||
Self {
|
||||
name: value.name,
|
||||
download_url: value.download_url,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::github::GithubRelease> for github::GithubRelease {
|
||||
fn from(value: latest::github::GithubRelease) -> Self {
|
||||
Self {
|
||||
version: value.version,
|
||||
assets: value.assets.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<github::GithubReleaseOptions> for latest::github::GithubReleaseOptions {
|
||||
fn from(value: github::GithubReleaseOptions) -> Self {
|
||||
Self {
|
||||
require_assets: value.require_assets,
|
||||
pre_release: value.pre_release,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl zed::extension::github::Host for WasmState {
|
||||
async fn github_release_by_tag_name(
|
||||
&mut self,
|
||||
repo: String,
|
||||
tag: String,
|
||||
) -> wasmtime::Result<Result<github::GithubRelease, String>> {
|
||||
latest::github::Host::github_release_by_tag_name(self, repo, tag)
|
||||
.await
|
||||
.map(|result| result.map(Into::into))
|
||||
}
|
||||
|
||||
async fn latest_github_release(
|
||||
&mut self,
|
||||
repo: String,
|
||||
options: github::GithubReleaseOptions,
|
||||
) -> wasmtime::Result<Result<github::GithubRelease, String>> {
|
||||
latest::github::Host::latest_github_release(self, repo, options.into())
|
||||
.await
|
||||
.map(|result| result.map(Into::into))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::Completion> for lsp::Completion {
|
||||
fn from(value: latest::lsp::Completion) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
label_details: value.label_details.map(Into::into),
|
||||
detail: value.detail,
|
||||
kind: value.kind.map(Into::into),
|
||||
insert_text_format: value.insert_text_format.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::Symbol> for lsp::Symbol {
|
||||
fn from(value: latest::lsp::Symbol) -> Self {
|
||||
Self {
|
||||
name: value.name,
|
||||
kind: value.kind.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::CompletionLabelDetails> for lsp::CompletionLabelDetails {
|
||||
fn from(value: latest::lsp::CompletionLabelDetails) -> Self {
|
||||
Self {
|
||||
detail: value.detail,
|
||||
description: value.description,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::CompletionKind> for lsp::CompletionKind {
|
||||
fn from(value: latest::lsp::CompletionKind) -> Self {
|
||||
match value {
|
||||
latest::lsp::CompletionKind::Text => Self::Text,
|
||||
latest::lsp::CompletionKind::Method => Self::Method,
|
||||
latest::lsp::CompletionKind::Function => Self::Function,
|
||||
latest::lsp::CompletionKind::Constructor => Self::Constructor,
|
||||
latest::lsp::CompletionKind::Field => Self::Field,
|
||||
latest::lsp::CompletionKind::Variable => Self::Variable,
|
||||
latest::lsp::CompletionKind::Class => Self::Class,
|
||||
latest::lsp::CompletionKind::Interface => Self::Interface,
|
||||
latest::lsp::CompletionKind::Module => Self::Module,
|
||||
latest::lsp::CompletionKind::Property => Self::Property,
|
||||
latest::lsp::CompletionKind::Unit => Self::Unit,
|
||||
latest::lsp::CompletionKind::Value => Self::Value,
|
||||
latest::lsp::CompletionKind::Enum => Self::Enum,
|
||||
latest::lsp::CompletionKind::Keyword => Self::Keyword,
|
||||
latest::lsp::CompletionKind::Snippet => Self::Snippet,
|
||||
latest::lsp::CompletionKind::Color => Self::Color,
|
||||
latest::lsp::CompletionKind::File => Self::File,
|
||||
latest::lsp::CompletionKind::Reference => Self::Reference,
|
||||
latest::lsp::CompletionKind::Folder => Self::Folder,
|
||||
latest::lsp::CompletionKind::EnumMember => Self::EnumMember,
|
||||
latest::lsp::CompletionKind::Constant => Self::Constant,
|
||||
latest::lsp::CompletionKind::Struct => Self::Struct,
|
||||
latest::lsp::CompletionKind::Event => Self::Event,
|
||||
latest::lsp::CompletionKind::Operator => Self::Operator,
|
||||
latest::lsp::CompletionKind::TypeParameter => Self::TypeParameter,
|
||||
latest::lsp::CompletionKind::Other(kind) => Self::Other(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::InsertTextFormat> for lsp::InsertTextFormat {
|
||||
fn from(value: latest::lsp::InsertTextFormat) -> Self {
|
||||
match value {
|
||||
latest::lsp::InsertTextFormat::PlainText => Self::PlainText,
|
||||
latest::lsp::InsertTextFormat::Snippet => Self::Snippet,
|
||||
latest::lsp::InsertTextFormat::Other(value) => Self::Other(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::lsp::SymbolKind> for lsp::SymbolKind {
|
||||
fn from(value: latest::lsp::SymbolKind) -> Self {
|
||||
match value {
|
||||
latest::lsp::SymbolKind::File => Self::File,
|
||||
latest::lsp::SymbolKind::Module => Self::Module,
|
||||
latest::lsp::SymbolKind::Namespace => Self::Namespace,
|
||||
latest::lsp::SymbolKind::Package => Self::Package,
|
||||
latest::lsp::SymbolKind::Class => Self::Class,
|
||||
latest::lsp::SymbolKind::Method => Self::Method,
|
||||
latest::lsp::SymbolKind::Property => Self::Property,
|
||||
latest::lsp::SymbolKind::Field => Self::Field,
|
||||
latest::lsp::SymbolKind::Constructor => Self::Constructor,
|
||||
latest::lsp::SymbolKind::Enum => Self::Enum,
|
||||
latest::lsp::SymbolKind::Interface => Self::Interface,
|
||||
latest::lsp::SymbolKind::Function => Self::Function,
|
||||
latest::lsp::SymbolKind::Variable => Self::Variable,
|
||||
latest::lsp::SymbolKind::Constant => Self::Constant,
|
||||
latest::lsp::SymbolKind::String => Self::String,
|
||||
latest::lsp::SymbolKind::Number => Self::Number,
|
||||
latest::lsp::SymbolKind::Boolean => Self::Boolean,
|
||||
latest::lsp::SymbolKind::Array => Self::Array,
|
||||
latest::lsp::SymbolKind::Object => Self::Object,
|
||||
latest::lsp::SymbolKind::Key => Self::Key,
|
||||
latest::lsp::SymbolKind::Null => Self::Null,
|
||||
latest::lsp::SymbolKind::EnumMember => Self::EnumMember,
|
||||
latest::lsp::SymbolKind::Struct => Self::Struct,
|
||||
latest::lsp::SymbolKind::Event => Self::Event,
|
||||
latest::lsp::SymbolKind::Operator => Self::Operator,
|
||||
latest::lsp::SymbolKind::TypeParameter => Self::TypeParameter,
|
||||
latest::lsp::SymbolKind::Other(kind) => Self::Other(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl lsp::Host for WasmState {}
|
||||
|
||||
impl HostKeyValueStore for WasmState {
|
||||
async fn insert(
|
||||
&mut self,
|
||||
kv_store: Resource<ExtensionKeyValueStore>,
|
||||
key: String,
|
||||
value: String,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::HostKeyValueStore::insert(self, kv_store, key, value).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<ExtensionKeyValueStore>) -> Result<()> {
|
||||
// We only ever hand out borrows of key-value stores.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostProject for WasmState {
|
||||
async fn worktree_ids(
|
||||
&mut self,
|
||||
project: Resource<ExtensionProject>,
|
||||
) -> wasmtime::Result<Vec<u64>> {
|
||||
latest::HostProject::worktree_ids(self, project).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
|
||||
// We only ever hand out borrows of projects.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl HostWorktree for WasmState {
|
||||
async fn id(&mut self, delegate: Resource<Arc<dyn WorktreeDelegate>>) -> wasmtime::Result<u64> {
|
||||
latest::HostWorktree::id(self, delegate).await
|
||||
}
|
||||
|
||||
async fn root_path(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<String> {
|
||||
latest::HostWorktree::root_path(self, delegate).await
|
||||
}
|
||||
|
||||
async fn read_text_file(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
path: String,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::HostWorktree::read_text_file(self, delegate, path).await
|
||||
}
|
||||
|
||||
async fn shell_env(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
) -> wasmtime::Result<EnvVars> {
|
||||
latest::HostWorktree::shell_env(self, delegate).await
|
||||
}
|
||||
|
||||
async fn which(
|
||||
&mut self,
|
||||
delegate: Resource<Arc<dyn WorktreeDelegate>>,
|
||||
binary_name: String,
|
||||
) -> wasmtime::Result<Option<String>> {
|
||||
latest::HostWorktree::which(self, delegate, binary_name).await
|
||||
}
|
||||
|
||||
async fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
|
||||
// We only ever hand out borrows of worktrees.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionImports for WasmState {
|
||||
async fn get_settings(
|
||||
&mut self,
|
||||
location: Option<self::SettingsLocation>,
|
||||
category: String,
|
||||
key: Option<String>,
|
||||
) -> wasmtime::Result<Result<String, String>> {
|
||||
latest::ExtensionImports::get_settings(
|
||||
self,
|
||||
location.map(|location| location.into()),
|
||||
category,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn set_language_server_installation_status(
|
||||
&mut self,
|
||||
server_name: String,
|
||||
status: LanguageServerInstallationStatus,
|
||||
) -> wasmtime::Result<()> {
|
||||
latest::ExtensionImports::set_language_server_installation_status(
|
||||
self,
|
||||
server_name,
|
||||
status.into(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn download_file(
|
||||
&mut self,
|
||||
url: String,
|
||||
path: String,
|
||||
file_type: DownloadedFileType,
|
||||
) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
|
||||
}
|
||||
|
||||
async fn make_file_executable(&mut self, path: String) -> wasmtime::Result<Result<(), String>> {
|
||||
latest::ExtensionImports::make_file_executable(self, path).await
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::TcpArguments> for latest::dap::TcpArguments {
|
||||
fn from(value: dap::TcpArguments) -> Self {
|
||||
let [a, b, c, d] = std::net::Ipv4Addr::from_bits(value.host).octets();
|
||||
Self {
|
||||
host: latest::dap::IpAddress::Ipv4((a, b, c, d)),
|
||||
port: value.port,
|
||||
timeout: value.timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<latest::dap::TcpArguments> for dap::TcpArguments {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: latest::dap::TcpArguments) -> Result<Self> {
|
||||
let host = match value.host {
|
||||
latest::dap::IpAddress::Ipv4((a, b, c, d)) => {
|
||||
std::net::Ipv4Addr::new(a, b, c, d).to_bits()
|
||||
}
|
||||
latest::dap::IpAddress::Ipv6((a, b, c, d, e, f, g, h)) => {
|
||||
let addr = std::net::Ipv6Addr::new(a, b, c, d, e, f, g, h);
|
||||
anyhow::bail!(
|
||||
"DAP returned IPv6 host {addr}, which the v0.6.0 extension API cannot represent; the extension must be updated to v0.8.0 or later"
|
||||
);
|
||||
}
|
||||
};
|
||||
Ok(Self {
|
||||
host,
|
||||
port: value.port,
|
||||
timeout: value.timeout,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::TcpArgumentsTemplate> for latest::dap::TcpArgumentsTemplate {
|
||||
fn from(value: dap::TcpArgumentsTemplate) -> Self {
|
||||
Self {
|
||||
host: value.host.map(|host| {
|
||||
let [a, b, c, d] = std::net::Ipv4Addr::from_bits(host).octets();
|
||||
latest::dap::IpAddress::Ipv4((a, b, c, d))
|
||||
}),
|
||||
port: value.port,
|
||||
timeout: value.timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::TcpArgumentsTemplate> for dap::TcpArgumentsTemplate {
|
||||
fn from(value: latest::dap::TcpArgumentsTemplate) -> Self {
|
||||
Self {
|
||||
host: value.host.and_then(|host| match host {
|
||||
latest::dap::IpAddress::Ipv4((a, b, c, d)) => {
|
||||
Some(std::net::Ipv4Addr::new(a, b, c, d).to_bits())
|
||||
}
|
||||
latest::dap::IpAddress::Ipv6((a, b, c, d, e, f, g, h)) => {
|
||||
let addr = std::net::Ipv6Addr::new(a, b, c, d, e, f, g, h);
|
||||
log::warn!(
|
||||
"Dropping IPv6 host {addr} when handing TCP arguments back to a v0.6.0 extension; update the extension to v0.8.0 or later for IPv6 support"
|
||||
);
|
||||
None
|
||||
}
|
||||
}),
|
||||
port: value.port,
|
||||
timeout: value.timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::LaunchRequest> for latest::dap::LaunchRequest {
|
||||
fn from(value: dap::LaunchRequest) -> Self {
|
||||
Self {
|
||||
program: value.program,
|
||||
cwd: value.cwd,
|
||||
args: value.args,
|
||||
envs: value.envs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::LaunchRequest> for dap::LaunchRequest {
|
||||
fn from(value: latest::dap::LaunchRequest) -> Self {
|
||||
Self {
|
||||
program: value.program,
|
||||
cwd: value.cwd,
|
||||
args: value.args,
|
||||
envs: value.envs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::AttachRequest> for latest::dap::AttachRequest {
|
||||
fn from(value: dap::AttachRequest) -> Self {
|
||||
Self {
|
||||
process_id: value.process_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::AttachRequest> for dap::AttachRequest {
|
||||
fn from(value: latest::dap::AttachRequest) -> Self {
|
||||
Self {
|
||||
process_id: value.process_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DebugRequest> for latest::DebugRequest {
|
||||
fn from(value: DebugRequest) -> Self {
|
||||
match value {
|
||||
DebugRequest::Launch(req) => Self::Launch(req.into()),
|
||||
DebugRequest::Attach(req) => Self::Attach(req.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::DebugRequest> for DebugRequest {
|
||||
fn from(value: latest::DebugRequest) -> Self {
|
||||
match value {
|
||||
latest::DebugRequest::Launch(req) => Self::Launch(req.into()),
|
||||
latest::DebugRequest::Attach(req) => Self::Attach(req.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DebugConfig> for latest::DebugConfig {
|
||||
fn from(value: DebugConfig) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
adapter: value.adapter,
|
||||
request: value.request.into(),
|
||||
stop_on_entry: value.stop_on_entry,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::DebugConfig> for DebugConfig {
|
||||
fn from(value: latest::DebugConfig) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
adapter: value.adapter,
|
||||
request: value.request.into(),
|
||||
stop_on_entry: value.stop_on_entry,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::TaskTemplate> for latest::dap::TaskTemplate {
|
||||
fn from(value: dap::TaskTemplate) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
cwd: value.cwd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::TaskTemplate> for dap::TaskTemplate {
|
||||
fn from(value: latest::dap::TaskTemplate) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
command: value.command,
|
||||
args: value.args,
|
||||
env: value.env,
|
||||
cwd: value.cwd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::BuildTaskDefinition> for latest::dap::BuildTaskDefinition {
|
||||
fn from(value: dap::BuildTaskDefinition) -> Self {
|
||||
match value {
|
||||
dap::BuildTaskDefinition::ByName(name) => Self::ByName(name),
|
||||
dap::BuildTaskDefinition::Template(payload) => {
|
||||
Self::Template(latest::dap::BuildTaskDefinitionTemplatePayload {
|
||||
locator_name: payload.locator_name,
|
||||
template: payload.template.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::BuildTaskDefinition> for dap::BuildTaskDefinition {
|
||||
fn from(value: latest::dap::BuildTaskDefinition) -> Self {
|
||||
match value {
|
||||
latest::dap::BuildTaskDefinition::ByName(name) => Self::ByName(name),
|
||||
latest::dap::BuildTaskDefinition::Template(payload) => {
|
||||
Self::Template(dap::BuildTaskDefinitionTemplatePayload {
|
||||
locator_name: payload.locator_name,
|
||||
template: payload.template.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DebugScenario> for latest::DebugScenario {
|
||||
fn from(value: DebugScenario) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
adapter: value.adapter,
|
||||
build: value.build.map(Into::into),
|
||||
config: value.config,
|
||||
tcp_connection: value.tcp_connection.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::DebugScenario> for DebugScenario {
|
||||
fn from(value: latest::DebugScenario) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
adapter: value.adapter,
|
||||
build: value.build.map(Into::into),
|
||||
config: value.config,
|
||||
tcp_connection: value.tcp_connection.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DebugTaskDefinition> for latest::DebugTaskDefinition {
|
||||
fn from(value: DebugTaskDefinition) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
adapter: value.adapter,
|
||||
config: value.config,
|
||||
tcp_connection: value.tcp_connection.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::DebugTaskDefinition> for DebugTaskDefinition {
|
||||
fn from(value: latest::DebugTaskDefinition) -> Self {
|
||||
Self {
|
||||
label: value.label,
|
||||
adapter: value.adapter,
|
||||
config: value.config,
|
||||
tcp_connection: value.tcp_connection.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::StartDebuggingRequestArgumentsRequest>
|
||||
for latest::dap::StartDebuggingRequestArgumentsRequest
|
||||
{
|
||||
fn from(value: dap::StartDebuggingRequestArgumentsRequest) -> Self {
|
||||
match value {
|
||||
dap::StartDebuggingRequestArgumentsRequest::Launch => Self::Launch,
|
||||
dap::StartDebuggingRequestArgumentsRequest::Attach => Self::Attach,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::StartDebuggingRequestArgumentsRequest>
|
||||
for dap::StartDebuggingRequestArgumentsRequest
|
||||
{
|
||||
fn from(value: latest::dap::StartDebuggingRequestArgumentsRequest) -> Self {
|
||||
match value {
|
||||
latest::dap::StartDebuggingRequestArgumentsRequest::Launch => Self::Launch,
|
||||
latest::dap::StartDebuggingRequestArgumentsRequest::Attach => Self::Attach,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<dap::StartDebuggingRequestArguments> for latest::dap::StartDebuggingRequestArguments {
|
||||
fn from(value: dap::StartDebuggingRequestArguments) -> Self {
|
||||
Self {
|
||||
configuration: value.configuration,
|
||||
request: value.request.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<latest::dap::StartDebuggingRequestArguments> for dap::StartDebuggingRequestArguments {
|
||||
fn from(value: latest::dap::StartDebuggingRequestArguments) -> Self {
|
||||
Self {
|
||||
configuration: value.configuration,
|
||||
request: value.request.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DebugAdapterBinary> for latest::DebugAdapterBinary {
|
||||
fn from(value: DebugAdapterBinary) -> Self {
|
||||
Self {
|
||||
command: value.command,
|
||||
arguments: value.arguments,
|
||||
envs: value.envs,
|
||||
cwd: value.cwd,
|
||||
connection: value.connection.map(Into::into),
|
||||
request_args: value.request_args.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<latest::DebugAdapterBinary> for DebugAdapterBinary {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: latest::DebugAdapterBinary) -> Result<Self> {
|
||||
Ok(Self {
|
||||
command: value.command,
|
||||
arguments: value.arguments,
|
||||
envs: value.envs,
|
||||
cwd: value.cwd,
|
||||
connection: value.connection.map(TryInto::try_into).transpose()?,
|
||||
request_args: value.request_args.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl zed::extension::dap::Host for WasmState {
|
||||
async fn resolve_tcp_template(
|
||||
&mut self,
|
||||
template: dap::TcpArgumentsTemplate,
|
||||
) -> wasmtime::Result<Result<dap::TcpArguments, String>> {
|
||||
let result = latest::dap::Host::resolve_tcp_template(self, template.into()).await?;
|
||||
Ok(
|
||||
result
|
||||
.and_then(|args| dap::TcpArguments::try_from(args).map_err(|err| err.to_string())),
|
||||
)
|
||||
}
|
||||
}
|
||||
1149
crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs
Normal file
1149
crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user