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