lspower/
lib.rs

1//! Language Server Protocol (LSP) server abstraction for [Tower].
2//!
3//! [Tower]: https://github.com/tower-rs/tower
4
5#![deny(missing_debug_implementations)]
6#![deny(missing_docs)]
7#![forbid(unsafe_code)]
8
9pub extern crate lsp;
10
11mod client;
12mod codec;
13pub mod jsonrpc;
14mod server;
15mod service;
16mod transport;
17
18pub use self::{
19    client::{CancellationToken, Client, TokenCanceller},
20    service::{ExitedError, LspService, MessageStream},
21    transport::Server,
22};
23pub use async_trait::async_trait;
24use auto_impl::auto_impl;
25use lspower_macros::rpc;
26
27/// Trait implemented by language server backends.
28///
29/// This interface allows servers adhering to the [Language Server Protocol] to be implemented in a
30/// safe and easily testable way without exposing the low-level implementation details.
31///
32/// [Language Server Protocol]: https://microsoft.github.io/language-server-protocol/
33#[rpc]
34#[async_trait]
35#[auto_impl(Arc, Box)]
36pub trait LanguageServer: Send + Sync + 'static {
37    /// The [`initialize`] request is the first request sent from the client to the server.
38    ///
39    /// [`initialize`]: https://microsoft.github.io/language-server-protocol/specification#initialize
40    ///
41    /// This method is guaranteed to only execute once. If the client sends this request to the
42    /// server again, the server will respond with JSON-RPC error code `-32600` (invalid request).
43    #[rpc(name = "initialize")]
44    async fn initialize(&self, params: lsp::InitializeParams) -> crate::jsonrpc::Result<lsp::InitializeResult>;
45
46    /// The [`initialized`] notification is sent from the client to the server after the client
47    /// received the result of the initialize request but before the client sends anything else.
48    ///
49    /// The server can use the `initialized` notification for example to dynamically register
50    /// capabilities with the client.
51    ///
52    /// [`initialized`]: https://microsoft.github.io/language-server-protocol/specification#initialized
53    #[rpc(name = "initialized")]
54    async fn initialized(&self, _params: lsp::InitializedParams) {
55    }
56
57    /// The [`shutdown`] request asks the server to gracefully shut down, but to not exit.
58    ///
59    /// This request is often later followed by an [`exit`] notification, which will cause the
60    /// server to exit immediately.
61    ///
62    /// [`shutdown`]: https://microsoft.github.io/language-server-protocol/specification#shutdown
63    /// [`exit`]: https://microsoft.github.io/language-server-protocol/specification#exit
64    ///
65    /// This method is guaranteed to only execute once. If the client sends this request to the
66    /// server again, the server will respond with JSON-RPC error code `-32600` (invalid request).
67    #[rpc(name = "shutdown")]
68    async fn shutdown(&self) -> crate::jsonrpc::Result<()>;
69
70    /// The [`workspace/didChangeWorkspaceFolders`] notification is sent from the client to the
71    /// server to inform about workspace folder configuration changes.
72    ///
73    /// The notification is sent by default if both of these boolean fields were set to `true` in
74    /// the [`initialize`] method:
75    ///
76    /// * `InitializeParams::capabilities::workspace::workspace_folders`
77    /// * `InitializeResult::capabilities::workspace::workspace_folders::supported`
78    ///
79    /// This notification is also sent if the server has registered itself to receive this
80    /// notification.
81    ///
82    /// [`workspace/didChangeWorkspaceFolders`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWorkspaceFolders
83    /// [`initialize`]: #tymethod.initialize
84    #[rpc(name = "workspace/didChangeWorkspaceFolders")]
85    async fn did_change_workspace_folders(&self, _params: lsp::DidChangeWorkspaceFoldersParams) {
86        log::warn!("Got a workspace/didChangeWorkspaceFolders notification, but it is not implemented");
87    }
88
89    /// The [`workspace/didChangeConfiguration`] notification is sent from the client to the server
90    /// to signal the change of configuration settings.
91    ///
92    /// [`workspace/didChangeConfiguration`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration
93    #[rpc(name = "workspace/didChangeConfiguration")]
94    async fn did_change_configuration(&self, _params: lsp::DidChangeConfigurationParams) {
95        log::warn!("Got a workspace/didChangeConfiguration notification, but it is not implemented");
96    }
97
98    /// The [`workspace/didChangeWatchedFiles`] notification is sent from the client to the server
99    /// when the client detects changes to files watched by the language client.
100    ///
101    /// It is recommended that servers register for these file events using the registration
102    /// mechanism. This can be done here or in the [`initialized`] method using
103    /// `Client::register_capability()`.
104    ///
105    /// [`workspace/didChangeWatchedFiles`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration
106    /// [`initialized`]: #tymethod.initialized
107    #[rpc(name = "workspace/didChangeWatchedFiles")]
108    async fn did_change_watched_files(&self, _params: lsp::DidChangeWatchedFilesParams) {
109        log::warn!("Got a workspace/didChangeWatchedFiles notification, but it is not implemented");
110    }
111
112    /// The [`workspace/symbol`] request is sent from the client to the server to list project-wide
113    /// symbols matching the given query string.
114    ///
115    /// [`workspace/symbol`]: https://microsoft.github.io/language-server-protocol/specification#workspace_symbol
116    #[rpc(name = "workspace/symbol")]
117    async fn symbol(
118        &self,
119        _params: lsp::WorkspaceSymbolParams,
120    ) -> crate::jsonrpc::Result<Option<Vec<lsp::SymbolInformation>>> {
121        log::error!("Got a workspace/symbol request, but it is not implemented");
122        Err(crate::jsonrpc::Error::method_not_found())
123    }
124
125    /// The [`workspace/executeCommand`] request is sent from the client to the server to trigger
126    /// command execution on the server.
127    ///
128    /// In most cases, the server creates a `WorkspaceEdit` structure and applies the changes to
129    /// the workspace using `Client::apply_edit()` before returning from this function.
130    ///
131    /// [`workspace/executeCommand`]: https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand
132    #[rpc(name = "workspace/executeCommand")]
133    async fn execute_command(
134        &self,
135        _params: lsp::ExecuteCommandParams,
136    ) -> crate::jsonrpc::Result<Option<serde_json::Value>> {
137        log::error!("Got a workspace/executeCommand request, but it is not implemented");
138        Err(crate::jsonrpc::Error::method_not_found())
139    }
140
141    /// The [`textDocument/didOpen`] notification is sent from the client to the server to signal
142    /// that a new text document has been opened by the client.
143    ///
144    /// The document's truth is now managed by the client and the server must not try to read the
145    /// document’s truth using the document's URI. "Open" in this sense means it is managed by the
146    /// client. It doesn't necessarily mean that its content is presented in an editor.
147    ///
148    /// [`textDocument/didOpen`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_didOpen
149    #[rpc(name = "textDocument/didOpen")]
150    async fn did_open(&self, _params: lsp::DidOpenTextDocumentParams) {
151        log::warn!("Got a textDocument/didOpen notification, but it is not implemented");
152    }
153
154    /// The [`textDocument/didChange`] notification is sent from the client to the server to signal
155    /// changes to a text document.
156    ///
157    /// This notification will contain a distinct version tag and a list of edits made to the
158    /// document for the server to interpret.
159    ///
160    /// [`textDocument/didChange`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_didChange
161    #[rpc(name = "textDocument/didChange")]
162    async fn did_change(&self, _params: lsp::DidChangeTextDocumentParams) {
163        log::warn!("Got a textDocument/didChange notification, but it is not implemented");
164    }
165
166    /// The [`textDocument/willSave`] notification is sent from the client to the server before the
167    /// document is actually saved.
168    ///
169    /// [`textDocument/willSave`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_willSave
170    #[rpc(name = "textDocument/willSave")]
171    async fn will_save(&self, _params: lsp::WillSaveTextDocumentParams) {
172        log::warn!("Got a textDocument/willSave notification, but it is not implemented");
173    }
174
175    /// The [`textDocument/willSaveWaitUntil`] request is sent from the client to the server before
176    /// the document is actually saved.
177    ///
178    /// The request can return an array of `TextEdit`s which will be applied to the text document
179    /// before it is saved.
180    ///
181    /// Please note that clients might drop results if computing the text edits took too long or if
182    /// a server constantly fails on this request. This is done to keep the save fast and reliable.
183    #[rpc(name = "textDocument/willSaveWaitUntil")]
184    async fn will_save_wait_until(
185        &self,
186        _params: lsp::WillSaveTextDocumentParams,
187    ) -> crate::jsonrpc::Result<Option<Vec<lsp::TextEdit>>> {
188        log::error!("Got a textDocument/willSaveWaitUntil request, but it is not implemented");
189        Err(crate::jsonrpc::Error::method_not_found())
190    }
191
192    /// The [`textDocument/didSave`] notification is sent from the client to the server when the
193    /// document was saved in the client.
194    ///
195    /// [`textDocument/didSave`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_didSave
196    #[rpc(name = "textDocument/didSave")]
197    async fn did_save(&self, _params: lsp::DidSaveTextDocumentParams) {
198        log::warn!("Got a textDocument/didSave notification, but it is not implemented");
199    }
200
201    /// The [`textDocument/didClose`] notification is sent from the client to the server when the
202    /// document got closed in the client.
203    ///
204    /// The document's truth now exists where the document's URI points to (e.g. if the document's
205    /// URI is a file URI, the truth now exists on disk).
206    ///
207    /// [`textDocument/didClose`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_didClose
208    #[rpc(name = "textDocument/didClose")]
209    async fn did_close(&self, _params: lsp::DidCloseTextDocumentParams) {
210        log::warn!("Got a textDocument/didClose notification, but it is not implemented");
211    }
212
213    /// The [`textDocument/completion`] request is sent from the client to the server to compute
214    /// completion items at a given cursor position.
215    ///
216    /// If computing full completion items is expensive, servers can additionally provide a handler
217    /// for the completion item resolve request (`completionItem/resolve`). This request is sent
218    /// when a completion item is selected in the user interface.
219    ///
220    /// [`textDocument/completion`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_completion
221    #[rpc(name = "textDocument/completion")]
222    async fn completion(
223        &self,
224        _params: lsp::CompletionParams,
225    ) -> crate::jsonrpc::Result<Option<lsp::CompletionResponse>> {
226        log::error!("Got a textDocument/completion request, but it is not implemented");
227        Err(crate::jsonrpc::Error::method_not_found())
228    }
229
230    /// The [`completionItem/resolve`] request is sent from the client to the server to resolve
231    /// additional information for a given completion item.
232    ///
233    /// [`completionItem/resolve`]: https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve
234    #[rpc(name = "completionItem/resolve")]
235    async fn completion_resolve(&self, _params: lsp::CompletionItem) -> crate::jsonrpc::Result<lsp::CompletionItem> {
236        log::error!("Got a completionItem/resolve request, but it is not implemented");
237        Err(crate::jsonrpc::Error::method_not_found())
238    }
239
240    /// The [`textDocument/hover`] request asks the server for hover information at a given text
241    /// document position.
242    ///
243    /// Such hover information typically includes type signature information and inline
244    /// documentation for the symbol at the given text document position.
245    ///
246    /// [`textDocument/hover`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_hover
247    #[rpc(name = "textDocument/hover")]
248    async fn hover(&self, _params: lsp::HoverParams) -> crate::jsonrpc::Result<Option<lsp::Hover>> {
249        log::error!("Got a textDocument/hover request, but it is not implemented");
250        Err(crate::jsonrpc::Error::method_not_found())
251    }
252
253    /// The [`textDocument/signatureHelp`] request is sent from the client to the server to request
254    /// signature information at a given cursor position.
255    ///
256    /// [`textDocument/signatureHelp`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp
257    #[rpc(name = "textDocument/signatureHelp")]
258    async fn signature_help(
259        &self,
260        _params: lsp::SignatureHelpParams,
261    ) -> crate::jsonrpc::Result<Option<lsp::SignatureHelp>> {
262        log::error!("Got a textDocument/signatureHelp request, but it is not implemented");
263        Err(crate::jsonrpc::Error::method_not_found())
264    }
265
266    /// The [`textDocument/declaration`] request asks the server for the declaration location of a
267    /// symbol at a given text document position.
268    ///
269    /// [`textDocument/declaration`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_declaration
270    ///
271    /// # Compatibility
272    ///
273    /// This request was introduced in specification version 3.14.0.
274    ///
275    /// The [`GotoDefinitionResponse::Link`] return value was introduced in specification version
276    /// 3.14.0 and requires client-side support in order to be used. It can be returned if the
277    /// client set the following field to `true` in the [`initialize`] method:
278    ///
279    /// ```text
280    /// InitializeParams::capabilities::text_document::declaration::link_support
281    /// ```
282    ///
283    /// [`GotoDefinitionResponse::Link`]: https://docs.rs/lsp-types/0.74.0/lsp_types/enum.GotoDefinitionResponse.html#variant.Link
284    /// [`initialize`]: #tymethod.initialize
285    #[rpc(name = "textDocument/declaration")]
286    async fn goto_declaration(
287        &self,
288        _params: lsp::request::GotoDeclarationParams,
289    ) -> crate::jsonrpc::Result<Option<lsp::request::GotoDeclarationResponse>> {
290        log::error!("Got a textDocument/declaration request, but it is not implemented");
291        Err(crate::jsonrpc::Error::method_not_found())
292    }
293
294    /// The [`textDocument/definition`] request asks the server for the definition location of a
295    /// symbol at a given text document position.
296    ///
297    /// [`textDocument/definition`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_definition
298    ///
299    /// # Compatibility
300    ///
301    /// The [`GotoDefinitionResponse::Link`] return value was introduced in specification version
302    /// 3.14.0 and requires client-side support in order to be used. It can be returned if the
303    /// client set the following field to `true` in the [`initialize`] method:
304    ///
305    /// ```text
306    /// InitializeParams::capabilities::text_document::definition::link_support
307    /// ```
308    ///
309    /// [`GotoDefinitionResponse::Link`]: https://docs.rs/lsp-types/0.74.0/lsp_types/enum.GotoDefinitionResponse.html#variant.Link
310    /// [`initialize`]: #tymethod.initialize
311    #[rpc(name = "textDocument/definition")]
312    async fn goto_definition(
313        &self,
314        _params: lsp::GotoDefinitionParams,
315    ) -> crate::jsonrpc::Result<Option<lsp::GotoDefinitionResponse>> {
316        log::error!("Got a textDocument/definition request, but it is not implemented");
317        Err(crate::jsonrpc::Error::method_not_found())
318    }
319
320    /// The [`textDocument/typeDefinition`] request asks the server for the type definition location
321    /// of a symbol at a given text document position.
322    ///
323    /// [`textDocument/typeDefinition`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition
324    ///
325    /// # Compatibility
326    ///
327    /// This request was introduced in specification version 3.6.0.
328    ///
329    /// The [`GotoDefinitionResponse::Link`] return value was introduced in specification version
330    /// 3.14.0 and requires client-side support in order to be used. It can be returned if the
331    /// client set the following field to `true` in the [`initialize`] method:
332    ///
333    /// ```text
334    /// InitializeParams::capabilities::text_document::type_definition::link_support
335    /// ```
336    ///
337    /// [`GotoDefinitionResponse::Link`]: https://docs.rs/lsp-types/0.74.0/lsp_types/enum.GotoDefinitionResponse.html#variant.Link
338    /// [`initialize`]: #tymethod.initialize
339    #[rpc(name = "textDocument/typeDefinition")]
340    async fn goto_type_definition(
341        &self,
342        _params: lsp::request::GotoTypeDefinitionParams,
343    ) -> crate::jsonrpc::Result<Option<lsp::request::GotoTypeDefinitionResponse>> {
344        log::error!("Got a textDocument/typeDefinition request, but it is not implemented");
345        Err(crate::jsonrpc::Error::method_not_found())
346    }
347
348    /// The [`textDocument/implementation`] request is sent from the client to the server to resolve
349    /// the implementation location of a symbol at a given text document position.
350    ///
351    /// [`textDocument/implementation`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_implementation
352    ///
353    /// # Compatibility
354    ///
355    /// This request was introduced in specification version 3.6.0.
356    ///
357    /// The [`GotoImplementationResponse::Link`] return value was introduced in specification
358    /// version 3.14.0 and requires client-side support in order to be used. It can be returned if
359    /// the client set the following field to `true` in the [`initialize`] method:
360    ///
361    /// ```text
362    /// InitializeParams::capabilities::text_document::implementation::link_support
363    /// ```
364    ///
365    /// [`GotoImplementationResponse::Link`]: https://docs.rs/lsp-types/0.74.0/lsp_types/enum.GotoDefinitionResponse.html#variant.Link
366    /// [`initialize`]: #tymethod.initialize
367    #[rpc(name = "textDocument/implementation")]
368    async fn goto_implementation(
369        &self,
370        _params: lsp::request::GotoImplementationParams,
371    ) -> crate::jsonrpc::Result<Option<lsp::request::GotoImplementationResponse>> {
372        log::error!("Got a textDocument/implementation request, but it is not implemented");
373        Err(crate::jsonrpc::Error::method_not_found())
374    }
375
376    /// The [`textDocument/references`] request is sent from the client to the server to resolve
377    /// project-wide references for the symbol denoted by the given text document position.
378    ///
379    /// [`textDocument/references`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_references
380    #[rpc(name = "textDocument/references")]
381    async fn references(&self, _params: lsp::ReferenceParams) -> crate::jsonrpc::Result<Option<Vec<lsp::Location>>> {
382        log::error!("Got a textDocument/references request, but it is not implemented");
383        Err(crate::jsonrpc::Error::method_not_found())
384    }
385
386    /// The [`textDocument/documentHighlight`] request is sent from the client to the server to
387    /// resolve appropriate highlights for a given text document position.
388    ///
389    /// For programming languages, this usually highlights all textual references to the symbol
390    /// scoped to this file.
391    ///
392    /// This request differs slightly from `textDocument/references` in that this one is allowed to
393    /// be more fuzzy.
394    ///
395    /// [`textDocument/documentHighlight`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight
396    #[rpc(name = "textDocument/documentHighlight")]
397    async fn document_highlight(
398        &self,
399        _params: lsp::DocumentHighlightParams,
400    ) -> crate::jsonrpc::Result<Option<Vec<lsp::DocumentHighlight>>> {
401        log::error!("Got a textDocument/documentHighlight request, but it is not implemented");
402        Err(crate::jsonrpc::Error::method_not_found())
403    }
404
405    /// The [`textDocument/documentSymbol`] request is sent from the client to the server to
406    /// retrieve all symbols found in a given text document.
407    ///
408    /// The returned result is either:
409    ///
410    /// * [`DocumentSymbolResponse::Flat`] which is a flat list of all symbols found in a given text
411    ///   document. Then neither the symbol’s location range nor the symbol’s container name should
412    ///   be used to infer a hierarchy.
413    /// * [`DocumentSymbolResponse::Nested`] which is a hierarchy of symbols found in a given text
414    ///   document.
415    ///
416    /// [`textDocument/documentSymbol`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol
417    /// [`DocumentSymbolResponse::Flat`]: https://docs.rs/lsp-types/0.74.0/lsp_types/enum.DocumentSymbolResponse.html#variant.Flat
418    /// [`DocumentSymbolResponse::Nested`]: https://docs.rs/lsp-types/0.74.0/lsp_types/enum.DocumentSymbolResponse.html#variant.Nested
419    #[rpc(name = "textDocument/documentSymbol")]
420    async fn document_symbol(
421        &self,
422        _params: lsp::DocumentSymbolParams,
423    ) -> crate::jsonrpc::Result<Option<lsp::DocumentSymbolResponse>> {
424        log::error!("Got a textDocument/documentSymbol request, but it is not implemented");
425        Err(crate::jsonrpc::Error::method_not_found())
426    }
427
428    /// The [`textDocument/codeAction`] request is sent from the client to the server to compute
429    /// commands for a given text document and range. These commands are typically code fixes to
430    /// either fix problems or to beautify/refactor code.
431    ///
432    /// The result of a [`textDocument/codeAction`] request is an array of `Command` literals which
433    /// are typically presented in the user interface.
434    ///
435    /// To ensure that a server is useful in many clients, the commands specified in a code actions
436    /// should be handled by the server and not by the client (see [`workspace/executeCommand`] and
437    /// `ServerCapabilities::execute_command_provider`). If the client supports providing edits
438    /// with a code action, then the mode should be used.
439    ///
440    /// When the command is selected the server should be contacted again (via the
441    /// [`workspace/executeCommand`] request) to execute the command.
442    ///
443    /// # Compatibility
444    ///
445    /// Since version 3.8.0: support for `CodeAction` literals to enable the following scenarios:
446    ///
447    /// * The ability to directly return a workspace edit from the code action request. This avoids
448    ///   having another server roundtrip to execute an actual code action. However server providers
449    ///   should be aware that if the code action is expensive to compute or the edits are huge it
450    ///   might still be beneficial if the result is simply a command and the actual edit is only
451    ///   computed when needed.
452    ///
453    /// * The ability to group code actions using a kind. Clients are allowed to ignore that
454    ///   information. However it allows them to better group code action for example into
455    ///   corresponding menus (e.g. all refactor code actions into a refactor menu).
456    ///
457    /// [`textDocument/codeAction`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction
458    /// [`workspace/executeCommand`]: https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand
459    #[rpc(name = "textDocument/codeAction")]
460    async fn code_action(
461        &self,
462        _params: lsp::CodeActionParams,
463    ) -> crate::jsonrpc::Result<Option<lsp::CodeActionResponse>> {
464        log::error!("Got a textDocument/codeAction request, but it is not implemented");
465        Err(crate::jsonrpc::Error::method_not_found())
466    }
467
468    /// The [`textDocument/codeLens`] request is sent from the client to the server to compute code
469    /// lenses for a given text document.
470    ///
471    /// [`textDocument/codeLens`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens
472    #[rpc(name = "textDocument/codeLens")]
473    async fn code_lens(&self, _params: lsp::CodeLensParams) -> crate::jsonrpc::Result<Option<Vec<lsp::CodeLens>>> {
474        log::error!("Got a textDocument/codeLens request, but it is not implemented");
475        Err(crate::jsonrpc::Error::method_not_found())
476    }
477
478    /// The [`codeLens/resolve`] request is sent from the client to the server to resolve the
479    /// command for a given code lens item.
480    ///
481    /// [`codeLens/resolve`]: https://microsoft.github.io/language-server-protocol/specification#codeLens_resolve
482    #[rpc(name = "codeLens/resolve")]
483    async fn code_lens_resolve(&self, _params: lsp::CodeLens) -> crate::jsonrpc::Result<lsp::CodeLens> {
484        log::error!("Got a codeLens/resolve request, but it is not implemented");
485        Err(crate::jsonrpc::Error::method_not_found())
486    }
487
488    /// The [`textDocument/documentLink`] request is sent from the client to the server to request
489    /// the location of links in a document.
490    ///
491    /// A document link is a range in a text document that links to an internal or external
492    /// resource, like another text document or a web site.
493    ///
494    /// [`textDocument/documentLink`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_documentLink
495    ///
496    /// # Compatibility
497    ///
498    /// The [`DocumentLink::tooltip`] field was introduced in specification version 3.15.0 and
499    /// requires client-side support in order to be used. It can be returned if the client set the
500    /// following field to `true` in the [`initialize`] method:
501    ///
502    /// ```text
503    /// InitializeParams::capabilities::text_document::document_link::tooltip_support
504    /// ```
505    ///
506    /// [`initialize`]: #tymethod.initialize
507    #[rpc(name = "textDocument/documentLink")]
508    async fn document_link(
509        &self,
510        _params: lsp::DocumentLinkParams,
511    ) -> crate::jsonrpc::Result<Option<Vec<lsp::DocumentLink>>> {
512        log::error!("Got a textDocument/documentLink request, but it is not implemented");
513        Err(crate::jsonrpc::Error::method_not_found())
514    }
515
516    /// The [`documentLink/resolve`] request is sent from the client to the server to resolve the
517    /// target of a given document link.
518    ///
519    /// A document link is a range in a text document that links to an internal or external
520    /// resource, like another text document or a web site.
521    ///
522    /// [`documentLink/resolve`]: https://microsoft.github.io/language-server-protocol/specification#documentLink_resolve
523    #[rpc(name = "documentLink/resolve")]
524    async fn document_link_resolve(&self, _params: lsp::DocumentLink) -> crate::jsonrpc::Result<lsp::DocumentLink> {
525        log::error!("Got a documentLink/resolve request, but it is not implemented");
526        Err(crate::jsonrpc::Error::method_not_found())
527    }
528
529    /// The [`textDocument/documentColor`] request is sent from the client to the server to list
530    /// all color references found in a given text document. Along with the range, a color value in
531    /// RGB is returned.
532    ///
533    /// [`textDocument/documentColor`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor
534    ///
535    /// Clients can use the result to decorate color references in an editor. For example:
536    ///
537    /// * Color boxes showing the actual color next to the reference
538    /// * Show a color picker when a color reference is edited
539    ///
540    /// # Compatibility
541    ///
542    /// This request was introduced in specification version 3.6.0.
543    #[rpc(name = "textDocument/documentColor")]
544    async fn document_color(
545        &self,
546        _params: lsp::DocumentColorParams,
547    ) -> crate::jsonrpc::Result<Vec<lsp::ColorInformation>> {
548        log::error!("Got a textDocument/documentColor request, but it is not implemented");
549        Err(crate::jsonrpc::Error::method_not_found())
550    }
551
552    /// The [`textDocument/colorPresentation`] request is sent from the client to the server to
553    /// obtain a list of presentations for a color value at a given location.
554    ///
555    /// Clients can use the result to:
556    ///
557    /// * Modify a color reference
558    /// * Show in a color picker and let users pick one of the presentations
559    ///
560    /// # Compatibility
561    ///
562    /// This request was introduced in specification version 3.6.0.
563    ///
564    /// This request has no special capabilities and registration options since it is sent as a
565    /// resolve request for the [`textDocument/documentColor`] request.
566    ///
567    /// [`textDocument/documentColor`]: #tymethod.document_color
568    #[rpc(name = "textDocument/colorPresentation")]
569    async fn color_presentation(
570        &self,
571        _params: lsp::ColorPresentationParams,
572    ) -> crate::jsonrpc::Result<Vec<lsp::ColorPresentation>> {
573        log::error!("Got a textDocument/colorPresentation request, but it is not implemented");
574        Err(crate::jsonrpc::Error::method_not_found())
575    }
576
577    /// The [`textDocument/formatting`] request is sent from the client to the server to format a
578    /// whole document.
579    ///
580    /// [`textDocument/formatting`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
581    #[rpc(name = "textDocument/formatting")]
582    async fn formatting(
583        &self,
584        _params: lsp::DocumentFormattingParams,
585    ) -> crate::jsonrpc::Result<Option<Vec<lsp::TextEdit>>> {
586        log::error!("Got a textDocument/formatting request, but it is not implemented");
587        Err(crate::jsonrpc::Error::method_not_found())
588    }
589
590    /// The [`textDocument/rangeFormatting`] request is sent from the client to the server to
591    /// format a given range in a document.
592    ///
593    /// [`textDocument/rangeFormatting`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting
594    #[rpc(name = "textDocument/rangeFormatting")]
595    async fn range_formatting(
596        &self,
597        _params: lsp::DocumentRangeFormattingParams,
598    ) -> crate::jsonrpc::Result<Option<Vec<lsp::TextEdit>>> {
599        log::error!("Got a textDocument/rangeFormatting request, but it is not implemented");
600        Err(crate::jsonrpc::Error::method_not_found())
601    }
602
603    /// The [`textDocument/onTypeFormatting`] request is sent from the client to the server to
604    /// format parts of the document during typing.
605    ///
606    /// [`textDocument/onTypeFormatting`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting
607    #[rpc(name = "textDocument/onTypeFormatting")]
608    async fn on_type_formatting(
609        &self,
610        _params: lsp::DocumentOnTypeFormattingParams,
611    ) -> crate::jsonrpc::Result<Option<Vec<lsp::TextEdit>>> {
612        log::error!("Got a textDocument/onTypeFormatting request, but it is not implemented");
613        Err(crate::jsonrpc::Error::method_not_found())
614    }
615
616    /// The [`textDocument/rename`] request is sent from the client to the server to ask the server
617    /// to compute a workspace change so that the client can perform a workspace-wide rename of a
618    /// symbol.
619    ///
620    /// [`textDocument/rename`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_rename
621    #[rpc(name = "textDocument/rename")]
622    async fn rename(&self, _params: lsp::RenameParams) -> crate::jsonrpc::Result<Option<lsp::WorkspaceEdit>> {
623        log::error!("Got a textDocument/rename request, but it is not implemented");
624        Err(crate::jsonrpc::Error::method_not_found())
625    }
626
627    /// The [`textDocument/prepareRename`] request is sent from the client to the server to setup
628    /// and test the validity of a rename operation at a given location.
629    ///
630    /// [`textDocument/prepareRename`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename
631    ///
632    /// # Compatibility
633    ///
634    /// This request was introduced in specification version 3.12.0.
635    #[rpc(name = "textDocument/prepareRename")]
636    async fn prepare_rename(
637        &self,
638        _params: lsp::TextDocumentPositionParams,
639    ) -> crate::jsonrpc::Result<Option<lsp::PrepareRenameResponse>> {
640        log::error!("Got a textDocument/prepareRename request, but it is not implemented");
641        Err(crate::jsonrpc::Error::method_not_found())
642    }
643
644    /// The [`textDocument/foldingRange`] request is sent from the client to the server to return
645    /// all folding ranges found in a given text document.
646    ///
647    /// [`textDocument/foldingRange`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange
648    ///
649    /// # Compatibility
650    ///
651    /// This request was introduced in specification version 3.10.0.
652    #[rpc(name = "textDocument/foldingRange")]
653    async fn folding_range(
654        &self,
655        _params: lsp::FoldingRangeParams,
656    ) -> crate::jsonrpc::Result<Option<Vec<lsp::FoldingRange>>> {
657        log::error!("Got a textDocument/foldingRange request, but it is not implemented");
658        Err(crate::jsonrpc::Error::method_not_found())
659    }
660
661    /// The [`textDocument/selectionRange`] request is sent from the client to the server to return
662    /// suggested selection ranges at an array of given positions. A selection range is a range
663    /// around the cursor position which the user might be interested in selecting.
664    ///
665    /// [`textDocument/selectionRange`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange
666    ///
667    /// A selection range in the return array is for the position in the provided parameters at the
668    /// same index. Therefore `params.positions[i]` must be contained in `result[i].range`.
669    ///
670    /// # Compatibility
671    ///
672    /// This request was introduced in specification version 3.15.0.
673    #[rpc(name = "textDocument/selectionRange")]
674    async fn selection_range(
675        &self,
676        _params: lsp::SelectionRangeParams,
677    ) -> crate::jsonrpc::Result<Option<Vec<lsp::SelectionRange>>> {
678        log::error!("Got a textDocument/selectionRange request, but it is not implemented");
679        Err(crate::jsonrpc::Error::method_not_found())
680    }
681
682    /// [`callHierarchy/incomingCalls`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#callHierarchy_incomingCalls
683    #[rpc(name = "callHierarchy/incomingCalls")]
684    async fn incoming_calls(
685        &self,
686        _params: lsp::CallHierarchyIncomingCallsParams,
687    ) -> crate::jsonrpc::Result<Option<Vec<lsp::CallHierarchyIncomingCall>>> {
688        log::error!("Got a callHierarchy/incomingCalls request, but it is not implemented");
689        Err(crate::jsonrpc::Error::method_not_found())
690    }
691
692    /// [`callHierarchy/outgoingCalls`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#callHierarchy_outgoingCalls
693    #[rpc(name = "callHierarchy/outgoingCalls")]
694    async fn outgoing_calls(
695        &self,
696        _params: lsp::CallHierarchyOutgoingCallsParams,
697    ) -> crate::jsonrpc::Result<Option<Vec<lsp::CallHierarchyOutgoingCall>>> {
698        log::error!("Got a callHierarchy/outgoingCalls request, but it is not implemented");
699        Err(crate::jsonrpc::Error::method_not_found())
700    }
701
702    /// [`textDocument/prepareCallHierarchy`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_prepareCallHierarchy
703    #[rpc(name = "textDocument/prepareCallHierarchy")]
704    async fn prepare_call_hierarchy(
705        &self,
706        _params: lsp::CallHierarchyPrepareParams,
707    ) -> crate::jsonrpc::Result<Option<Vec<lsp::CallHierarchyItem>>> {
708        log::error!("Got a textDocument/prepareCallHierarchy request, but it is not implemented");
709        Err(crate::jsonrpc::Error::method_not_found())
710    }
711
712    /// [`textDocument/semanticTokens/full`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
713    #[rpc(name = "textDocument/semanticTokens/full")]
714    async fn semantic_tokens_full(
715        &self,
716        _params: lsp::SemanticTokensParams,
717    ) -> crate::jsonrpc::Result<Option<lsp::SemanticTokensResult>> {
718        log::error!("Got a textDocument/semanticTokens/full request, but it is not implemented");
719        Err(crate::jsonrpc::Error::method_not_found())
720    }
721
722    /// [`textDocument/semanticTokens/full/delta`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
723    #[rpc(name = "textDocument/semanticTokens/full/delta")]
724    async fn semantic_tokens_full_delta(
725        &self,
726        _params: lsp::SemanticTokensDeltaParams,
727    ) -> crate::jsonrpc::Result<Option<lsp::SemanticTokensFullDeltaResult>> {
728        log::error!("Got a textDocument/semanticTokens/full/delta request, but it is not implemented");
729        Err(crate::jsonrpc::Error::method_not_found())
730    }
731
732    /// [`textDocument/semanticTokens/range`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
733    #[rpc(name = "textDocument/semanticTokens/range")]
734    async fn semantic_tokens_range(
735        &self,
736        _params: lsp::SemanticTokensRangeParams,
737    ) -> crate::jsonrpc::Result<Option<lsp::SemanticTokensRangeResult>> {
738        log::error!("Got a textDocument/semanticTokens/range request, but it is not implemented");
739        Err(crate::jsonrpc::Error::method_not_found())
740    }
741
742    /// [`workspace/semanticTokens/full`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
743    #[rpc(name = "workspace/semanticTokens/refresh")]
744    async fn semantic_tokens_refresh(&self) -> crate::jsonrpc::Result<()> {
745        log::error!("Got a workspace/semanticTokens/refresh request, but it is not implemented");
746        Err(crate::jsonrpc::Error::method_not_found())
747    }
748
749    /// [`codeAction/resolve`]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#codeAction_resolve
750    #[rpc(name = "codeAction/resolve")]
751    async fn code_action_resolve(&self, _params: lsp::CodeAction) -> crate::jsonrpc::Result<lsp::CodeAction> {
752        log::error!("Got a codeAction/resolve request, but it is not implemented");
753        Err(crate::jsonrpc::Error::method_not_found())
754    }
755
756    /// This handler can be used to respond to all requests that are not handled by built in request
757    /// handlers.
758    async fn request_else(
759        &self,
760        method: &str,
761        _params: Option<serde_json::Value>,
762    ) -> crate::jsonrpc::Result<Option<serde_json::Value>> {
763        log::error!(
764            "Got a {} request, but LanguageServer::request_else is not implemented",
765            method
766        );
767        Err(crate::jsonrpc::Error::method_not_found())
768    }
769}
770
771#[cfg(test)]
772mod tests {
773    use super::*;
774    use crate::jsonrpc::{Id, Incoming, Outgoing, Response};
775    use serde_json::json;
776    use std::task::Poll;
777    use tower_test::mock::Spawn;
778
779    #[derive(Debug, Default)]
780    struct Mock;
781
782    #[async_trait]
783    impl crate::LanguageServer for Mock {
784        async fn initialize(&self, _: lsp::InitializeParams) -> crate::jsonrpc::Result<lsp::InitializeResult> {
785            Ok(lsp::InitializeResult::default())
786        }
787
788        async fn shutdown(&self) -> crate::jsonrpc::Result<()> {
789            Ok(())
790        }
791    }
792
793    mod helper {
794        use super::*;
795        use crate::jsonrpc::Incoming;
796        use serde::{de::DeserializeOwned, Serialize};
797        use serde_json::json;
798        use std::task::Poll;
799        use tower_test::mock::Spawn;
800
801        pub(super) async fn initialize(service: &mut Spawn<LspService>) {
802            let params = serde_json::from_value::<lsp::InitializeParams>(json!({ "capabilities": {} })).unwrap();
803            let request: Incoming = request("initialize", params).unwrap();
804            let response =
805                serde_json::from_value(json!({ "jsonrpc": "2.0", "result": { "capabilities": {} }, "id": 1 })).unwrap();
806            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
807            assert_eq!(service.call(request.clone()).await, Ok(Some(response)));
808        }
809
810        pub(super) fn request<I: Serialize, O: DeserializeOwned>(
811            method: &str,
812            params: I,
813        ) -> Result<O, serde_json::Error> {
814            serde_json::from_value(json!({
815                "jsonrpc": "2.0",
816                "method": method,
817                "params": params,
818                "id": 1,
819            }))
820        }
821    }
822
823    #[tokio::test]
824    async fn initialize() {
825        let (service, _) = LspService::new(|_| Mock::default());
826        let mut service = Spawn::new(service);
827
828        helper::initialize(&mut service).await;
829    }
830
831    #[tokio::test]
832    async fn initialized() {
833        let (service, _) = LspService::new(|_| Mock::default());
834        let mut service = Spawn::new(service);
835
836        helper::initialize(&mut service).await;
837
838        let params = lsp::InitializedParams {};
839        let request: Incoming = helper::request("initialized", params).unwrap();
840        assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
841        assert_eq!(service.call(request.clone()).await, Ok(None));
842    }
843
844    #[tokio::test]
845    async fn shutdown() {
846        let (service, _) = LspService::new(|_| Mock::default());
847        let mut service = Spawn::new(service);
848
849        helper::initialize(&mut service).await;
850
851        let request: Incoming = helper::request("shutdown", ()).unwrap();
852        let response = Response::ok(Id::Number(1), json!(null));
853        assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
854        assert_eq!(
855            service.call(request.clone()).await,
856            Ok(Some(Outgoing::Response(response)))
857        );
858    }
859
860    mod call_hierarchy {
861        use super::*;
862        use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
863        use std::task::Poll;
864        use tower_test::mock::Spawn;
865
866        #[tokio::test]
867        async fn incoming_calls() {
868            let (service, _) = LspService::new(|_| Mock::default());
869            let mut service = Spawn::new(service);
870
871            super::helper::initialize(&mut service).await;
872
873            let params = lsp::CallHierarchyIncomingCallsParams {
874                item: lsp::CallHierarchyItem {
875                    name: Default::default(),
876                    kind: lsp::SymbolKind::NULL,
877                    tags: Default::default(),
878                    detail: Default::default(),
879                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
880                    range: Default::default(),
881                    selection_range: Default::default(),
882                    data: Default::default(),
883                },
884                work_done_progress_params: Default::default(),
885                partial_result_params: Default::default(),
886            };
887            let request: Incoming = helper::request("callHierarchy/incomingCalls", params).unwrap();
888            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
889            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
890            assert_eq!(
891                service.call(request.clone()).await,
892                Ok(Some(Outgoing::Response(response)))
893            );
894        }
895
896        #[tokio::test]
897        async fn outgoing_calls() {
898            let (service, _) = LspService::new(|_| Mock::default());
899            let mut service = Spawn::new(service);
900
901            super::helper::initialize(&mut service).await;
902
903            let params = lsp::CallHierarchyOutgoingCallsParams {
904                item: lsp::CallHierarchyItem {
905                    name: Default::default(),
906                    kind: lsp::SymbolKind::NULL,
907                    tags: Default::default(),
908                    detail: Default::default(),
909                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
910                    range: Default::default(),
911                    selection_range: Default::default(),
912                    data: Default::default(),
913                },
914                work_done_progress_params: Default::default(),
915                partial_result_params: Default::default(),
916            };
917            let request: Incoming = helper::request("callHierarchy/outgoingCalls", params).unwrap();
918            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
919            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
920            assert_eq!(
921                service.call(request.clone()).await,
922                Ok(Some(Outgoing::Response(response)))
923            );
924        }
925    }
926
927    mod code_action {
928        use super::*;
929        use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
930        use std::task::Poll;
931        use tower_test::mock::Spawn;
932
933        #[tokio::test]
934        async fn resolve() {
935            let (service, _) = LspService::new(|_| Mock::default());
936            let mut service = Spawn::new(service);
937
938            super::helper::initialize(&mut service).await;
939
940            let params = lsp::CodeAction::default();
941            let request: Incoming = helper::request("codeAction/resolve", params).unwrap();
942            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
943            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
944            assert_eq!(
945                service.call(request.clone()).await,
946                Ok(Some(Outgoing::Response(response)))
947            );
948        }
949    }
950
951    mod completion_item {
952        use super::*;
953        use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
954        use std::task::Poll;
955        use tower_test::mock::Spawn;
956
957        #[tokio::test]
958        async fn resolve() {
959            let (service, _) = LspService::new(|_| Mock::default());
960            let mut service = Spawn::new(service);
961
962            super::helper::initialize(&mut service).await;
963
964            let params = lsp::CompletionItem::default();
965            let request: Incoming = helper::request("completionItem/resolve", params).unwrap();
966            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
967            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
968            assert_eq!(
969                service.call(request.clone()).await,
970                Ok(Some(Outgoing::Response(response)))
971            );
972        }
973    }
974
975    mod text_document {
976        use super::*;
977        use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
978        use std::task::Poll;
979        use tower_test::mock::Spawn;
980
981        mod semantic_tokens {
982            use super::*;
983            use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
984            use std::task::Poll;
985            use tower_test::mock::Spawn;
986
987            mod full {
988                use super::*;
989                use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
990                use std::task::Poll;
991                use tower_test::mock::Spawn;
992
993                #[tokio::test]
994                async fn delta() {
995                    let (service, _) = LspService::new(|_| Mock::default());
996                    let mut service = Spawn::new(service);
997
998                    super::helper::initialize(&mut service).await;
999
1000                    let params = lsp::SemanticTokensDeltaParams {
1001                        work_done_progress_params: Default::default(),
1002                        partial_result_params: Default::default(),
1003                        text_document: lsp::TextDocumentIdentifier {
1004                            uri: lsp::Url::parse("inmemory::///test").unwrap(),
1005                        },
1006                        previous_result_id: Default::default(),
1007                    };
1008                    let request: Incoming = helper::request("textDocument/semanticTokens/full", params).unwrap();
1009                    let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1010                    assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1011                    assert_eq!(
1012                        service.call(request.clone()).await,
1013                        Ok(Some(Outgoing::Response(response)))
1014                    );
1015                }
1016            }
1017
1018            #[tokio::test]
1019            async fn full() {
1020                let (service, _) = LspService::new(|_| Mock::default());
1021                let mut service = Spawn::new(service);
1022
1023                super::helper::initialize(&mut service).await;
1024
1025                let params = lsp::SemanticTokensParams {
1026                    work_done_progress_params: Default::default(),
1027                    partial_result_params: Default::default(),
1028                    text_document: lsp::TextDocumentIdentifier {
1029                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1030                    },
1031                };
1032                let request: Incoming = helper::request("textDocument/semanticTokens/full", params).unwrap();
1033                let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1034                assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1035                assert_eq!(
1036                    service.call(request.clone()).await,
1037                    Ok(Some(Outgoing::Response(response)))
1038                );
1039            }
1040
1041            #[tokio::test]
1042            async fn range() {
1043                let (service, _) = LspService::new(|_| Mock::default());
1044                let mut service = Spawn::new(service);
1045
1046                super::helper::initialize(&mut service).await;
1047
1048                let params = lsp::SemanticTokensRangeParams {
1049                    work_done_progress_params: Default::default(),
1050                    partial_result_params: Default::default(),
1051                    text_document: lsp::TextDocumentIdentifier {
1052                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1053                    },
1054                    range: Default::default(),
1055                };
1056                let request: Incoming = helper::request("textDocument/semanticTokens/range", params).unwrap();
1057                let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1058                assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1059                assert_eq!(
1060                    service.call(request.clone()).await,
1061                    Ok(Some(Outgoing::Response(response)))
1062                );
1063            }
1064
1065            #[tokio::test]
1066            async fn refresh() {
1067                let (service, _) = LspService::new(|_| Mock::default());
1068                let mut service = Spawn::new(service);
1069
1070                super::helper::initialize(&mut service).await;
1071
1072                let request: Incoming = helper::request("textDocument/semanticTokens/refresh", ()).unwrap();
1073                let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1074                assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1075                assert_eq!(
1076                    service.call(request.clone()).await,
1077                    Ok(Some(Outgoing::Response(response)))
1078                );
1079            }
1080        }
1081
1082        #[tokio::test]
1083        async fn code_action() {
1084            let (service, _) = LspService::new(|_| Mock::default());
1085            let mut service = Spawn::new(service);
1086
1087            super::helper::initialize(&mut service).await;
1088
1089            let params = lsp::CodeActionParams {
1090                text_document: lsp::TextDocumentIdentifier {
1091                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1092                },
1093                range: Default::default(),
1094                context: Default::default(),
1095                work_done_progress_params: Default::default(),
1096                partial_result_params: Default::default(),
1097            };
1098            let request: Incoming = helper::request("textDocument/codeAction", params).unwrap();
1099            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1100            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1101            assert_eq!(
1102                service.call(request.clone()).await,
1103                Ok(Some(Outgoing::Response(response)))
1104            );
1105        }
1106
1107        #[tokio::test]
1108        async fn code_lens() {
1109            let (service, _) = LspService::new(|_| Mock::default());
1110            let mut service = Spawn::new(service);
1111
1112            super::helper::initialize(&mut service).await;
1113
1114            let params = lsp::CodeLensParams {
1115                text_document: lsp::TextDocumentIdentifier {
1116                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1117                },
1118                work_done_progress_params: Default::default(),
1119                partial_result_params: Default::default(),
1120            };
1121            let request: Incoming = helper::request("textDocument/codeLens", params).unwrap();
1122            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1123            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1124            assert_eq!(
1125                service.call(request.clone()).await,
1126                Ok(Some(Outgoing::Response(response)))
1127            );
1128        }
1129
1130        #[tokio::test]
1131        async fn code_lens_resolve() {
1132            let (service, _) = LspService::new(|_| Mock::default());
1133            let mut service = Spawn::new(service);
1134
1135            super::helper::initialize(&mut service).await;
1136
1137            let params = lsp::CodeLens {
1138                range: Default::default(),
1139                command: Default::default(),
1140                data: Default::default(),
1141            };
1142            let request: Incoming = helper::request("textDocument/codeLensResolve", params).unwrap();
1143            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1144            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1145            assert_eq!(
1146                service.call(request.clone()).await,
1147                Ok(Some(Outgoing::Response(response)))
1148            );
1149        }
1150
1151        #[tokio::test]
1152        async fn color_presentation() {
1153            let (service, _) = LspService::new(|_| Mock::default());
1154            let mut service = Spawn::new(service);
1155
1156            super::helper::initialize(&mut service).await;
1157
1158            let params = lsp::ColorPresentationParams {
1159                text_document: lsp::TextDocumentIdentifier {
1160                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1161                },
1162                color: lsp::Color {
1163                    red: Default::default(),
1164                    green: Default::default(),
1165                    blue: Default::default(),
1166                    alpha: Default::default(),
1167                },
1168                range: Default::default(),
1169                work_done_progress_params: Default::default(),
1170                partial_result_params: Default::default(),
1171            };
1172            let request: Incoming = helper::request("textDocument/colorPresentation", params).unwrap();
1173            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1174            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1175            assert_eq!(
1176                service.call(request.clone()).await,
1177                Ok(Some(Outgoing::Response(response)))
1178            );
1179        }
1180
1181        #[tokio::test]
1182        async fn completion() {
1183            let (service, _) = LspService::new(|_| Mock::default());
1184            let mut service = Spawn::new(service);
1185
1186            super::helper::initialize(&mut service).await;
1187
1188            let params = lsp::CompletionParams {
1189                text_document_position: lsp::TextDocumentPositionParams {
1190                    text_document: lsp::TextDocumentIdentifier {
1191                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1192                    },
1193                    position: Default::default(),
1194                },
1195                work_done_progress_params: Default::default(),
1196                partial_result_params: Default::default(),
1197                context: Default::default(),
1198            };
1199            let request: Incoming = helper::request("textDocument/completion", params).unwrap();
1200            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1201            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1202            assert_eq!(
1203                service.call(request.clone()).await,
1204                Ok(Some(Outgoing::Response(response)))
1205            );
1206        }
1207
1208        #[tokio::test]
1209        async fn declaration() {
1210            let (service, _) = LspService::new(|_| Mock::default());
1211            let mut service = Spawn::new(service);
1212
1213            super::helper::initialize(&mut service).await;
1214
1215            let params = lsp::request::GotoDeclarationParams {
1216                text_document_position_params: lsp::TextDocumentPositionParams {
1217                    text_document: lsp::TextDocumentIdentifier {
1218                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1219                    },
1220                    position: Default::default(),
1221                },
1222                work_done_progress_params: Default::default(),
1223                partial_result_params: Default::default(),
1224            };
1225            let request: Incoming = helper::request("textDocument/declaration", params).unwrap();
1226            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1227            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1228            assert_eq!(
1229                service.call(request.clone()).await,
1230                Ok(Some(Outgoing::Response(response)))
1231            );
1232        }
1233
1234        #[tokio::test]
1235        async fn definition() {
1236            let (service, _) = LspService::new(|_| Mock::default());
1237            let mut service = Spawn::new(service);
1238
1239            super::helper::initialize(&mut service).await;
1240
1241            let params = lsp::GotoDefinitionParams {
1242                text_document_position_params: lsp::TextDocumentPositionParams {
1243                    text_document: lsp::TextDocumentIdentifier {
1244                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1245                    },
1246                    position: Default::default(),
1247                },
1248                work_done_progress_params: Default::default(),
1249                partial_result_params: Default::default(),
1250            };
1251            let request: Incoming = helper::request("textDocument/definition", params).unwrap();
1252            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1253            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1254            assert_eq!(
1255                service.call(request.clone()).await,
1256                Ok(Some(Outgoing::Response(response)))
1257            );
1258        }
1259
1260        #[tokio::test]
1261        async fn did_change() {
1262            let (service, _) = LspService::new(|_| Mock::default());
1263            let mut service = Spawn::new(service);
1264
1265            super::helper::initialize(&mut service).await;
1266
1267            let params = lsp::DidChangeTextDocumentParams {
1268                text_document: lsp::VersionedTextDocumentIdentifier {
1269                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1270                    version: Default::default(),
1271                },
1272                content_changes: Default::default(),
1273            };
1274            let request: Incoming = helper::request("textDocument/didChange", params).unwrap();
1275            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1276            assert_eq!(service.call(request.clone()).await, Ok(None));
1277        }
1278
1279        #[tokio::test]
1280        async fn did_close() {
1281            let (service, _) = LspService::new(|_| Mock::default());
1282            let mut service = Spawn::new(service);
1283
1284            super::helper::initialize(&mut service).await;
1285
1286            let params = lsp::DidCloseTextDocumentParams {
1287                text_document: lsp::TextDocumentIdentifier {
1288                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1289                },
1290            };
1291            let request: Incoming = helper::request("textDocument/didClose", params).unwrap();
1292            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1293            assert_eq!(service.call(request.clone()).await, Ok(None));
1294        }
1295
1296        #[tokio::test]
1297        async fn did_open() {
1298            let (service, _) = LspService::new(|_| Mock::default());
1299            let mut service = Spawn::new(service);
1300
1301            super::helper::initialize(&mut service).await;
1302
1303            let params = lsp::DidOpenTextDocumentParams {
1304                text_document: lsp::TextDocumentItem {
1305                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1306                    language_id: Default::default(),
1307                    version: Default::default(),
1308                    text: Default::default(),
1309                },
1310            };
1311            let request: Incoming = helper::request("textDocument/didOpen", params).unwrap();
1312            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1313            assert_eq!(service.call(request.clone()).await, Ok(None));
1314        }
1315
1316        #[tokio::test]
1317        async fn did_save() {
1318            let (service, _) = LspService::new(|_| Mock::default());
1319            let mut service = Spawn::new(service);
1320
1321            super::helper::initialize(&mut service).await;
1322
1323            let params = lsp::DidSaveTextDocumentParams {
1324                text_document: lsp::TextDocumentIdentifier {
1325                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1326                },
1327                text: Default::default(),
1328            };
1329            let request: Incoming = helper::request("textDocument/didSave", params).unwrap();
1330            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1331            assert_eq!(service.call(request.clone()).await, Ok(None));
1332        }
1333
1334        #[tokio::test]
1335        async fn document_color() {
1336            let (service, _) = LspService::new(|_| Mock::default());
1337            let mut service = Spawn::new(service);
1338
1339            super::helper::initialize(&mut service).await;
1340
1341            let params = lsp::DocumentColorParams {
1342                text_document: lsp::TextDocumentIdentifier {
1343                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1344                },
1345                work_done_progress_params: Default::default(),
1346                partial_result_params: Default::default(),
1347            };
1348            let request: Incoming = helper::request("textDocument/documentColor", params).unwrap();
1349            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1350            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1351            assert_eq!(
1352                service.call(request.clone()).await,
1353                Ok(Some(Outgoing::Response(response)))
1354            );
1355        }
1356
1357        #[tokio::test]
1358        async fn document_highlight() {
1359            let (service, _) = LspService::new(|_| Mock::default());
1360            let mut service = Spawn::new(service);
1361
1362            super::helper::initialize(&mut service).await;
1363
1364            let params = lsp::DocumentHighlightParams {
1365                text_document_position_params: lsp::TextDocumentPositionParams {
1366                    text_document: lsp::TextDocumentIdentifier {
1367                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1368                    },
1369                    position: Default::default(),
1370                },
1371                work_done_progress_params: Default::default(),
1372                partial_result_params: Default::default(),
1373            };
1374            let request: Incoming = helper::request("textDocument/documentHighlight", params).unwrap();
1375            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1376            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1377            assert_eq!(
1378                service.call(request.clone()).await,
1379                Ok(Some(Outgoing::Response(response)))
1380            );
1381        }
1382
1383        #[tokio::test]
1384        async fn document_link() {
1385            let (service, _) = LspService::new(|_| Mock::default());
1386            let mut service = Spawn::new(service);
1387
1388            super::helper::initialize(&mut service).await;
1389
1390            let params = lsp::DocumentLinkParams {
1391                text_document: lsp::TextDocumentIdentifier {
1392                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1393                },
1394                work_done_progress_params: Default::default(),
1395                partial_result_params: Default::default(),
1396            };
1397            let request: Incoming = helper::request("textDocument/documentLink", params).unwrap();
1398            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1399            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1400            assert_eq!(
1401                service.call(request.clone()).await,
1402                Ok(Some(Outgoing::Response(response)))
1403            );
1404        }
1405
1406        #[tokio::test]
1407        async fn document_link_resolve() {
1408            let (service, _) = LspService::new(|_| Mock::default());
1409            let mut service = Spawn::new(service);
1410
1411            super::helper::initialize(&mut service).await;
1412
1413            let params = lsp::DocumentLink {
1414                range: Default::default(),
1415                target: Default::default(),
1416                tooltip: Default::default(),
1417                data: Default::default(),
1418            };
1419            let request: Incoming = helper::request("textDocument/documentLinkResolve", params).unwrap();
1420            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1421            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1422            assert_eq!(
1423                service.call(request.clone()).await,
1424                Ok(Some(Outgoing::Response(response)))
1425            );
1426        }
1427
1428        #[tokio::test]
1429        async fn document_symbol() {
1430            let (service, _) = LspService::new(|_| Mock::default());
1431            let mut service = Spawn::new(service);
1432
1433            super::helper::initialize(&mut service).await;
1434
1435            let params = lsp::DocumentSymbolParams {
1436                text_document: lsp::TextDocumentIdentifier {
1437                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1438                },
1439                work_done_progress_params: Default::default(),
1440                partial_result_params: Default::default(),
1441            };
1442            let request: Incoming = helper::request("textDocument/documentSymbol", params).unwrap();
1443            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1444            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1445            assert_eq!(
1446                service.call(request.clone()).await,
1447                Ok(Some(Outgoing::Response(response)))
1448            );
1449        }
1450
1451        #[tokio::test]
1452        async fn folding_range() {
1453            let (service, _) = LspService::new(|_| Mock::default());
1454            let mut service = Spawn::new(service);
1455
1456            super::helper::initialize(&mut service).await;
1457
1458            let params = lsp::FoldingRangeParams {
1459                text_document: lsp::TextDocumentIdentifier {
1460                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1461                },
1462                work_done_progress_params: Default::default(),
1463                partial_result_params: Default::default(),
1464            };
1465            let request: Incoming = helper::request("textDocument/foldingRange", params).unwrap();
1466            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1467            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1468            assert_eq!(
1469                service.call(request.clone()).await,
1470                Ok(Some(Outgoing::Response(response)))
1471            );
1472        }
1473
1474        #[tokio::test]
1475        async fn formatting() {
1476            let (service, _) = LspService::new(|_| Mock::default());
1477            let mut service = Spawn::new(service);
1478
1479            super::helper::initialize(&mut service).await;
1480
1481            let params = lsp::DocumentFormattingParams {
1482                text_document: lsp::TextDocumentIdentifier {
1483                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1484                },
1485                options: Default::default(),
1486                work_done_progress_params: Default::default(),
1487            };
1488            let request: Incoming = helper::request("textDocument/formatting", params).unwrap();
1489            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1490            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1491            assert_eq!(
1492                service.call(request.clone()).await,
1493                Ok(Some(Outgoing::Response(response)))
1494            );
1495        }
1496
1497        #[tokio::test]
1498        async fn hover() {
1499            let (service, _) = LspService::new(|_| Mock::default());
1500            let mut service = Spawn::new(service);
1501
1502            super::helper::initialize(&mut service).await;
1503
1504            let params = lsp::HoverParams {
1505                text_document_position_params: lsp::TextDocumentPositionParams {
1506                    text_document: lsp::TextDocumentIdentifier {
1507                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1508                    },
1509                    position: Default::default(),
1510                },
1511                work_done_progress_params: Default::default(),
1512            };
1513            let request: Incoming = helper::request("textDocument/hover", params).unwrap();
1514            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1515            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1516            assert_eq!(
1517                service.call(request.clone()).await,
1518                Ok(Some(Outgoing::Response(response)))
1519            );
1520        }
1521
1522        #[tokio::test]
1523        async fn implementation() {
1524            let (service, _) = LspService::new(|_| Mock::default());
1525            let mut service = Spawn::new(service);
1526
1527            super::helper::initialize(&mut service).await;
1528
1529            let params = lsp::request::GotoImplementationParams {
1530                text_document_position_params: lsp::TextDocumentPositionParams {
1531                    text_document: lsp::TextDocumentIdentifier {
1532                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1533                    },
1534                    position: Default::default(),
1535                },
1536                work_done_progress_params: Default::default(),
1537                partial_result_params: Default::default(),
1538            };
1539            let request: Incoming = helper::request("textDocument/implementation", params).unwrap();
1540            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1541            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1542            assert_eq!(
1543                service.call(request.clone()).await,
1544                Ok(Some(Outgoing::Response(response)))
1545            );
1546        }
1547
1548        #[tokio::test]
1549        async fn on_type_formatting() {
1550            let (service, _) = LspService::new(|_| Mock::default());
1551            let mut service = Spawn::new(service);
1552
1553            super::helper::initialize(&mut service).await;
1554
1555            let params = lsp::DocumentOnTypeFormattingParams {
1556                text_document_position: lsp::TextDocumentPositionParams {
1557                    text_document: lsp::TextDocumentIdentifier {
1558                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1559                    },
1560                    position: Default::default(),
1561                },
1562                ch: Default::default(),
1563                options: Default::default(),
1564            };
1565            let request: Incoming = helper::request("textDocument/onTypeFormatting", params).unwrap();
1566            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1567            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1568            assert_eq!(
1569                service.call(request.clone()).await,
1570                Ok(Some(Outgoing::Response(response)))
1571            );
1572        }
1573
1574        #[tokio::test]
1575        async fn prepare_call_hierarchy() {
1576            let (service, _) = LspService::new(|_| Mock::default());
1577            let mut service = Spawn::new(service);
1578
1579            super::helper::initialize(&mut service).await;
1580
1581            let params = lsp::CallHierarchyPrepareParams {
1582                text_document_position_params: lsp::TextDocumentPositionParams {
1583                    text_document: lsp::TextDocumentIdentifier {
1584                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1585                    },
1586                    position: Default::default(),
1587                },
1588                work_done_progress_params: Default::default(),
1589            };
1590            let request: Incoming = helper::request("textDocument/prepareCallHierarchy", params).unwrap();
1591            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1592            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1593            assert_eq!(
1594                service.call(request.clone()).await,
1595                Ok(Some(Outgoing::Response(response)))
1596            );
1597        }
1598
1599        #[tokio::test]
1600        async fn prepare_rename() {
1601            let (service, _) = LspService::new(|_| Mock::default());
1602            let mut service = Spawn::new(service);
1603
1604            super::helper::initialize(&mut service).await;
1605
1606            let params = lsp::TextDocumentPositionParams {
1607                text_document: lsp::TextDocumentIdentifier {
1608                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1609                },
1610                position: Default::default(),
1611            };
1612            let request: Incoming = helper::request("textDocument/prepareRename", params).unwrap();
1613            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1614            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1615            assert_eq!(
1616                service.call(request.clone()).await,
1617                Ok(Some(Outgoing::Response(response)))
1618            );
1619        }
1620
1621        #[tokio::test]
1622        async fn range_formatting() {
1623            let (service, _) = LspService::new(|_| Mock::default());
1624            let mut service = Spawn::new(service);
1625
1626            super::helper::initialize(&mut service).await;
1627
1628            let params = lsp::DocumentRangeFormattingParams {
1629                text_document: lsp::TextDocumentIdentifier {
1630                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1631                },
1632                range: Default::default(),
1633                options: Default::default(),
1634                work_done_progress_params: Default::default(),
1635            };
1636            let request: Incoming = helper::request("textDocument/rangeFormatting", params).unwrap();
1637            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1638            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1639            assert_eq!(
1640                service.call(request.clone()).await,
1641                Ok(Some(Outgoing::Response(response)))
1642            );
1643        }
1644
1645        #[tokio::test]
1646        async fn references() {
1647            let (service, _) = LspService::new(|_| Mock::default());
1648            let mut service = Spawn::new(service);
1649
1650            super::helper::initialize(&mut service).await;
1651
1652            let params = lsp::ReferenceParams {
1653                text_document_position: lsp::TextDocumentPositionParams {
1654                    text_document: lsp::TextDocumentIdentifier {
1655                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1656                    },
1657                    position: Default::default(),
1658                },
1659                work_done_progress_params: Default::default(),
1660                partial_result_params: Default::default(),
1661                context: lsp::ReferenceContext {
1662                    include_declaration: Default::default(),
1663                },
1664            };
1665            let request: Incoming = helper::request("textDocument/references", params).unwrap();
1666            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1667            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1668            assert_eq!(
1669                service.call(request.clone()).await,
1670                Ok(Some(Outgoing::Response(response)))
1671            );
1672        }
1673
1674        #[tokio::test]
1675        async fn rename() {
1676            let (service, _) = LspService::new(|_| Mock::default());
1677            let mut service = Spawn::new(service);
1678
1679            super::helper::initialize(&mut service).await;
1680
1681            let params = lsp::RenameParams {
1682                text_document_position: lsp::TextDocumentPositionParams {
1683                    text_document: lsp::TextDocumentIdentifier {
1684                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1685                    },
1686                    position: Default::default(),
1687                },
1688                new_name: Default::default(),
1689                work_done_progress_params: Default::default(),
1690            };
1691            let request: Incoming = helper::request("textDocument/rename", params).unwrap();
1692            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1693            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1694            assert_eq!(
1695                service.call(request.clone()).await,
1696                Ok(Some(Outgoing::Response(response)))
1697            );
1698        }
1699
1700        #[tokio::test]
1701        async fn request_else() {
1702            let (service, _) = LspService::new(|_| Mock::default());
1703            let mut service = Spawn::new(service);
1704
1705            super::helper::initialize(&mut service).await;
1706
1707            let params = None::<serde_json::Value>;
1708            let request: Incoming = helper::request("foo/bar", params).unwrap();
1709            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1710            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1711            assert_eq!(
1712                service.call(request.clone()).await,
1713                Ok(Some(Outgoing::Response(response)))
1714            );
1715        }
1716
1717        #[tokio::test]
1718        async fn selection_range() {
1719            let (service, _) = LspService::new(|_| Mock::default());
1720            let mut service = Spawn::new(service);
1721
1722            super::helper::initialize(&mut service).await;
1723
1724            let params = lsp::SelectionRangeParams {
1725                text_document: lsp::TextDocumentIdentifier {
1726                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1727                },
1728                positions: Default::default(),
1729                work_done_progress_params: Default::default(),
1730                partial_result_params: Default::default(),
1731            };
1732            let request: Incoming = helper::request("textDocument/selectionRange", params).unwrap();
1733            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1734            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1735            assert_eq!(
1736                service.call(request.clone()).await,
1737                Ok(Some(Outgoing::Response(response)))
1738            );
1739        }
1740
1741        #[tokio::test]
1742        async fn signature_help() {
1743            let (service, _) = LspService::new(|_| Mock::default());
1744            let mut service = Spawn::new(service);
1745
1746            super::helper::initialize(&mut service).await;
1747
1748            let params = lsp::SignatureHelpParams {
1749                context: Default::default(),
1750                text_document_position_params: lsp::TextDocumentPositionParams {
1751                    text_document: lsp::TextDocumentIdentifier {
1752                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1753                    },
1754                    position: Default::default(),
1755                },
1756                work_done_progress_params: Default::default(),
1757            };
1758            let request: Incoming = helper::request("textDocument/signatureHelp", params).unwrap();
1759            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1760            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1761            assert_eq!(
1762                service.call(request.clone()).await,
1763                Ok(Some(Outgoing::Response(response)))
1764            );
1765        }
1766
1767        #[tokio::test]
1768        async fn type_definition() {
1769            let (service, _) = LspService::new(|_| Mock::default());
1770            let mut service = Spawn::new(service);
1771
1772            super::helper::initialize(&mut service).await;
1773
1774            let params = lsp::request::GotoTypeDefinitionParams {
1775                text_document_position_params: lsp::TextDocumentPositionParams {
1776                    text_document: lsp::TextDocumentIdentifier {
1777                        uri: lsp::Url::parse("inmemory::///test").unwrap(),
1778                    },
1779                    position: Default::default(),
1780                },
1781                work_done_progress_params: Default::default(),
1782                partial_result_params: Default::default(),
1783            };
1784            let request: Incoming = helper::request("textDocument/typeDefinition", params).unwrap();
1785            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1786            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1787            assert_eq!(
1788                service.call(request.clone()).await,
1789                Ok(Some(Outgoing::Response(response)))
1790            );
1791        }
1792
1793        #[tokio::test]
1794        async fn will_save() {
1795            let (service, _) = LspService::new(|_| Mock::default());
1796            let mut service = Spawn::new(service);
1797
1798            super::helper::initialize(&mut service).await;
1799
1800            let params = lsp::WillSaveTextDocumentParams {
1801                text_document: lsp::TextDocumentIdentifier {
1802                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1803                },
1804                reason: lsp::TextDocumentSaveReason::MANUAL,
1805            };
1806            let request: Incoming = helper::request("textDocument/willSave", params).unwrap();
1807            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1808            assert_eq!(service.call(request.clone()).await, Ok(None));
1809        }
1810
1811        #[tokio::test]
1812        async fn will_save_wait_until() {
1813            let (service, _) = LspService::new(|_| Mock::default());
1814            let mut service = Spawn::new(service);
1815
1816            super::helper::initialize(&mut service).await;
1817
1818            let params = lsp::WillSaveTextDocumentParams {
1819                text_document: lsp::TextDocumentIdentifier {
1820                    uri: lsp::Url::parse("inmemory::///test").unwrap(),
1821                },
1822                reason: lsp::TextDocumentSaveReason::MANUAL,
1823            };
1824            let request: Incoming = helper::request("textDocument/willSaveWaitUntil", params).unwrap();
1825            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1826            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1827            assert_eq!(
1828                service.call(request.clone()).await,
1829                Ok(Some(Outgoing::Response(response)))
1830            );
1831        }
1832    }
1833
1834    mod workspace {
1835        use super::*;
1836        use crate::jsonrpc::{Error, Id, Incoming, Outgoing, Response};
1837        use serde_json::Value;
1838        use std::task::Poll;
1839        use tower_test::mock::Spawn;
1840
1841        #[tokio::test]
1842        async fn did_change_configuration() {
1843            let (service, _) = LspService::new(|_| Mock::default());
1844            let mut service = Spawn::new(service);
1845
1846            super::helper::initialize(&mut service).await;
1847
1848            let params = lsp::DidChangeConfigurationParams { settings: Value::Null };
1849            let request: Incoming = helper::request("workspace/didChangeConfiguration", params).unwrap();
1850            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1851            assert_eq!(service.call(request.clone()).await, Ok(None));
1852        }
1853
1854        #[tokio::test]
1855        async fn did_change_watched_files() {
1856            let (service, _) = LspService::new(|_| Mock::default());
1857            let mut service = Spawn::new(service);
1858
1859            super::helper::initialize(&mut service).await;
1860
1861            let params = lsp::DidChangeWatchedFilesParams {
1862                changes: Default::default(),
1863            };
1864            let request: Incoming = helper::request("workspace/didChangeWatchedFiles", params).unwrap();
1865            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1866            assert_eq!(service.call(request.clone()).await, Ok(None));
1867        }
1868
1869        #[tokio::test]
1870        async fn did_change_workspace_folders() {
1871            let (service, _) = LspService::new(|_| Mock::default());
1872            let mut service = Spawn::new(service);
1873
1874            super::helper::initialize(&mut service).await;
1875
1876            let params = lsp::DidChangeWorkspaceFoldersParams::default();
1877            let request: Incoming = helper::request("workspace/didChangeWorkspaceFolders", params).unwrap();
1878            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1879            assert_eq!(service.call(request.clone()).await, Ok(None));
1880        }
1881
1882        #[tokio::test]
1883        async fn execute_command() {
1884            let (service, _) = LspService::new(|_| Mock::default());
1885            let mut service = Spawn::new(service);
1886
1887            super::helper::initialize(&mut service).await;
1888
1889            let params = lsp::ExecuteCommandParams::default();
1890            let request: Incoming = helper::request("workspace/executeCommand", params).unwrap();
1891            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1892            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1893            assert_eq!(
1894                service.call(request.clone()).await,
1895                Ok(Some(Outgoing::Response(response)))
1896            );
1897        }
1898
1899        #[tokio::test]
1900        async fn symbol() {
1901            let (service, _) = LspService::new(|_| Mock::default());
1902            let mut service = Spawn::new(service);
1903
1904            super::helper::initialize(&mut service).await;
1905
1906            let params = lsp::WorkspaceSymbolParams::default();
1907            let request: Incoming = helper::request("workspace/symbol", params).unwrap();
1908            let response = Response::error(Some(Id::Number(1)), Error::method_not_found());
1909            assert_eq!(service.poll_ready(), Poll::Ready(Ok(())));
1910            assert_eq!(
1911                service.call(request.clone()).await,
1912                Ok(Some(Outgoing::Response(response)))
1913            );
1914        }
1915    }
1916}