molc/
lib.rs

1pub mod messages;
2
3use std::collections::HashMap;
4use std::fs::File;
5use std::io::{stdout, Read, Write};
6use std::path::Path;
7use std::sync::mpsc::{Receiver, Sender};
8use std::time::Duration;
9
10use lsp_types::notification::{Notification, PublishDiagnostics};
11use lsp_types::request::Request;
12use lsp_types::{
13    ClientCapabilities, CodeAction, CodeActionClientCapabilities, CodeActionContext,
14    CodeActionParams, CodeActionResponse, CodeLens, CodeLensParams, CompletionClientCapabilities,
15    CompletionContext, CompletionItem, CompletionParams, CompletionResponse, CompletionTriggerKind,
16    DidChangeTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams,
17    DocumentLinkClientCapabilities, DocumentSymbolClientCapabilities, DocumentSymbolParams,
18    DocumentSymbolResponse, DynamicRegistrationClientCapabilities, FoldingRange,
19    FoldingRangeClientCapabilities, FoldingRangeParams, GotoCapability, GotoDefinitionParams,
20    GotoDefinitionResponse, Hover, HoverClientCapabilities, HoverParams, InitializeParams,
21    InitializeResult, InitializedParams, InlayHint, InlayHintClientCapabilities, InlayHintParams,
22    Location, MarkupKind, Position, PublishDiagnosticsClientCapabilities, PublishDiagnosticsParams,
23    Range, ReferenceContext, ReferenceParams, RenameClientCapabilities, RenameParams,
24    SelectionRangeClientCapabilities, SemanticTokensClientCapabilities, ServerCapabilities,
25    SignatureHelp, SignatureHelpClientCapabilities, SignatureHelpContext, SignatureHelpParams,
26    SignatureHelpTriggerKind, TextDocumentClientCapabilities, TextDocumentContentChangeEvent,
27    TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams,
28    TextDocumentSyncClientCapabilities, Url, VersionedTextDocumentIdentifier, WorkspaceEdit,
29};
30use serde::de::Deserialize;
31use serde::Serialize;
32use serde_json::{json, Value};
33
34use crate::messages::{ErrorMessage, LogMessage, ShowMessage};
35
36fn safe_yield() {
37    std::thread::yield_now();
38    std::thread::sleep(std::time::Duration::from_millis(10));
39}
40
41/// Adds a character at the given position.
42pub fn add_char(line: u32, character: u32, text: &str) -> TextDocumentContentChangeEvent {
43    TextDocumentContentChangeEvent {
44        range: Some(Range {
45            start: Position { line, character },
46            end: Position { line, character },
47        }),
48        range_length: None,
49        text: text.to_string(),
50    }
51}
52
53/// Changes the text at the given position.
54pub fn change_text(line: u32, character: u32, text: &str) -> TextDocumentContentChangeEvent {
55    TextDocumentContentChangeEvent {
56        range: Some(Range {
57            start: Position { line, character },
58            end: Position {
59                line,
60                character: character + text.chars().count() as u32,
61            },
62        }),
63        range_length: None,
64        text: text.to_string(),
65    }
66}
67
68/// Deletes the text at the given range.
69pub fn delete_text(line: u32, character: u32, len: u32) -> TextDocumentContentChangeEvent {
70    TextDocumentContentChangeEvent {
71        range: Some(Range {
72            start: Position { line, character },
73            end: Position {
74                line,
75                character: character + len,
76            },
77        }),
78        range_length: Some(len),
79        text: "".to_string(),
80    }
81}
82
83/// Deletes the line at the given index.
84pub fn delete_line(line: u32) -> TextDocumentContentChangeEvent {
85    TextDocumentContentChangeEvent {
86        range: Some(Range {
87            start: Position { line, character: 0 },
88            end: Position {
89                line: line + 1,
90                character: 0,
91            },
92        }),
93        range_length: None,
94        text: "".to_string(),
95    }
96}
97
98/// Indicates an absolute position in the document.
99pub fn abs_pos(uri: Url, line: u32, col: u32) -> TextDocumentPositionParams {
100    TextDocumentPositionParams {
101        text_document: TextDocumentIdentifier::new(uri),
102        position: Position {
103            line,
104            character: col,
105        },
106    }
107}
108
109/// Indicates a range of one line.
110pub fn oneline_range(line: u32, from: u32, to: u32) -> Range {
111    Range {
112        start: Position {
113            line,
114            character: from,
115        },
116        end: Position {
117            line,
118            character: to,
119        },
120    }
121}
122
123/// Parses a sequence of LSP messages and returns them as a vector of `Value`s.
124pub fn parse_msgs(_input: &str) -> Vec<Value> {
125    let mut input = _input;
126    let mut msgs = Vec::new();
127    loop {
128        if input.starts_with("Content-Length: ") {
129            let idx = "Content-Length: ".len();
130            input = &input[idx..];
131        } else {
132            break;
133        }
134        let dights = input.find("\r\n").unwrap();
135        let len = input[..dights].parse::<usize>().unwrap();
136        let idx = dights + "\r\n\r\n".len();
137        input = &input[idx..];
138        let msg = &input
139            .get(..len)
140            .unwrap_or_else(|| panic!("len: {len}, input: `{input}` -> _input: `{_input}`"));
141        input = &input[len..];
142        msgs.push(serde_json::from_str(msg).unwrap());
143    }
144    msgs
145}
146
147pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
148
149/// Servers implementing this must return output with the `send_*` method provided by this trait.
150pub trait RedirectableStdout {
151    fn sender(&self) -> Option<&Sender<Value>>;
152
153    fn send_stdout<T: ?Sized + Serialize>(&self, message: &T) -> Result<()> {
154        if let Some(sender) = self.sender() {
155            sender.send(serde_json::to_value(message)?)?;
156        } else {
157            let msg = serde_json::to_string(message)?;
158            let mut stdout = stdout().lock();
159            write!(stdout, "Content-Length: {}\r\n\r\n{}", msg.len(), msg)?;
160            stdout.flush()?;
161        }
162        Ok(())
163    }
164
165    fn send_log<S: Into<String>>(&self, msg: S) -> Result<()> {
166        if cfg!(debug_assertions) || cfg!(feature = "debug") {
167            self.send_stdout(&LogMessage::new(msg))
168        } else {
169            Ok(())
170        }
171    }
172
173    #[allow(unused)]
174    fn send_info<S: Into<String>>(&self, msg: S) -> Result<()> {
175        self.send_stdout(&ShowMessage::info(msg))
176    }
177
178    fn send_error_info<S: Into<String>>(&self, msg: S) -> Result<()> {
179        self.send_stdout(&ShowMessage::error(msg))
180    }
181
182    fn send_error<S: Into<String>>(&self, id: Option<i64>, code: i64, msg: S) -> Result<()> {
183        self.send_stdout(&ErrorMessage::new(
184            id,
185            json!({ "code": code, "message": msg.into() }),
186        ))
187    }
188
189    fn send_invalid_req_error(&self) -> Result<()> {
190        self.send_error(None, -32601, "received an invalid request")
191    }
192}
193
194pub trait LangServer {
195    /// Receive and process a message from the client. Output should be returned to the channel.
196    fn dispatch(&mut self, msg: impl Into<Value>) -> Result<()>;
197}
198
199pub struct FakeClient<LS: LangServer> {
200    pub server: LS,
201    receiver: Receiver<Value>,
202    pub client_capas: ClientCapabilities,
203    pub server_capas: Option<ServerCapabilities>,
204    /// Stores all messages received from the server.
205    pub responses: Vec<Value>,
206    #[allow(clippy::complexity)]
207    handlers: HashMap<String, Box<dyn Fn(&Value, &mut LS) -> Result<()>>>,
208    ver: i32,
209    req_id: i64,
210}
211
212impl<LS: LangServer> FakeClient<LS> {
213    /// The server should send responses to the channel at least during testing.
214    pub fn new(server: LS, receiver: Receiver<Value>) -> Self {
215        FakeClient {
216            receiver,
217            responses: Vec::new(),
218            ver: 0,
219            req_id: 0,
220            client_capas: ClientCapabilities {
221                text_document: Some(TextDocumentClientCapabilities {
222                    synchronization: Some(TextDocumentSyncClientCapabilities {
223                        did_save: Some(true),
224                        ..Default::default()
225                    }),
226                    completion: Some(CompletionClientCapabilities {
227                        completion_item: Some(Default::default()),
228                        completion_item_kind: Some(Default::default()),
229                        ..Default::default()
230                    }),
231                    hover: Some(HoverClientCapabilities {
232                        content_format: Some(vec![MarkupKind::PlainText]),
233                        ..Default::default()
234                    }),
235                    signature_help: Some(SignatureHelpClientCapabilities {
236                        signature_information: Some(Default::default()),
237                        ..Default::default()
238                    }),
239                    references: Some(DynamicRegistrationClientCapabilities::default()),
240                    document_highlight: Some(DynamicRegistrationClientCapabilities::default()),
241                    document_symbol: Some(DocumentSymbolClientCapabilities {
242                        ..Default::default()
243                    }),
244                    formatting: Some(DynamicRegistrationClientCapabilities::default()),
245                    range_formatting: Some(DynamicRegistrationClientCapabilities::default()),
246                    on_type_formatting: Some(DynamicRegistrationClientCapabilities::default()),
247                    declaration: Some(GotoCapability {
248                        link_support: Some(true),
249                        ..Default::default()
250                    }),
251                    definition: Some(GotoCapability {
252                        link_support: Some(true),
253                        ..Default::default()
254                    }),
255                    type_definition: Some(GotoCapability {
256                        link_support: Some(true),
257                        ..Default::default()
258                    }),
259                    implementation: Some(GotoCapability {
260                        link_support: Some(true),
261                        ..Default::default()
262                    }),
263                    code_action: Some(CodeActionClientCapabilities {
264                        data_support: Some(true),
265                        ..Default::default()
266                    }),
267                    code_lens: Some(DynamicRegistrationClientCapabilities::default()),
268                    document_link: Some(DocumentLinkClientCapabilities {
269                        tooltip_support: Some(true),
270                        dynamic_registration: Some(false),
271                    }),
272                    color_provider: Some(DynamicRegistrationClientCapabilities::default()),
273                    rename: Some(RenameClientCapabilities {
274                        prepare_support: Some(true),
275                        ..Default::default()
276                    }),
277                    publish_diagnostics: Some(PublishDiagnosticsClientCapabilities {
278                        related_information: Some(true),
279                        ..Default::default()
280                    }),
281                    folding_range: Some(FoldingRangeClientCapabilities {
282                        ..Default::default()
283                    }),
284                    selection_range: Some(SelectionRangeClientCapabilities {
285                        ..Default::default()
286                    }),
287                    linked_editing_range: Some(DynamicRegistrationClientCapabilities::default()),
288                    call_hierarchy: Some(DynamicRegistrationClientCapabilities::default()),
289                    semantic_tokens: Some(SemanticTokensClientCapabilities {
290                        ..Default::default()
291                    }),
292                    moniker: Some(DynamicRegistrationClientCapabilities::default()),
293                    inlay_hint: Some(InlayHintClientCapabilities {
294                        ..Default::default()
295                    }),
296                }),
297                ..Default::default()
298            },
299            server_capas: None,
300            handlers: HashMap::new(),
301            server,
302        }
303    }
304
305    pub fn with_capabilities(server: LS, receiver: Receiver<Value>, client_capas: ClientCapabilities) -> Self {
306        FakeClient { client_capas, ..FakeClient::new(server, receiver) }
307    }
308
309    /// Adds a handler for the request/notification with the given method name.
310    /// When the client receives a request/notification for the specified method, it executes the handler.
311    pub fn add_handler(
312        &mut self,
313        method_name: impl Into<String>,
314        handler: impl Fn(&Value, &mut LS) -> Result<()> + 'static,
315    ) {
316        self.handlers.insert(method_name.into(), Box::new(handler));
317    }
318
319    /// Removes the handler for the request/notification with the given method name.
320    pub fn remove_handler(&mut self, method_name: &str) {
321        self.handlers.remove(method_name);
322    }
323
324    pub fn enable_log_display(&mut self) {
325        self.add_handler("window/logMessage", |msg, _| {
326            let msg = LogMessage::deserialize(msg.clone())?;
327            println!("[LOG]: {}", &msg.params["message"]);
328            Ok(())
329        });
330    }
331
332    /// Waits for `n` messages to be received.
333    /// When a request is received, the registered handler will be executed.
334    pub fn wait_messages(&mut self, n: usize) -> Result<()> {
335        for _ in 0..n {
336            if let Ok(msg) = self.receiver.recv() {
337                if msg.get("method").is_some() {
338                    self.handle_server_message(&msg);
339                }
340                self.responses.push(msg);
341            }
342        }
343        Ok(())
344    }
345
346    pub fn wait_diagnostics(&mut self) -> Result<PublishDiagnosticsParams> {
347        loop {
348            if let Ok(msg) = self.receiver.recv() {
349                if msg.get("method").is_some() {
350                    self.handle_server_message(&msg);
351                }
352                self.responses.push(msg);
353                let msg = self.responses.last().unwrap();
354                if msg
355                    .get("method")
356                    .is_some_and(|val| val == PublishDiagnostics::METHOD)
357                {
358                    if let Some(result) = msg
359                        .get("params")
360                        .cloned()
361                        .and_then(|res| PublishDiagnosticsParams::deserialize(res).ok())
362                    {
363                        return Ok(result);
364                    }
365                }
366            }
367            safe_yield();
368        }
369    }
370
371    /// Waits for a response to the request, where its `id` is expected to be that of `req_id`,
372    /// and `req_id` will be incremented if the response is successfully received.
373    /// When a request is received, the registered handler will be executed.
374    pub fn wait_for<R>(&mut self) -> Result<R>
375    where
376        R: Deserialize<'static>,
377    {
378        loop {
379            if let Ok(msg) = self.receiver.recv() {
380                if msg.get("method").is_some() {
381                    self.handle_server_message(&msg);
382                }
383                self.responses.push(msg);
384                let msg = self.responses.last().unwrap();
385                if msg.get("id").is_some_and(|val| val == self.req_id) {
386                    if let Some(result) = msg
387                        .get("result")
388                        .cloned()
389                        .and_then(|res| R::deserialize(res).ok())
390                    {
391                        self.req_id += 1;
392                        return Ok(result);
393                    }
394                }
395            }
396            safe_yield();
397        }
398    }
399
400    pub fn wait_with_timeout<R>(&mut self, timeout: Duration) -> Result<Option<R>>
401    where
402        R: Deserialize<'static>,
403    {
404        let start = std::time::Instant::now();
405        loop {
406            if let Ok(msg) = self.receiver.recv_timeout(std::time::Duration::from_millis(10)) {
407                if msg.get("method").is_some() {
408                    self.handle_server_message(&msg);
409                }
410                self.responses.push(msg);
411                let msg = self.responses.last().unwrap();
412                if msg.get("id").is_some_and(|val| val == self.req_id) {
413                    if let Some(result) = msg
414                        .get("result")
415                        .cloned()
416                        .and_then(|res| R::deserialize(res).ok())
417                    {
418                        self.req_id += 1;
419                        return Ok(Some(result));
420                    }
421                }
422            }
423            if start.elapsed() > timeout {
424                return Ok(None);
425            }
426            safe_yield();
427        }
428    }
429
430    fn handle_server_message(&mut self, msg: &Value) {
431        if let Some(method) = msg.get("method").and_then(|val| val.as_str()) {
432            if let Some(handler) = self.handlers.get(method) {
433                if let Err(err) = handler(msg, &mut self.server) {
434                    eprintln!("error: {:?}", err);
435                }
436            }
437        }
438    }
439
440    /// Send a request to the server.
441    pub fn request<R: Request>(&mut self, params: R::Params) -> Result<R::Result> {
442        let msg = json!({
443            "jsonrpc": "2.0",
444            "id": self.req_id,
445            "method": R::METHOD,
446            "params": params,
447        });
448        self.server.dispatch(msg)?;
449        self.wait_for::<R::Result>()
450    }
451
452    /// Send a notification to the server.
453    pub fn notify<N: Notification>(&mut self, params: N::Params) -> Result<()> {
454        let msg = json!({
455            "jsonrpc": "2.0",
456            "method": N::METHOD,
457            "params": params,
458        });
459        self.server.dispatch(msg)?;
460        Ok(())
461    }
462
463    /// Send an `initialize` request to the server.
464    /// This will set the server capabilities
465    pub fn request_initialize(&mut self) -> Result<InitializeResult> {
466        let params = InitializeParams {
467            capabilities: self.client_capas.clone(),
468            ..Default::default()
469        };
470        let msg = json!({
471            "jsonrpc": "2.0",
472            "id": self.req_id,
473            "method": "initialize",
474            "params": params,
475        });
476        self.server.dispatch(msg)?;
477        let res = self.wait_for::<InitializeResult>()?;
478        self.server_capas = Some(res.capabilities.clone());
479        Ok(res)
480    }
481
482    /// Send an `initialized` notification to the server.
483    pub fn notify_initialized(&mut self) -> Result<()> {
484        let params = InitializedParams {};
485        let msg = json!({
486            "jsonrpc": "2.0",
487            "method": "initialized",
488            "params": params,
489        });
490        self.server.dispatch(msg)?;
491        Ok(())
492    }
493
494    /// Send an `exit` notification to the server.
495    pub fn notify_exit(&mut self) -> Result<()> {
496        let msg = json!({
497            "jsonrpc": "2.0",
498            "method": "exit",
499            "params": null,
500        });
501        self.server.dispatch(msg)?;
502        Ok(())
503    }
504
505    /// Send a `textDocument/didOpen` notification to the server.
506    pub fn notify_open(&mut self, file: &str) -> Result<()> {
507        let uri = Url::from_file_path(Path::new(file).canonicalize().unwrap()).unwrap();
508        let mut text = String::new();
509        File::open(file).unwrap().read_to_string(&mut text)?;
510        let params = DidOpenTextDocumentParams {
511            text_document: TextDocumentItem::new(uri, "erg".to_string(), self.ver, text),
512        };
513        self.ver += 1;
514        let msg = json!({
515            "jsonrpc": "2.0",
516            "method": "textDocument/didOpen",
517            "params": params,
518        });
519        self.server.dispatch(msg)?;
520        Ok(())
521    }
522
523    /// Send a `textDocument/didChange` notification to the server.
524    pub fn notify_change(
525        &mut self,
526        uri: Url,
527        change: TextDocumentContentChangeEvent,
528    ) -> Result<()> {
529        let params = DidChangeTextDocumentParams {
530            text_document: VersionedTextDocumentIdentifier::new(uri.clone(), self.ver),
531            content_changes: vec![change],
532        };
533        self.ver += 1;
534        let msg = json!({
535            "jsonrpc": "2.0",
536            "method": "textDocument/didChange",
537            "params": params,
538        });
539        self.server.dispatch(msg)?;
540        Ok(())
541    }
542
543    /// Send a `textDocument/didSave` notification to the server.
544    pub fn notify_save(&mut self, uri: Url) -> Result<()> {
545        let params = DidSaveTextDocumentParams {
546            text_document: TextDocumentIdentifier::new(uri),
547            text: None,
548        };
549        let msg = json!({
550            "jsonrpc": "2.0",
551            "method": "textDocument/didSave",
552            "params": params,
553        });
554        self.server.dispatch(msg)?;
555        Ok(())
556    }
557
558    /// Send a `textDocument/didClose` notification to the server.
559    pub fn notify_close(&mut self, uri: Url) -> Result<()> {
560        let params = TextDocumentIdentifier::new(uri);
561        let msg = json!({
562            "jsonrpc": "2.0",
563            "method": "textDocument/didClose",
564            "params": params,
565        });
566        self.server.dispatch(msg)?;
567        Ok(())
568    }
569
570    fn is_trigger_char(&self, character: &str) -> bool {
571        self.server_capas.as_ref().is_some_and(|cap| {
572            cap.completion_provider.as_ref().is_some_and(|comp| {
573                comp.trigger_characters
574                    .as_ref()
575                    .is_some_and(|chars| chars.iter().any(|c| c == character))
576            })
577        })
578    }
579
580    /// Send a `shutdown` request to the server.
581    pub fn request_shutdown(&mut self) -> Result<()> {
582        let msg = json!({
583            "jsonrpc": "2.0",
584            "id": self.req_id,
585            "method": "shutdown",
586        });
587        self.server.dispatch(msg)?;
588        self.wait_for::<()>()
589    }
590
591    /// Send a `textDocument/completion` request to the server.
592    pub fn request_completion(
593        &mut self,
594        uri: Url,
595        line: u32,
596        col: u32,
597        character: &str,
598    ) -> Result<Option<CompletionResponse>> {
599        let text_document_position = abs_pos(uri, line, col);
600        let trigger_kind = if self.is_trigger_char(character) {
601            CompletionTriggerKind::TRIGGER_CHARACTER
602        } else {
603            CompletionTriggerKind::INVOKED
604        };
605        let trigger_character = self
606            .is_trigger_char(character)
607            .then_some(character.to_string());
608        let context = Some(CompletionContext {
609            trigger_kind,
610            trigger_character,
611        });
612        let params = CompletionParams {
613            text_document_position,
614            context,
615            work_done_progress_params: Default::default(),
616            partial_result_params: Default::default(),
617        };
618        let msg = json!({
619            "jsonrpc": "2.0",
620            "id": self.req_id,
621            "method": "textDocument/completion",
622            "params": params,
623        });
624        self.server.dispatch(msg)?;
625        self.wait_for::<Option<CompletionResponse>>()
626    }
627
628    /// Send a `completionItem/resolve` request to the server.
629    pub fn request_completion_item_resolve(
630        &mut self,
631        completion_item: CompletionItem,
632    ) -> Result<CompletionItem> {
633        let msg = json!({
634            "jsonrpc": "2.0",
635            "id": self.req_id,
636            "method": "completionItem/resolve",
637            "params": completion_item,
638        });
639        self.server.dispatch(msg)?;
640        self.wait_for::<CompletionItem>()
641    }
642
643    /// Send a `textDocument/rename` request to the server.
644    pub fn request_rename(
645        &mut self,
646        uri: Url,
647        line: u32,
648        col: u32,
649        new_name: &str,
650    ) -> Result<Option<WorkspaceEdit>> {
651        let text_document_position = abs_pos(uri, line, col);
652        let params = RenameParams {
653            text_document_position,
654            new_name: new_name.to_string(),
655            work_done_progress_params: Default::default(),
656        };
657        let msg = json!({
658            "jsonrpc": "2.0",
659            "id": self.req_id,
660            "method": "textDocument/rename",
661            "params": params,
662        });
663        self.server.dispatch(msg)?;
664        self.wait_for::<Option<WorkspaceEdit>>()
665    }
666
667    /// Send a `textDocument/signatureHelp` request to the server.
668    pub fn request_signature_help(
669        &mut self,
670        uri: Url,
671        line: u32,
672        col: u32,
673        character: &str,
674    ) -> Result<Option<SignatureHelp>> {
675        let text_document_position_params = abs_pos(uri, line, col);
676        let context = SignatureHelpContext {
677            trigger_kind: SignatureHelpTriggerKind::TRIGGER_CHARACTER,
678            trigger_character: Some(character.to_string()),
679            is_retrigger: false,
680            active_signature_help: None,
681        };
682        let params = SignatureHelpParams {
683            text_document_position_params,
684            context: Some(context),
685            work_done_progress_params: Default::default(),
686        };
687        let msg = json!({
688            "jsonrpc": "2.0",
689            "id": self.req_id,
690            "method": "textDocument/signatureHelp",
691            "params": params,
692        });
693        self.server.dispatch(msg)?;
694        self.wait_for::<Option<SignatureHelp>>()
695    }
696
697    /// Send a `textDocument/hover` request to the server.
698    pub fn request_hover(&mut self, uri: Url, line: u32, col: u32) -> Result<Option<Hover>> {
699        let params = HoverParams {
700            text_document_position_params: abs_pos(uri, line, col),
701            work_done_progress_params: Default::default(),
702        };
703        let msg = json!({
704            "jsonrpc": "2.0",
705            "id": self.req_id,
706            "method": "textDocument/hover",
707            "params": params,
708        });
709        self.server.dispatch(msg)?;
710        self.wait_for::<Option<Hover>>()
711    }
712
713    /// Send a `textDocument/references` request to the server.
714    pub fn request_references(
715        &mut self,
716        uri: Url,
717        line: u32,
718        col: u32,
719    ) -> Result<Option<Vec<Location>>> {
720        let context = ReferenceContext {
721            include_declaration: false,
722        };
723        let params = ReferenceParams {
724            text_document_position: abs_pos(uri, line, col),
725            context,
726            work_done_progress_params: Default::default(),
727            partial_result_params: Default::default(),
728        };
729        let msg = json!({
730            "jsonrpc": "2.0",
731            "id": self.req_id,
732            "method": "textDocument/references",
733            "params": params,
734        });
735        self.server.dispatch(msg)?;
736        self.wait_for::<Option<Vec<Location>>>()
737    }
738
739    /// Send a `textDocument/definition` request to the server.
740    pub fn request_goto_definition(
741        &mut self,
742        uri: Url,
743        line: u32,
744        col: u32,
745    ) -> Result<Option<GotoDefinitionResponse>> {
746        let params = GotoDefinitionParams {
747            text_document_position_params: abs_pos(uri, line, col),
748            work_done_progress_params: Default::default(),
749            partial_result_params: Default::default(),
750        };
751        let msg = json!({
752            "jsonrpc": "2.0",
753            "id": self.req_id,
754            "method": "textDocument/definition",
755            "params": params,
756        });
757        self.server.dispatch(msg)?;
758        self.wait_for::<Option<GotoDefinitionResponse>>()
759    }
760
761    /// Send a `textDocument/foldingRange` request to the server.
762    pub fn request_folding_range(&mut self, uri: Url) -> Result<Option<Vec<FoldingRange>>> {
763        let params = FoldingRangeParams {
764            text_document: TextDocumentIdentifier::new(uri),
765            work_done_progress_params: Default::default(),
766            partial_result_params: Default::default(),
767        };
768        let msg = json!({
769            "jsonrpc": "2.0",
770            "id": self.req_id,
771            "method": "textDocument/foldingRange",
772            "params": params,
773        });
774        self.server.dispatch(msg)?;
775        self.wait_for::<Option<Vec<FoldingRange>>>()
776    }
777
778    /// Send a `textDocument/documentSymbol` request to the server.
779    pub fn request_document_symbols(&mut self, uri: Url) -> Result<Option<DocumentSymbolResponse>> {
780        let params = DocumentSymbolParams {
781            text_document: TextDocumentIdentifier::new(uri),
782            work_done_progress_params: Default::default(),
783            partial_result_params: Default::default(),
784        };
785        let msg = json!({
786            "jsonrpc": "2.0",
787            "id": self.req_id,
788            "method": "textDocument/documentSymbol",
789            "params": params,
790        });
791        self.server.dispatch(msg)?;
792        self.wait_for::<Option<DocumentSymbolResponse>>()
793    }
794
795    /// Send a `textDocument/inlayHint` request to the server.
796    pub fn request_inlay_hint(&mut self, uri: Url) -> Result<Option<Vec<InlayHint>>> {
797        let params = InlayHintParams {
798            text_document: TextDocumentIdentifier::new(uri),
799            range: Range {
800                start: Position {
801                    line: 0,
802                    character: 0,
803                },
804                end: Position {
805                    line: u32::MAX,
806                    character: u32::MAX,
807                },
808            },
809            work_done_progress_params: Default::default(),
810        };
811        let msg = json!({
812            "jsonrpc": "2.0",
813            "id": self.req_id,
814            "method": "textDocument/inlayHint",
815            "params": params,
816        });
817        self.server.dispatch(msg)?;
818        self.wait_for::<Option<Vec<InlayHint>>>()
819    }
820
821    /// Send a `textDocument/codeAction` request to the server.
822    pub fn request_code_action(
823        &mut self,
824        uri: Url,
825        line: u32,
826        col: u32,
827    ) -> Result<Option<CodeActionResponse>> {
828        let params = CodeActionParams {
829            text_document: TextDocumentIdentifier::new(uri),
830            range: Range {
831                start: Position {
832                    line,
833                    character: col,
834                },
835                end: Position {
836                    line,
837                    character: col,
838                },
839            },
840            context: CodeActionContext {
841                diagnostics: vec![],
842                only: None,
843            },
844            work_done_progress_params: Default::default(),
845            partial_result_params: Default::default(),
846        };
847        let msg = json!({
848            "jsonrpc": "2.0",
849            "id": self.req_id,
850            "method": lsp_types::request::CodeActionRequest::METHOD,
851            "params": params,
852        });
853        self.server.dispatch(msg)?;
854        self.wait_for::<Option<CodeActionResponse>>()
855    }
856
857    pub fn request_code_action_resolve(&mut self, code_action: CodeAction) -> Result<CodeAction> {
858        let msg = json!({
859            "jsonrpc": "2.0",
860            "id": self.req_id,
861            "method": lsp_types::request::CodeActionResolveRequest::METHOD,
862            "params": code_action,
863        });
864        self.server.dispatch(msg)?;
865        self.wait_for::<CodeAction>()
866    }
867
868    /// Send a `textDocument/codeLens` request to the server.
869    pub fn request_code_lens(&mut self, uri: Url) -> Result<Option<Vec<CodeLens>>> {
870        let params = CodeLensParams {
871            text_document: TextDocumentIdentifier::new(uri),
872            work_done_progress_params: Default::default(),
873            partial_result_params: Default::default(),
874        };
875        let msg = json!({
876            "jsonrpc": "2.0",
877            "id": self.req_id,
878            "method": lsp_types::request::CodeLensRequest::METHOD,
879            "params": params,
880        });
881        self.server.dispatch(msg)?;
882        self.wait_for::<Option<Vec<CodeLens>>>()
883    }
884
885    /// Send a `codeLens/resolve` request to the server.
886    pub fn request_code_lens_resolve(&mut self, code_lens: CodeLens) -> Result<CodeLens> {
887        let msg = json!({
888            "jsonrpc": "2.0",
889            "id": self.req_id,
890            "method": lsp_types::request::CodeLensResolve::METHOD,
891            "params": code_lens,
892        });
893        self.server.dispatch(msg)?;
894        self.wait_for::<CodeLens>()
895    }
896}