lsp_max/service/client/
mod.rs1pub use self::socket::{ClientSocket, RequestStream, ResponseSink};
4
5use std::fmt::{self, Debug, Formatter};
6use std::sync::atomic::{AtomicU32, Ordering};
7use std::sync::Arc;
8use std::task::{Context, Poll};
9
10use futures::channel::mpsc::{self, Sender};
11use futures::future::BoxFuture;
12use futures::sink::SinkExt;
13use tower::Service;
14use tracing::{error, trace};
15
16use self::pending::Pending;
17pub use self::progress::Progress;
18use super::state::{ServerState, State};
19use super::ExitedError;
20use crate::jsonrpc::{self, Error, ErrorCode, Id, Request, Response};
21
22mod lsp_methods;
23mod pending;
24pub mod progress;
25pub mod progress_ext;
26mod socket;
27
28#[cfg(test)]
29mod tests;
30
31struct ClientInner {
32 tx: Sender<Request>,
33 request_id: AtomicU32,
34 pending: Arc<Pending>,
35 state: Arc<ServerState>,
36}
37
38#[derive(Clone)]
40pub struct Client {
41 inner: Arc<ClientInner>,
42}
43
44impl Client {
45 pub(super) fn new(state: Arc<ServerState>) -> (Self, ClientSocket) {
46 let (tx, rx) = mpsc::channel(1);
47 let pending = Arc::new(Pending::new());
48
49 let client = Client {
50 inner: Arc::new(ClientInner {
51 tx,
52 request_id: AtomicU32::new(0),
53 pending: pending.clone(),
54 state: state.clone(),
55 }),
56 };
57
58 (client, ClientSocket { rx, pending, state })
59 }
60
61 pub(crate) fn close(&self) {
63 self.inner.tx.clone().close_channel();
64 }
65}
66
67impl Client {
68 pub async fn send_notification<N>(&self, params: N::Params)
70 where
71 N: lsp_types_max::notification::Notification,
72 {
73 if let State::Initialized | State::ShutDown = self.inner.state.get() {
74 self.send_notification_unchecked::<N>(params).await;
75 } else {
76 let msg = Request::from_notification::<N>(params);
77 trace!("server not initialized, supressing message: {}", msg);
78 }
79 }
80
81 async fn send_notification_unchecked<N>(&self, params: N::Params)
82 where
83 N: lsp_types_max::notification::Notification,
84 {
85 let request = Request::from_notification::<N>(params);
86 if self.clone().call(request).await.is_err() {
87 error!("failed to send notification");
88 }
89 }
90
91 pub async fn send_request<R>(&self, params: R::Params) -> jsonrpc::Result<R::Result>
93 where
94 R: lsp_types_max::request::Request,
95 {
96 if let State::Initialized | State::ShutDown = self.inner.state.get() {
97 self.send_request_unchecked::<R>(params).await
98 } else {
99 let id = self.inner.request_id.load(Ordering::SeqCst) as i64 + 1;
100 let msg = Request::from_request::<R>(id.into(), params);
101 trace!("server not initialized, supressing message: {}", msg);
102 Err(jsonrpc::not_initialized_error())
103 }
104 }
105
106 async fn send_request_unchecked<R>(&self, params: R::Params) -> jsonrpc::Result<R::Result>
107 where
108 R: lsp_types_max::request::Request,
109 {
110 let id = self.next_request_id();
111 let request = Request::from_request::<R>(id, params);
112
113 let response = match self.clone().call(request).await {
114 Ok(Some(response)) => response,
115 Ok(None) | Err(_) => return Err(Error::internal_error()),
116 };
117
118 let (_, result) = response.into_parts();
119 result.and_then(|v| {
120 serde_json::from_value(v).map_err(|e| Error {
121 code: ErrorCode::ParseError,
122 message: e.to_string().into(),
123 data: None,
124 })
125 })
126 }
127}
128
129impl Client {
130 pub fn next_request_id(&self) -> Id {
132 let num = self.inner.request_id.fetch_add(1, Ordering::Relaxed);
133 Id::Number(num as i64)
134 }
135}
136
137impl Debug for Client {
138 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
139 f.debug_struct("Client")
140 .field("tx", &self.inner.tx)
141 .field("pending", &self.inner.pending)
142 .field("request_id", &self.inner.request_id)
143 .field("state", &self.inner.state)
144 .finish()
145 }
146}
147
148impl Service<Request> for Client {
149 type Response = Option<Response>;
150 type Error = ExitedError;
151 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
152
153 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
154 let state = self.inner.state.clone();
155 self.inner.tx.clone().poll_ready(cx).map_err(move |_| {
156 let code = if state.get() == State::Exited {
157 state.get_exit_code()
158 } else {
159 1
160 };
161 ExitedError(code)
162 })
163 }
164
165 fn call(&mut self, req: Request) -> Self::Future {
166 let mut tx = self.inner.tx.clone();
167 let response_waiter = req.id().cloned().map(|id| self.inner.pending.wait(id));
168 let state = self.inner.state.clone();
169
170 Box::pin(async move {
171 if tx.send(req).await.is_err() {
172 let code = if state.get() == State::Exited {
173 state.get_exit_code()
174 } else {
175 1
176 };
177 return Err(ExitedError(code));
178 }
179
180 match response_waiter {
181 Some(fut) => Ok(Some(fut.await)),
182 None => Ok(None),
183 }
184 })
185 }
186}
187
188#[derive(Debug)]
189struct FoldingRangeRefresh;
190
191impl lsp_types_max::request::Request for FoldingRangeRefresh {
192 type Params = ();
193 type Result = ();
194 const METHOD: &'static str = "workspace/foldingRange/refresh";
195}