wit.rs

   1mod since_v0_0_1;
   2mod since_v0_0_4;
   3mod since_v0_0_6;
   4mod since_v0_1_0;
   5mod since_v0_2_0;
   6mod since_v0_3_0;
   7mod since_v0_4_0;
   8mod since_v0_5_0;
   9mod since_v0_6_0;
  10use dap::DebugRequest;
  11use extension::{DebugTaskDefinition, KeyValueStoreDelegate, WorktreeDelegate};
  12use gpui::BackgroundExecutor;
  13use language::LanguageName;
  14use lsp::LanguageServerName;
  15use release_channel::ReleaseChannel;
  16use task::{DebugScenario, SpawnInTerminal, TaskTemplate, ZedDebugConfig};
  17
  18use crate::wasm_host::wit::since_v0_6_0::dap::StartDebuggingRequestArgumentsRequest;
  19
  20use super::{WasmState, wasm_engine};
  21use anyhow::{Context as _, Result, anyhow};
  22use semantic_version::SemanticVersion;
  23use since_v0_6_0 as latest;
  24use std::{ops::RangeInclusive, path::PathBuf, sync::Arc};
  25use wasmtime::{
  26    Store,
  27    component::{Component, Linker, Resource},
  28};
  29
  30#[cfg(test)]
  31pub use latest::CodeLabelSpanLiteral;
  32pub use latest::{
  33    CodeLabel, CodeLabelSpan, Command, DebugAdapterBinary, ExtensionProject, Range, SlashCommand,
  34    zed::extension::context_server::ContextServerConfiguration,
  35    zed::extension::lsp::{
  36        Completion, CompletionKind, CompletionLabelDetails, InsertTextFormat, Symbol, SymbolKind,
  37    },
  38    zed::extension::slash_command::{SlashCommandArgumentCompletion, SlashCommandOutput},
  39};
  40pub use since_v0_0_4::LanguageServerConfig;
  41
  42pub fn new_linker(
  43    executor: &BackgroundExecutor,
  44    f: impl Fn(&mut Linker<WasmState>, fn(&mut WasmState) -> &mut WasmState) -> Result<()>,
  45) -> Linker<WasmState> {
  46    let mut linker = Linker::new(&wasm_engine(executor));
  47    wasmtime_wasi::add_to_linker_async(&mut linker).unwrap();
  48    f(&mut linker, wasi_view).unwrap();
  49    linker
  50}
  51
  52fn wasi_view(state: &mut WasmState) -> &mut WasmState {
  53    state
  54}
  55
  56/// Returns whether the given Wasm API version is supported by the Wasm host.
  57pub fn is_supported_wasm_api_version(
  58    release_channel: ReleaseChannel,
  59    version: SemanticVersion,
  60) -> bool {
  61    wasm_api_version_range(release_channel).contains(&version)
  62}
  63
  64/// Returns the Wasm API version range that is supported by the Wasm host.
  65#[inline(always)]
  66pub fn wasm_api_version_range(release_channel: ReleaseChannel) -> RangeInclusive<SemanticVersion> {
  67    // Note: The release channel can be used to stage a new version of the extension API.
  68    let _ = release_channel;
  69
  70    let max_version = match release_channel {
  71        ReleaseChannel::Dev | ReleaseChannel::Nightly => latest::MAX_VERSION,
  72        ReleaseChannel::Stable | ReleaseChannel::Preview => since_v0_5_0::MAX_VERSION,
  73    };
  74
  75    since_v0_0_1::MIN_VERSION..=max_version
  76}
  77
  78/// Authorizes access to use unreleased versions of the Wasm API, based on the provided [`ReleaseChannel`].
  79///
  80/// Note: If there isn't currently an unreleased Wasm API version this function may be unused. Don't delete it!
  81pub fn authorize_access_to_unreleased_wasm_api_version(
  82    release_channel: ReleaseChannel,
  83) -> Result<()> {
  84    let allow_unreleased_version = match release_channel {
  85        ReleaseChannel::Dev | ReleaseChannel::Nightly => true,
  86        ReleaseChannel::Stable | ReleaseChannel::Preview => {
  87            // We always allow the latest in tests so that the extension tests pass on release branches.
  88            cfg!(any(test, feature = "test-support"))
  89        }
  90    };
  91
  92    anyhow::ensure!(
  93        allow_unreleased_version,
  94        "unreleased versions of the extension API can only be used on development builds of Zed"
  95    );
  96
  97    Ok(())
  98}
  99
 100pub enum Extension {
 101    V0_6_0(since_v0_6_0::Extension),
 102    V0_5_0(since_v0_5_0::Extension),
 103    V0_4_0(since_v0_4_0::Extension),
 104    V0_3_0(since_v0_3_0::Extension),
 105    V0_2_0(since_v0_2_0::Extension),
 106    V0_1_0(since_v0_1_0::Extension),
 107    V0_0_6(since_v0_0_6::Extension),
 108    V0_0_4(since_v0_0_4::Extension),
 109    V0_0_1(since_v0_0_1::Extension),
 110}
 111
 112impl Extension {
 113    pub async fn instantiate_async(
 114        executor: &BackgroundExecutor,
 115        store: &mut Store<WasmState>,
 116        release_channel: ReleaseChannel,
 117        version: SemanticVersion,
 118        component: &Component,
 119    ) -> Result<Self> {
 120        // Note: The release channel can be used to stage a new version of the extension API.
 121        let _ = release_channel;
 122
 123        if version >= latest::MIN_VERSION {
 124            authorize_access_to_unreleased_wasm_api_version(release_channel)?;
 125
 126            let extension =
 127                latest::Extension::instantiate_async(store, component, latest::linker(executor))
 128                    .await
 129                    .context("failed to instantiate wasm extension")?;
 130            Ok(Self::V0_6_0(extension))
 131        } else if version >= since_v0_5_0::MIN_VERSION {
 132            let extension = since_v0_5_0::Extension::instantiate_async(
 133                store,
 134                component,
 135                since_v0_5_0::linker(executor),
 136            )
 137            .await
 138            .context("failed to instantiate wasm extension")?;
 139            Ok(Self::V0_5_0(extension))
 140        } else if version >= since_v0_4_0::MIN_VERSION {
 141            let extension = since_v0_4_0::Extension::instantiate_async(
 142                store,
 143                component,
 144                since_v0_4_0::linker(executor),
 145            )
 146            .await
 147            .context("failed to instantiate wasm extension")?;
 148            Ok(Self::V0_4_0(extension))
 149        } else if version >= since_v0_3_0::MIN_VERSION {
 150            let extension = since_v0_3_0::Extension::instantiate_async(
 151                store,
 152                component,
 153                since_v0_3_0::linker(executor),
 154            )
 155            .await
 156            .context("failed to instantiate wasm extension")?;
 157            Ok(Self::V0_3_0(extension))
 158        } else if version >= since_v0_2_0::MIN_VERSION {
 159            let extension = since_v0_2_0::Extension::instantiate_async(
 160                store,
 161                component,
 162                since_v0_2_0::linker(executor),
 163            )
 164            .await
 165            .context("failed to instantiate wasm extension")?;
 166            Ok(Self::V0_2_0(extension))
 167        } else if version >= since_v0_1_0::MIN_VERSION {
 168            let extension = since_v0_1_0::Extension::instantiate_async(
 169                store,
 170                component,
 171                since_v0_1_0::linker(executor),
 172            )
 173            .await
 174            .context("failed to instantiate wasm extension")?;
 175            Ok(Self::V0_1_0(extension))
 176        } else if version >= since_v0_0_6::MIN_VERSION {
 177            let extension = since_v0_0_6::Extension::instantiate_async(
 178                store,
 179                component,
 180                since_v0_0_6::linker(executor),
 181            )
 182            .await
 183            .context("failed to instantiate wasm extension")?;
 184            Ok(Self::V0_0_6(extension))
 185        } else if version >= since_v0_0_4::MIN_VERSION {
 186            let extension = since_v0_0_4::Extension::instantiate_async(
 187                store,
 188                component,
 189                since_v0_0_4::linker(executor),
 190            )
 191            .await
 192            .context("failed to instantiate wasm extension")?;
 193            Ok(Self::V0_0_4(extension))
 194        } else {
 195            let extension = since_v0_0_1::Extension::instantiate_async(
 196                store,
 197                component,
 198                since_v0_0_1::linker(executor),
 199            )
 200            .await
 201            .context("failed to instantiate wasm extension")?;
 202            Ok(Self::V0_0_1(extension))
 203        }
 204    }
 205
 206    pub async fn call_init_extension(&self, store: &mut Store<WasmState>) -> Result<()> {
 207        match self {
 208            Extension::V0_6_0(ext) => ext.call_init_extension(store).await,
 209            Extension::V0_5_0(ext) => ext.call_init_extension(store).await,
 210            Extension::V0_4_0(ext) => ext.call_init_extension(store).await,
 211            Extension::V0_3_0(ext) => ext.call_init_extension(store).await,
 212            Extension::V0_2_0(ext) => ext.call_init_extension(store).await,
 213            Extension::V0_1_0(ext) => ext.call_init_extension(store).await,
 214            Extension::V0_0_6(ext) => ext.call_init_extension(store).await,
 215            Extension::V0_0_4(ext) => ext.call_init_extension(store).await,
 216            Extension::V0_0_1(ext) => ext.call_init_extension(store).await,
 217        }
 218    }
 219
 220    pub async fn call_language_server_command(
 221        &self,
 222        store: &mut Store<WasmState>,
 223        language_server_id: &LanguageServerName,
 224        language_name: &LanguageName,
 225        resource: Resource<Arc<dyn WorktreeDelegate>>,
 226    ) -> Result<Result<Command, String>> {
 227        match self {
 228            Extension::V0_6_0(ext) => {
 229                ext.call_language_server_command(store, &language_server_id.0, resource)
 230                    .await
 231            }
 232            Extension::V0_5_0(ext) => {
 233                ext.call_language_server_command(store, &language_server_id.0, resource)
 234                    .await
 235            }
 236            Extension::V0_4_0(ext) => {
 237                ext.call_language_server_command(store, &language_server_id.0, resource)
 238                    .await
 239            }
 240            Extension::V0_3_0(ext) => {
 241                ext.call_language_server_command(store, &language_server_id.0, resource)
 242                    .await
 243            }
 244            Extension::V0_2_0(ext) => Ok(ext
 245                .call_language_server_command(store, &language_server_id.0, resource)
 246                .await?
 247                .map(|command| command.into())),
 248            Extension::V0_1_0(ext) => Ok(ext
 249                .call_language_server_command(store, &language_server_id.0, resource)
 250                .await?
 251                .map(|command| command.into())),
 252            Extension::V0_0_6(ext) => Ok(ext
 253                .call_language_server_command(store, &language_server_id.0, resource)
 254                .await?
 255                .map(|command| command.into())),
 256            Extension::V0_0_4(ext) => Ok(ext
 257                .call_language_server_command(
 258                    store,
 259                    &LanguageServerConfig {
 260                        name: language_server_id.0.to_string(),
 261                        language_name: language_name.to_string(),
 262                    },
 263                    resource,
 264                )
 265                .await?
 266                .map(|command| command.into())),
 267            Extension::V0_0_1(ext) => Ok(ext
 268                .call_language_server_command(
 269                    store,
 270                    &LanguageServerConfig {
 271                        name: language_server_id.0.to_string(),
 272                        language_name: language_name.to_string(),
 273                    }
 274                    .into(),
 275                    resource,
 276                )
 277                .await?
 278                .map(|command| command.into())),
 279        }
 280    }
 281
 282    pub async fn call_language_server_initialization_options(
 283        &self,
 284        store: &mut Store<WasmState>,
 285        language_server_id: &LanguageServerName,
 286        language_name: &LanguageName,
 287        resource: Resource<Arc<dyn WorktreeDelegate>>,
 288    ) -> Result<Result<Option<String>, String>> {
 289        match self {
 290            Extension::V0_6_0(ext) => {
 291                ext.call_language_server_initialization_options(
 292                    store,
 293                    &language_server_id.0,
 294                    resource,
 295                )
 296                .await
 297            }
 298            Extension::V0_5_0(ext) => {
 299                ext.call_language_server_initialization_options(
 300                    store,
 301                    &language_server_id.0,
 302                    resource,
 303                )
 304                .await
 305            }
 306            Extension::V0_4_0(ext) => {
 307                ext.call_language_server_initialization_options(
 308                    store,
 309                    &language_server_id.0,
 310                    resource,
 311                )
 312                .await
 313            }
 314            Extension::V0_3_0(ext) => {
 315                ext.call_language_server_initialization_options(
 316                    store,
 317                    &language_server_id.0,
 318                    resource,
 319                )
 320                .await
 321            }
 322            Extension::V0_2_0(ext) => {
 323                ext.call_language_server_initialization_options(
 324                    store,
 325                    &language_server_id.0,
 326                    resource,
 327                )
 328                .await
 329            }
 330            Extension::V0_1_0(ext) => {
 331                ext.call_language_server_initialization_options(
 332                    store,
 333                    &language_server_id.0,
 334                    resource,
 335                )
 336                .await
 337            }
 338            Extension::V0_0_6(ext) => {
 339                ext.call_language_server_initialization_options(
 340                    store,
 341                    &language_server_id.0,
 342                    resource,
 343                )
 344                .await
 345            }
 346            Extension::V0_0_4(ext) => {
 347                ext.call_language_server_initialization_options(
 348                    store,
 349                    &LanguageServerConfig {
 350                        name: language_server_id.0.to_string(),
 351                        language_name: language_name.to_string(),
 352                    },
 353                    resource,
 354                )
 355                .await
 356            }
 357            Extension::V0_0_1(ext) => {
 358                ext.call_language_server_initialization_options(
 359                    store,
 360                    &LanguageServerConfig {
 361                        name: language_server_id.0.to_string(),
 362                        language_name: language_name.to_string(),
 363                    }
 364                    .into(),
 365                    resource,
 366                )
 367                .await
 368            }
 369        }
 370    }
 371
 372    pub async fn call_language_server_workspace_configuration(
 373        &self,
 374        store: &mut Store<WasmState>,
 375        language_server_id: &LanguageServerName,
 376        resource: Resource<Arc<dyn WorktreeDelegate>>,
 377    ) -> Result<Result<Option<String>, String>> {
 378        match self {
 379            Extension::V0_6_0(ext) => {
 380                ext.call_language_server_workspace_configuration(
 381                    store,
 382                    &language_server_id.0,
 383                    resource,
 384                )
 385                .await
 386            }
 387            Extension::V0_5_0(ext) => {
 388                ext.call_language_server_workspace_configuration(
 389                    store,
 390                    &language_server_id.0,
 391                    resource,
 392                )
 393                .await
 394            }
 395            Extension::V0_4_0(ext) => {
 396                ext.call_language_server_workspace_configuration(
 397                    store,
 398                    &language_server_id.0,
 399                    resource,
 400                )
 401                .await
 402            }
 403            Extension::V0_3_0(ext) => {
 404                ext.call_language_server_workspace_configuration(
 405                    store,
 406                    &language_server_id.0,
 407                    resource,
 408                )
 409                .await
 410            }
 411            Extension::V0_2_0(ext) => {
 412                ext.call_language_server_workspace_configuration(
 413                    store,
 414                    &language_server_id.0,
 415                    resource,
 416                )
 417                .await
 418            }
 419            Extension::V0_1_0(ext) => {
 420                ext.call_language_server_workspace_configuration(
 421                    store,
 422                    &language_server_id.0,
 423                    resource,
 424                )
 425                .await
 426            }
 427            Extension::V0_0_6(ext) => {
 428                ext.call_language_server_workspace_configuration(
 429                    store,
 430                    &language_server_id.0,
 431                    resource,
 432                )
 433                .await
 434            }
 435            Extension::V0_0_4(_) | Extension::V0_0_1(_) => Ok(Ok(None)),
 436        }
 437    }
 438
 439    pub async fn call_language_server_additional_initialization_options(
 440        &self,
 441        store: &mut Store<WasmState>,
 442        language_server_id: &LanguageServerName,
 443        target_language_server_id: &LanguageServerName,
 444        resource: Resource<Arc<dyn WorktreeDelegate>>,
 445    ) -> Result<Result<Option<String>, String>> {
 446        match self {
 447            Extension::V0_6_0(ext) => {
 448                ext.call_language_server_additional_initialization_options(
 449                    store,
 450                    &language_server_id.0,
 451                    &target_language_server_id.0,
 452                    resource,
 453                )
 454                .await
 455            }
 456            Extension::V0_5_0(ext) => {
 457                ext.call_language_server_additional_initialization_options(
 458                    store,
 459                    &language_server_id.0,
 460                    &target_language_server_id.0,
 461                    resource,
 462                )
 463                .await
 464            }
 465            Extension::V0_4_0(ext) => {
 466                ext.call_language_server_additional_initialization_options(
 467                    store,
 468                    &language_server_id.0,
 469                    &target_language_server_id.0,
 470                    resource,
 471                )
 472                .await
 473            }
 474            Extension::V0_3_0(_)
 475            | Extension::V0_2_0(_)
 476            | Extension::V0_1_0(_)
 477            | Extension::V0_0_6(_)
 478            | Extension::V0_0_4(_)
 479            | Extension::V0_0_1(_) => Ok(Ok(None)),
 480        }
 481    }
 482
 483    pub async fn call_language_server_additional_workspace_configuration(
 484        &self,
 485        store: &mut Store<WasmState>,
 486        language_server_id: &LanguageServerName,
 487        target_language_server_id: &LanguageServerName,
 488        resource: Resource<Arc<dyn WorktreeDelegate>>,
 489    ) -> Result<Result<Option<String>, String>> {
 490        match self {
 491            Extension::V0_6_0(ext) => {
 492                ext.call_language_server_additional_workspace_configuration(
 493                    store,
 494                    &language_server_id.0,
 495                    &target_language_server_id.0,
 496                    resource,
 497                )
 498                .await
 499            }
 500            Extension::V0_5_0(ext) => {
 501                ext.call_language_server_additional_workspace_configuration(
 502                    store,
 503                    &language_server_id.0,
 504                    &target_language_server_id.0,
 505                    resource,
 506                )
 507                .await
 508            }
 509            Extension::V0_4_0(ext) => {
 510                ext.call_language_server_additional_workspace_configuration(
 511                    store,
 512                    &language_server_id.0,
 513                    &target_language_server_id.0,
 514                    resource,
 515                )
 516                .await
 517            }
 518            Extension::V0_3_0(_)
 519            | Extension::V0_2_0(_)
 520            | Extension::V0_1_0(_)
 521            | Extension::V0_0_6(_)
 522            | Extension::V0_0_4(_)
 523            | Extension::V0_0_1(_) => Ok(Ok(None)),
 524        }
 525    }
 526
 527    pub async fn call_labels_for_completions(
 528        &self,
 529        store: &mut Store<WasmState>,
 530        language_server_id: &LanguageServerName,
 531        completions: Vec<latest::Completion>,
 532    ) -> Result<Result<Vec<Option<CodeLabel>>, String>> {
 533        match self {
 534            Extension::V0_6_0(ext) => {
 535                ext.call_labels_for_completions(store, &language_server_id.0, &completions)
 536                    .await
 537            }
 538            Extension::V0_5_0(ext) => Ok(ext
 539                .call_labels_for_completions(
 540                    store,
 541                    &language_server_id.0,
 542                    &completions.into_iter().collect::<Vec<_>>(),
 543                )
 544                .await?
 545                .map(|labels| {
 546                    labels
 547                        .into_iter()
 548                        .map(|label| label.map(Into::into))
 549                        .collect()
 550                })),
 551            Extension::V0_4_0(ext) => Ok(ext
 552                .call_labels_for_completions(
 553                    store,
 554                    &language_server_id.0,
 555                    &completions.into_iter().collect::<Vec<_>>(),
 556                )
 557                .await?
 558                .map(|labels| {
 559                    labels
 560                        .into_iter()
 561                        .map(|label| label.map(Into::into))
 562                        .collect()
 563                })),
 564            Extension::V0_3_0(ext) => Ok(ext
 565                .call_labels_for_completions(
 566                    store,
 567                    &language_server_id.0,
 568                    &completions.into_iter().collect::<Vec<_>>(),
 569                )
 570                .await?
 571                .map(|labels| {
 572                    labels
 573                        .into_iter()
 574                        .map(|label| label.map(Into::into))
 575                        .collect()
 576                })),
 577            Extension::V0_2_0(ext) => Ok(ext
 578                .call_labels_for_completions(
 579                    store,
 580                    &language_server_id.0,
 581                    &completions.into_iter().collect::<Vec<_>>(),
 582                )
 583                .await?
 584                .map(|labels| {
 585                    labels
 586                        .into_iter()
 587                        .map(|label| label.map(Into::into))
 588                        .collect()
 589                })),
 590            Extension::V0_1_0(ext) => Ok(ext
 591                .call_labels_for_completions(
 592                    store,
 593                    &language_server_id.0,
 594                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
 595                )
 596                .await?
 597                .map(|labels| {
 598                    labels
 599                        .into_iter()
 600                        .map(|label| label.map(Into::into))
 601                        .collect()
 602                })),
 603            Extension::V0_0_6(ext) => Ok(ext
 604                .call_labels_for_completions(
 605                    store,
 606                    &language_server_id.0,
 607                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
 608                )
 609                .await?
 610                .map(|labels| {
 611                    labels
 612                        .into_iter()
 613                        .map(|label| label.map(Into::into))
 614                        .collect()
 615                })),
 616            Extension::V0_0_1(_) | Extension::V0_0_4(_) => Ok(Ok(Vec::new())),
 617        }
 618    }
 619
 620    pub async fn call_labels_for_symbols(
 621        &self,
 622        store: &mut Store<WasmState>,
 623        language_server_id: &LanguageServerName,
 624        symbols: Vec<latest::Symbol>,
 625    ) -> Result<Result<Vec<Option<CodeLabel>>, String>> {
 626        match self {
 627            Extension::V0_6_0(ext) => {
 628                ext.call_labels_for_symbols(store, &language_server_id.0, &symbols)
 629                    .await
 630            }
 631            Extension::V0_5_0(ext) => Ok(ext
 632                .call_labels_for_symbols(
 633                    store,
 634                    &language_server_id.0,
 635                    &symbols.into_iter().collect::<Vec<_>>(),
 636                )
 637                .await?
 638                .map(|labels| {
 639                    labels
 640                        .into_iter()
 641                        .map(|label| label.map(Into::into))
 642                        .collect()
 643                })),
 644            Extension::V0_4_0(ext) => Ok(ext
 645                .call_labels_for_symbols(
 646                    store,
 647                    &language_server_id.0,
 648                    &symbols.into_iter().collect::<Vec<_>>(),
 649                )
 650                .await?
 651                .map(|labels| {
 652                    labels
 653                        .into_iter()
 654                        .map(|label| label.map(Into::into))
 655                        .collect()
 656                })),
 657            Extension::V0_3_0(ext) => Ok(ext
 658                .call_labels_for_symbols(
 659                    store,
 660                    &language_server_id.0,
 661                    &symbols.into_iter().collect::<Vec<_>>(),
 662                )
 663                .await?
 664                .map(|labels| {
 665                    labels
 666                        .into_iter()
 667                        .map(|label| label.map(Into::into))
 668                        .collect()
 669                })),
 670            Extension::V0_2_0(ext) => Ok(ext
 671                .call_labels_for_symbols(
 672                    store,
 673                    &language_server_id.0,
 674                    &symbols.into_iter().collect::<Vec<_>>(),
 675                )
 676                .await?
 677                .map(|labels| {
 678                    labels
 679                        .into_iter()
 680                        .map(|label| label.map(Into::into))
 681                        .collect()
 682                })),
 683            Extension::V0_1_0(ext) => Ok(ext
 684                .call_labels_for_symbols(
 685                    store,
 686                    &language_server_id.0,
 687                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
 688                )
 689                .await?
 690                .map(|labels| {
 691                    labels
 692                        .into_iter()
 693                        .map(|label| label.map(Into::into))
 694                        .collect()
 695                })),
 696            Extension::V0_0_6(ext) => Ok(ext
 697                .call_labels_for_symbols(
 698                    store,
 699                    &language_server_id.0,
 700                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
 701                )
 702                .await?
 703                .map(|labels| {
 704                    labels
 705                        .into_iter()
 706                        .map(|label| label.map(Into::into))
 707                        .collect()
 708                })),
 709            Extension::V0_0_1(_) | Extension::V0_0_4(_) => Ok(Ok(Vec::new())),
 710        }
 711    }
 712
 713    pub async fn call_complete_slash_command_argument(
 714        &self,
 715        store: &mut Store<WasmState>,
 716        command: &SlashCommand,
 717        arguments: &[String],
 718    ) -> Result<Result<Vec<SlashCommandArgumentCompletion>, String>> {
 719        match self {
 720            Extension::V0_6_0(ext) => {
 721                ext.call_complete_slash_command_argument(store, command, arguments)
 722                    .await
 723            }
 724            Extension::V0_5_0(ext) => {
 725                ext.call_complete_slash_command_argument(store, command, arguments)
 726                    .await
 727            }
 728            Extension::V0_4_0(ext) => {
 729                ext.call_complete_slash_command_argument(store, command, arguments)
 730                    .await
 731            }
 732            Extension::V0_3_0(ext) => {
 733                ext.call_complete_slash_command_argument(store, command, arguments)
 734                    .await
 735            }
 736            Extension::V0_2_0(ext) => {
 737                ext.call_complete_slash_command_argument(store, command, arguments)
 738                    .await
 739            }
 740            Extension::V0_1_0(ext) => {
 741                ext.call_complete_slash_command_argument(store, command, arguments)
 742                    .await
 743            }
 744            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
 745                Ok(Ok(Vec::new()))
 746            }
 747        }
 748    }
 749
 750    pub async fn call_run_slash_command(
 751        &self,
 752        store: &mut Store<WasmState>,
 753        command: &SlashCommand,
 754        arguments: &[String],
 755        resource: Option<Resource<Arc<dyn WorktreeDelegate>>>,
 756    ) -> Result<Result<SlashCommandOutput, String>> {
 757        match self {
 758            Extension::V0_6_0(ext) => {
 759                ext.call_run_slash_command(store, command, arguments, resource)
 760                    .await
 761            }
 762            Extension::V0_5_0(ext) => {
 763                ext.call_run_slash_command(store, command, arguments, resource)
 764                    .await
 765            }
 766            Extension::V0_4_0(ext) => {
 767                ext.call_run_slash_command(store, command, arguments, resource)
 768                    .await
 769            }
 770            Extension::V0_3_0(ext) => {
 771                ext.call_run_slash_command(store, command, arguments, resource)
 772                    .await
 773            }
 774            Extension::V0_2_0(ext) => {
 775                ext.call_run_slash_command(store, command, arguments, resource)
 776                    .await
 777            }
 778            Extension::V0_1_0(ext) => {
 779                ext.call_run_slash_command(store, command, arguments, resource)
 780                    .await
 781            }
 782            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
 783                anyhow::bail!("`run_slash_command` not available prior to v0.1.0");
 784            }
 785        }
 786    }
 787
 788    pub async fn call_context_server_command(
 789        &self,
 790        store: &mut Store<WasmState>,
 791        context_server_id: Arc<str>,
 792        project: Resource<ExtensionProject>,
 793    ) -> Result<Result<Command, String>> {
 794        match self {
 795            Extension::V0_6_0(ext) => {
 796                ext.call_context_server_command(store, &context_server_id, project)
 797                    .await
 798            }
 799            Extension::V0_5_0(ext) => {
 800                ext.call_context_server_command(store, &context_server_id, project)
 801                    .await
 802            }
 803            Extension::V0_4_0(ext) => {
 804                ext.call_context_server_command(store, &context_server_id, project)
 805                    .await
 806            }
 807            Extension::V0_3_0(ext) => {
 808                ext.call_context_server_command(store, &context_server_id, project)
 809                    .await
 810            }
 811            Extension::V0_2_0(ext) => Ok(ext
 812                .call_context_server_command(store, &context_server_id, project)
 813                .await?
 814                .map(Into::into)),
 815            Extension::V0_0_1(_)
 816            | Extension::V0_0_4(_)
 817            | Extension::V0_0_6(_)
 818            | Extension::V0_1_0(_) => {
 819                anyhow::bail!("`context_server_command` not available prior to v0.2.0");
 820            }
 821        }
 822    }
 823
 824    pub async fn call_context_server_configuration(
 825        &self,
 826        store: &mut Store<WasmState>,
 827        context_server_id: Arc<str>,
 828        project: Resource<ExtensionProject>,
 829    ) -> Result<Result<Option<ContextServerConfiguration>, String>> {
 830        match self {
 831            Extension::V0_6_0(ext) => {
 832                ext.call_context_server_configuration(store, &context_server_id, project)
 833                    .await
 834            }
 835            Extension::V0_5_0(ext) => {
 836                ext.call_context_server_configuration(store, &context_server_id, project)
 837                    .await
 838            }
 839            Extension::V0_0_1(_)
 840            | Extension::V0_0_4(_)
 841            | Extension::V0_0_6(_)
 842            | Extension::V0_1_0(_)
 843            | Extension::V0_2_0(_)
 844            | Extension::V0_3_0(_)
 845            | Extension::V0_4_0(_) => {
 846                anyhow::bail!("`context_server_configuration` not available prior to v0.5.0");
 847            }
 848        }
 849    }
 850
 851    pub async fn call_suggest_docs_packages(
 852        &self,
 853        store: &mut Store<WasmState>,
 854        provider: &str,
 855    ) -> Result<Result<Vec<String>, String>> {
 856        match self {
 857            Extension::V0_6_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
 858            Extension::V0_5_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
 859            Extension::V0_4_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
 860            Extension::V0_3_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
 861            Extension::V0_2_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
 862            Extension::V0_1_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
 863            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
 864                anyhow::bail!("`suggest_docs_packages` not available prior to v0.1.0");
 865            }
 866        }
 867    }
 868
 869    pub async fn call_index_docs(
 870        &self,
 871        store: &mut Store<WasmState>,
 872        provider: &str,
 873        package_name: &str,
 874        kv_store: Resource<Arc<dyn KeyValueStoreDelegate>>,
 875    ) -> Result<Result<(), String>> {
 876        match self {
 877            Extension::V0_6_0(ext) => {
 878                ext.call_index_docs(store, provider, package_name, kv_store)
 879                    .await
 880            }
 881            Extension::V0_5_0(ext) => {
 882                ext.call_index_docs(store, provider, package_name, kv_store)
 883                    .await
 884            }
 885            Extension::V0_4_0(ext) => {
 886                ext.call_index_docs(store, provider, package_name, kv_store)
 887                    .await
 888            }
 889            Extension::V0_3_0(ext) => {
 890                ext.call_index_docs(store, provider, package_name, kv_store)
 891                    .await
 892            }
 893            Extension::V0_2_0(ext) => {
 894                ext.call_index_docs(store, provider, package_name, kv_store)
 895                    .await
 896            }
 897            Extension::V0_1_0(ext) => {
 898                ext.call_index_docs(store, provider, package_name, kv_store)
 899                    .await
 900            }
 901            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
 902                anyhow::bail!("`index_docs` not available prior to v0.1.0");
 903            }
 904        }
 905    }
 906    pub async fn call_get_dap_binary(
 907        &self,
 908        store: &mut Store<WasmState>,
 909        adapter_name: Arc<str>,
 910        task: DebugTaskDefinition,
 911        user_installed_path: Option<PathBuf>,
 912        resource: Resource<Arc<dyn WorktreeDelegate>>,
 913    ) -> Result<Result<DebugAdapterBinary, String>> {
 914        match self {
 915            Extension::V0_6_0(ext) => {
 916                let dap_binary = ext
 917                    .call_get_dap_binary(
 918                        store,
 919                        &adapter_name,
 920                        &task.try_into()?,
 921                        user_installed_path.as_ref().and_then(|p| p.to_str()),
 922                        resource,
 923                    )
 924                    .await?
 925                    .map_err(|e| anyhow!("{e:?}"))?;
 926
 927                Ok(Ok(dap_binary))
 928            }
 929            _ => anyhow::bail!("`get_dap_binary` not available prior to v0.6.0"),
 930        }
 931    }
 932    pub async fn call_dap_request_kind(
 933        &self,
 934        store: &mut Store<WasmState>,
 935        adapter_name: Arc<str>,
 936        config: serde_json::Value,
 937    ) -> Result<Result<StartDebuggingRequestArgumentsRequest, String>> {
 938        match self {
 939            Extension::V0_6_0(ext) => {
 940                let config =
 941                    serde_json::to_string(&config).context("Adapter config is not a valid JSON")?;
 942                let dap_binary = ext
 943                    .call_dap_request_kind(store, &adapter_name, &config)
 944                    .await?
 945                    .map_err(|e| anyhow!("{e:?}"))?;
 946
 947                Ok(Ok(dap_binary))
 948            }
 949            _ => anyhow::bail!("`dap_request_kind` not available prior to v0.6.0"),
 950        }
 951    }
 952    pub async fn call_dap_config_to_scenario(
 953        &self,
 954        store: &mut Store<WasmState>,
 955        config: ZedDebugConfig,
 956    ) -> Result<Result<DebugScenario, String>> {
 957        match self {
 958            Extension::V0_6_0(ext) => {
 959                let config = config.into();
 960                let dap_binary = ext
 961                    .call_dap_config_to_scenario(store, &config)
 962                    .await?
 963                    .map_err(|e| anyhow!("{e:?}"))?;
 964
 965                Ok(Ok(dap_binary.try_into()?))
 966            }
 967            _ => anyhow::bail!("`dap_config_to_scenario` not available prior to v0.6.0"),
 968        }
 969    }
 970    pub async fn call_dap_locator_create_scenario(
 971        &self,
 972        store: &mut Store<WasmState>,
 973        locator_name: String,
 974        build_config_template: TaskTemplate,
 975        resolved_label: String,
 976        debug_adapter_name: String,
 977    ) -> Result<Option<DebugScenario>> {
 978        match self {
 979            Extension::V0_6_0(ext) => {
 980                let build_config_template = build_config_template.into();
 981                let dap_binary = ext
 982                    .call_dap_locator_create_scenario(
 983                        store,
 984                        &locator_name,
 985                        &build_config_template,
 986                        &resolved_label,
 987                        &debug_adapter_name,
 988                    )
 989                    .await?;
 990
 991                Ok(dap_binary.map(TryInto::try_into).transpose()?)
 992            }
 993            _ => anyhow::bail!("`dap_locator_create_scenario` not available prior to v0.6.0"),
 994        }
 995    }
 996    pub async fn call_run_dap_locator(
 997        &self,
 998        store: &mut Store<WasmState>,
 999        locator_name: String,
1000        resolved_build_task: SpawnInTerminal,
1001    ) -> Result<Result<DebugRequest, String>> {
1002        match self {
1003            Extension::V0_6_0(ext) => {
1004                let build_config_template = resolved_build_task.into();
1005                let dap_request = ext
1006                    .call_run_dap_locator(store, &locator_name, &build_config_template)
1007                    .await?
1008                    .map_err(|e| anyhow!("{e:?}"))?;
1009
1010                Ok(Ok(dap_request.into()))
1011            }
1012            _ => anyhow::bail!("`dap_locator_create_scenario` not available prior to v0.6.0"),
1013        }
1014    }
1015}
1016
1017trait ToWasmtimeResult<T> {
1018    fn to_wasmtime_result(self) -> wasmtime::Result<Result<T, String>>;
1019}
1020
1021impl<T> ToWasmtimeResult<T> for Result<T> {
1022    fn to_wasmtime_result(self) -> wasmtime::Result<Result<T, String>> {
1023        Ok(self.map_err(|error| format!("{error:?}")))
1024    }
1025}