1use crate::wasm_host::{wit::LanguageServerConfig, WasmExtension};
2use anyhow::{anyhow, Result};
3use async_trait::async_trait;
4use futures::{Future, FutureExt};
5use gpui::AsyncAppContext;
6use language::{Language, LanguageServerName, LspAdapter, LspAdapterDelegate};
7use lsp::LanguageServerBinary;
8use std::{
9 any::Any,
10 path::{Path, PathBuf},
11 pin::Pin,
12 sync::Arc,
13};
14use wasmtime_wasi::preview2::WasiView as _;
15
16pub struct ExtensionLspAdapter {
17 pub(crate) extension: WasmExtension,
18 pub(crate) config: LanguageServerConfig,
19 pub(crate) work_dir: PathBuf,
20}
21
22#[async_trait]
23impl LspAdapter for ExtensionLspAdapter {
24 fn name(&self) -> LanguageServerName {
25 LanguageServerName(self.config.name.clone().into())
26 }
27
28 fn get_language_server_command<'a>(
29 self: Arc<Self>,
30 _: Arc<Language>,
31 _: Arc<Path>,
32 delegate: Arc<dyn LspAdapterDelegate>,
33 _: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
34 _: &'a mut AsyncAppContext,
35 ) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> {
36 async move {
37 let command = self
38 .extension
39 .call({
40 let this = self.clone();
41 |extension, store| {
42 async move {
43 let resource = store.data_mut().table().push(delegate)?;
44 extension
45 .call_language_server_command(store, &this.config, resource)
46 .await
47 }
48 .boxed()
49 }
50 })
51 .await?
52 .map_err(|e| anyhow!("{}", e))?;
53
54 Ok(LanguageServerBinary {
55 path: self.work_dir.join(&command.command),
56 arguments: command.args.into_iter().map(|arg| arg.into()).collect(),
57 env: Some(command.env.into_iter().collect()),
58 })
59 }
60 .boxed_local()
61 }
62
63 async fn fetch_latest_server_version(
64 &self,
65 _: &dyn LspAdapterDelegate,
66 ) -> Result<Box<dyn 'static + Send + Any>> {
67 unreachable!("get_language_server_command is overridden")
68 }
69
70 async fn fetch_server_binary(
71 &self,
72 _: Box<dyn 'static + Send + Any>,
73 _: PathBuf,
74 _: &dyn LspAdapterDelegate,
75 ) -> Result<LanguageServerBinary> {
76 unreachable!("get_language_server_command is overridden")
77 }
78
79 async fn cached_server_binary(
80 &self,
81 _: PathBuf,
82 _: &dyn LspAdapterDelegate,
83 ) -> Option<LanguageServerBinary> {
84 unreachable!("get_language_server_command is overridden")
85 }
86
87 async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
88 None
89 }
90}