1use anyhow::Context as _;
2use gpui::{AppContext, WeakEntity};
3use lsp::{LanguageServer, LanguageServerName};
4use serde_json::json;
5
6use crate::LspStore;
7
8struct VueServerRequest;
9struct TypescriptServerResponse;
10
11impl lsp::notification::Notification for VueServerRequest {
12 type Params = [(u64, String, serde_json::Value); 1];
13
14 const METHOD: &'static str = "tsserver/request";
15}
16
17impl lsp::notification::Notification for TypescriptServerResponse {
18 type Params = serde_json::Value;
19
20 const METHOD: &'static str = "tsserver/response";
21}
22
23const VUE_SERVER_NAME: LanguageServerName = LanguageServerName::new_static("vue-language-server");
24const VTSLS: LanguageServerName = LanguageServerName::new_static("vtsls");
25const TS_LS: LanguageServerName = LanguageServerName::new_static("typescript-language-server");
26
27pub fn register_requests(lsp_store: WeakEntity<LspStore>, language_server: &LanguageServer) {
28 let language_server_name = language_server.name();
29 if language_server_name == VUE_SERVER_NAME {
30 let vue_server_id = language_server.server_id();
31 language_server
32 .on_notification::<VueServerRequest, _>({
33 let this = lsp_store.clone();
34 move |params, cx| {
35 let this = this.clone();
36 let Ok(target_server) = this
37 .read_with(cx, |this, _| {
38 let language_server_id = this
39 .as_local()
40 .and_then(|local| {
41 local.language_server_ids.iter().find_map(|(seed, v)| {
42 [VTSLS, TS_LS].contains(&seed.name).then_some(v.id)
43 })
44 })
45 .context("Could not find language server")?;
46
47 this.language_server_for_id(language_server_id)
48 .context("language server not found")
49 })
50 .flatten()
51 else {
52 return;
53 };
54 let Some(vue_server) = this
55 .read_with(cx, |this, _| this.language_server_for_id(vue_server_id))
56 .ok()
57 .flatten()
58 else {
59 return;
60 };
61 let cx = cx.clone();
62 cx.background_spawn(async move {
63 let (request_id, command, arguments) = params[0].clone();
64 let tsserver_response = target_server
65 .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
66 command: "typescript.tsserverRequest".to_owned(),
67 arguments: vec![serde_json::Value::String(command), arguments],
68 ..Default::default()
69 })
70 .await;
71 if let util::ConnectionResult::Result(Ok(result)) = tsserver_response {
72 _ = vue_server.notify::<TypescriptServerResponse>(
73 &json!({ "id": request_id, "response": result }),
74 );
75 }
76 })
77 .detach();
78 }
79 })
80 .detach();
81 }
82}