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
41pub 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
53pub 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
68pub 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
83pub 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
98pub 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
109pub 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
123pub 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
149pub 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}