1use std::any::TypeId;
2use std::fmt::Display;
3
4use anyhow::{Context, anyhow};
5use lsp_server::{ErrorCode, Message, Notification, RequestId, ResponseError};
6use serde_json::Value;
7
8use crate::Session;
9use crate::server::{ConnectionSender, Event, MainLoopSender};
10
11pub(crate) type ClientResponseHandler =
12 Box<dyn FnOnce(&Client, &mut Session, lsp_server::Response) + Send>;
13
14#[derive(Clone, Debug)]
16pub struct Client {
17 main_loop_sender: MainLoopSender,
18 client_sender: ConnectionSender,
19}
20
21impl Client {
22 pub fn new(main_loop_sender: MainLoopSender, client_sender: ConnectionSender) -> Self {
24 Self {
25 main_loop_sender,
26 client_sender,
27 }
28 }
29
30 pub(crate) fn send_request<R>(
31 &self,
32 session: &Session,
33 params: R::Params,
34 response_handler: impl FnOnce(&Client, &mut Session, R::Result) + Send + 'static,
35 ) -> crate::Result<()>
36 where
37 R: lsp_types::request::Request,
38 {
39 let response_handler = Box::new(
40 move |client: &Client, session: &mut Session, response: lsp_server::Response| match (
41 response.error,
42 response.result,
43 ) {
44 (Some(err), _) => {
45 tracing::error!(
46 "Client request failed (method={} code={}): {}",
47 R::METHOD,
48 err.code,
49 err.message
50 );
51 }
52 (None, Some(response)) => match serde_json::from_value(response) {
53 Ok(response) => response_handler(client, session, response),
54 Err(error) => {
55 tracing::error!(
56 "Failed to deserialize client response for {}: {error}",
57 R::METHOD
58 );
59 }
60 },
61 (None, None) => {
62 if TypeId::of::<R::Result>() == TypeId::of::<()>() {
63 match serde_json::from_value(Value::Null) {
64 Ok(response) => response_handler(client, session, response),
65 Err(error) => {
66 tracing::error!(
67 "Failed to deserialize unit client response for {}: {error}",
68 R::METHOD
69 );
70 }
71 }
72 } else {
73 tracing::error!(
74 "Client response missing result and error for {}",
75 R::METHOD
76 );
77 }
78 }
79 },
80 );
81
82 let id = session
83 .request_queue()
84 .outgoing()
85 .register(response_handler);
86 self.client_sender
87 .send(Message::Request(lsp_server::Request {
88 id,
89 method: R::METHOD.to_string(),
90 params: serde_json::to_value(params).context("Failed to serialize params")?,
91 }))
92 .with_context(|| format!("Failed to send request {}", R::METHOD))?;
93 Ok(())
94 }
95
96 pub(crate) fn send_notification<N>(&self, params: N::Params) -> crate::Result<()>
97 where
98 N: lsp_types::notification::Notification,
99 {
100 self.client_sender
101 .send(Message::Notification(Notification::new(
102 N::METHOD.to_string(),
103 params,
104 )))
105 .map_err(|error| anyhow!("Failed to send notification {}: {error}", N::METHOD))
106 }
107
108 pub(crate) fn send_notification_value(
109 &self,
110 method: &str,
111 params: serde_json::Value,
112 ) -> crate::Result<()> {
113 self.client_sender
114 .send(Message::Notification(Notification::new(
115 method.to_owned(),
116 params,
117 )))
118 .map_err(|error| anyhow!("Failed to send notification {method}: {error}"))
119 }
120
121 pub(crate) fn respond<R>(
122 &self,
123 id: &RequestId,
124 result: crate::server::Result<R>,
125 ) -> crate::Result<()>
126 where
127 R: serde::Serialize,
128 {
129 let response = match result {
130 Ok(value) => lsp_server::Response::new_ok(id.clone(), value),
131 Err(crate::server::Error { code, error }) => {
132 lsp_server::Response::new_err(id.clone(), code as i32, error.to_string())
133 }
134 };
135
136 self.main_loop_sender
137 .send(Event::SendResponse(response))
138 .map_err(|error| anyhow!("Failed to queue response {id}: {error}"))
139 }
140
141 pub(crate) fn respond_err(&self, id: RequestId, error: ResponseError) -> crate::Result<()> {
142 self.main_loop_sender
143 .send(Event::SendResponse(lsp_server::Response {
144 id,
145 result: None,
146 error: Some(error),
147 }))
148 .map_err(|send_error| anyhow!("Failed to queue error response: {send_error}"))
149 }
150
151 pub(crate) fn show_message(
152 &self,
153 message: impl Display,
154 message_type: lsp_types::MessageType,
155 ) -> crate::Result<()> {
156 self.send_notification::<lsp_types::notification::ShowMessage>(
157 lsp_types::ShowMessageParams {
158 typ: message_type,
159 message: message.to_string(),
160 },
161 )
162 }
163
164 pub(crate) fn log_message(
165 &self,
166 message: impl Display,
167 message_type: lsp_types::MessageType,
168 ) -> crate::Result<()> {
169 self.send_notification::<lsp_types::notification::LogMessage>(lsp_types::LogMessageParams {
170 typ: message_type,
171 message: message.to_string(),
172 })
173 }
174
175 pub(crate) fn show_error_message(&self, message: impl Display) {
176 if let Err(err) = self.show_message(message, lsp_types::MessageType::ERROR) {
177 tracing::error!("Failed to send error message to client: {err}");
178 }
179 }
180
181 pub(crate) fn cancel(&self, session: &mut Session, id: RequestId) -> crate::Result<()> {
182 let method_name = session.request_queue_mut().incoming_mut().cancel(&id);
183 if let Some(method_name) = method_name {
184 tracing::debug!("Cancelled request id={id} method={method_name}");
185 self.client_sender
186 .send(Message::Response(lsp_server::Response {
187 id,
188 result: None,
189 error: Some(ResponseError {
190 code: ErrorCode::RequestCanceled as i32,
191 message: "request was cancelled by client".to_owned(),
192 data: None,
193 }),
194 }))?;
195 }
196 Ok(())
197 }
198}