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