sync_lsp/connection/mod.rs
1use std::io::Error;
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut};
4use jsonrpc::RpcError;
5
6pub use jsonrpc::ErrorCode;
7pub use transport::Transport;
8pub(crate) use jsonrpc::{Callback, EmptyParams, RpcConnection, CancelParams};
9pub(crate) use rpc::Endpoint;
10
11use crate::TypeProvider;
12use crate::lifecycle::LifecycleService;
13use crate::lifecycle::initialize::ClientCapabilities;
14use crate::text_document::TextDocumentService;
15use crate::window::WindowService;
16use crate::workspace::WorkspaceService;
17
18use self::jsonrpc::{RpcConnectionImpl, MessageID};
19
20mod rpc;
21mod jsonrpc;
22mod transport;
23mod lifecycle;
24
25/// This struct is a wrapper around the server state, which provides
26/// type via the [`TypeProvider`] trait. It also contains the connection
27/// to the client and all callbacks for the different endpoints.
28///
29/// # Example
30/// ```
31/// use sync_lsp::{Transport, TypeProvider, Server};
32///
33/// // For this example, we don't need any state.
34/// struct MyServerState;
35///
36/// // This macro provides default implementations for all required types.
37/// #[sync_lsp::type_provider]
38/// impl TypeProvider for MyServerState {}
39///
40/// fn main() {
41/// let transport = Transport::stdio();
42/// let mut server = Server::new(MyServerState, transport);
43///
44/// //Callbacks can be registered here via the `server.on_*` methods.
45/// //Note that callbacks may also be registered after the server has been started.
46///
47/// server.serve().unwrap();
48/// }
49/// ```
50pub struct Server<T: TypeProvider> {
51 pub connection: Connection<T>,
52 state: T,
53 process_id: Option<u32>,
54 root_uri: Option<String>,
55 initialization_options: Option<T::InitializeOptions>,
56
57 lifecycle: LifecycleService<T>,
58 pub(crate) window: WindowService<T>,
59 pub(crate) text_document: TextDocumentService<T>,
60 pub(crate) workspace: WorkspaceService<T>,
61 pub(crate) capabilities: ClientCapabilities,
62}
63
64/// This struct may be used to send notifications and requests to the client.
65/// The connection to the client can be obtained in one of two way:
66/// * By calling [`Server::split`] and taking the first element of the tuple
67/// * By referencing the `connection` field of the [`Server`] struct.
68///
69/// # Example
70/// ```
71/// use sync_lsp::{Transport, TypeProvider, Server};
72///
73/// // For this example, we don't need any state.
74/// struct MyServerState;
75///
76// This macro provides default implementations for all required types.
77/// #[sync_lsp::type_provider]
78/// impl TypeProvider for MyServerState {}
79///
80/// fn main() {
81/// let transport = Transport::stdio();
82/// let mut server = Server::new(MyServerState, transport);
83/// server.on_open(|server, _| {
84/// #[allow(unused)]
85/// let (connection, state) = server.split();
86/// });
87/// server.serve().unwrap();
88/// }
89/// ```
90pub struct Connection<T: TypeProvider> {
91 transport: Transport,
92 error: Option<RpcError>,
93 current_request: Option<MessageID>,
94 marker: PhantomData<T>
95}
96
97impl<T: TypeProvider> Server<T> {
98 /// Creates a new server with the given state and transport.
99 pub fn new(state: T, transport: Transport) -> Server<T> {
100 Server {
101 state,
102 connection: Connection::new(transport),
103 process_id: None,
104 root_uri: None,
105 initialization_options: None,
106 lifecycle: Default::default(),
107 window: Default::default(),
108 text_document: Default::default(),
109 workspace: Default::default(),
110 capabilities: ClientCapabilities::default()
111 }
112 }
113
114 /// Returns the process id of the server, if one is provided by the client.
115 pub fn process_id(&self) -> Option<u32> {
116 self.process_id
117 }
118
119 /// Returns the root uri of the workspace, if one is provided by the client.
120 pub fn root_uri(&self) -> Option<&str> {
121 self.root_uri.as_ref().map(|uri| uri.as_str())
122 }
123
124 /// Returns the initialization options as defined in [`TypeProvider::InitializeOptions`] if available and parsed correctly.
125 pub fn initialization_options(&self) -> Option<&T::InitializeOptions> {
126 self.initialization_options.as_ref()
127 }
128
129 /// Splits the server into its connection and state.
130 pub fn split(&mut self) -> (&mut Connection<T>, &mut T) {
131 (&mut self.connection, &mut self.state)
132 }
133
134 /// Starts the server. This will block the current thread.
135 /// Until there is either an error or the client sends a shutdown request.
136 pub fn serve(self) -> Result<(), Error> {
137 RpcConnectionImpl::serve(self)
138 }
139}
140
141impl<T: TypeProvider> Connection<T> {
142 fn new(transport: Transport) -> Connection<T> {
143 Connection {
144 transport,
145 error: None,
146 current_request: None,
147 marker: PhantomData
148 }
149 }
150
151 /// This will send a error if called from a request and log it,
152 /// if called from a notification. For usability reasons it also
153 /// returns a default value of the type `R`, which makes it possible
154 /// to write
155 /// ```
156 /// return self.error(ErrorCode::InvalidParams, "Test Error".to_string());
157 /// ```
158 /// instead of
159 /// ```
160 /// self.error(ErrorCode::InvalidParams, "Test Error".to_string());
161 /// return SomeType::default();
162 /// ```
163 pub fn error<R: Default>(&mut self, code: ErrorCode, message: String) -> R {
164 self.error = Some(RpcError {
165 code,
166 message
167 });
168 R::default()
169 }
170
171 /// Check whether the current request has been cancelled.
172 /// If this method has been called in a cancelled request,
173 /// a error with code [`ErrorCode::RequestCancelled`] will be returned to the client,
174 /// regardless of what the request handler returns.
175 ///
176 /// # Example
177 /// ```
178 /// use sync_lsp::{Transport, TypeProvider, Server, text_document::completion::CompletionList};
179 ///
180 /// // For this example, we don't need any state.
181 /// struct MyServerState;
182 ///
183 /// // This macro provides default implementations for all required types.
184 /// #[sync_lsp::type_provider]
185 /// impl TypeProvider for MyServerState {}
186 ///
187 /// fn main() {
188 /// let transport = Transport::stdio();
189 /// let mut server = Server::new(MyServerState, transport);
190 ///
191 /// server.on_completion(|server, _, _| {
192 /// let result = Vec::new();
193 ///
194 /// while !server.connection.cancelled() {
195 /// // Do expensive work here
196 /// }
197 ///
198 /// CompletionList {
199 /// is_incomplete: false,
200 /// items: result
201 /// }
202 /// });
203 ///
204 /// server.serve().unwrap();
205 /// }
206 /// ```
207 pub fn cancelled(&mut self) -> bool {
208 let Some(id) = self.current_request.clone() else { return false; };
209 while let Some(params) = self.peek_notification::<CancelParams>("$/cancelRequest") {
210 if params.id == id {
211 self.current_request = self.error(
212 ErrorCode::RequestCancelled,
213 "Request cancelled".to_string()
214 );
215 return true;
216 }
217 }
218 false
219 }
220}
221
222impl<T: TypeProvider> Deref for Server<T> {
223 type Target = T;
224
225 fn deref(&self) -> &Self::Target {
226 &self.state
227 }
228}
229
230impl<T: TypeProvider> DerefMut for Server<T> {
231 fn deref_mut(&mut self) -> &mut Self::Target {
232 &mut self.state
233 }
234}