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}