diff options
author | Yuki Tanaka <uki00a@gmail.com> | 2021-02-16 11:34:09 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-16 13:34:09 +1100 |
commit | ccd6ee5c2394418c078f1a1be9e5cc1012829cbc (patch) | |
tree | 34d289fd504a89493de295ae9cd9a1cc771fede6 /cli/lsp/language_server.rs | |
parent | 3f5265b21ec578e543d09cdc9d8b19d9655aebd9 (diff) |
feat(lsp): Implement `textDocument/signatureHelp` (#9330)
Co-authored-by: Kitson Kelly <me@kitsonkelly.com>
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r-- | cli/lsp/language_server.rs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 6594492a4..1501249e8 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -1705,6 +1705,68 @@ impl Inner { } } } + + async fn signature_help( + &self, + params: SignatureHelpParams, + ) -> LspResult<Option<SignatureHelp>> { + if !self.enabled() { + return Ok(None); + } + let mark = self.performance.mark("signature_help"); + let specifier = utils::normalize_url( + params.text_document_position_params.text_document.uri, + ); + let line_index = + if let Some(line_index) = self.get_line_index_sync(&specifier) { + line_index + } else { + return Err(LspError::invalid_params(format!( + "An unexpected specifier ({}) was provided.", + specifier + ))); + }; + let options = if let Some(context) = params.context { + tsc::SignatureHelpItemsOptions { + trigger_reason: Some(tsc::SignatureHelpTriggerReason { + kind: context.trigger_kind.into(), + trigger_character: context.trigger_character, + }), + } + } else { + tsc::SignatureHelpItemsOptions { + trigger_reason: None, + } + }; + let req = tsc::RequestMethod::GetSignatureHelpItems(( + specifier, + line_index.offset_tsc(params.text_document_position_params.position)?, + options, + )); + let res = + self + .ts_server + .request(self.snapshot(), req) + .await + .map_err(|err| { + error!("Failed to request to tsserver: {}", err); + LspError::invalid_request() + })?; + let maybe_signature_help_items: Option<tsc::SignatureHelpItems> = + serde_json::from_value(res).map_err(|err| { + error!("Failed to deserialize tsserver response: {}", err); + LspError::internal_error() + })?; + + if let Some(signature_help_items) = maybe_signature_help_items { + let signature_help = signature_help_items.into_signature_help(); + self.performance.measure(mark); + Ok(Some(signature_help)) + } else { + self.performance.measure(mark); + Ok(None) + } + } } #[lspower::async_trait] @@ -1840,6 +1902,13 @@ impl lspower::LanguageServer for LanguageServer { ) -> LspResult<Option<Value>> { self.0.lock().await.request_else(method, params).await } + + async fn signature_help( + &self, + params: SignatureHelpParams, + ) -> LspResult<Option<SignatureHelp>> { + self.0.lock().await.signature_help(params).await + } } #[derive(Debug, Deserialize, Serialize)] @@ -2539,6 +2608,80 @@ mod tests { } #[tokio::test] + async fn test_signature_help() { + let mut harness = LspTestHarness::new(vec![ + ("initialize_request.json", LspResponse::RequestAny), + ("initialized_notification.json", LspResponse::None), + ( + "signature_help_did_open_notification.json", + LspResponse::None, + ), + ( + "signature_help_request_01.json", + LspResponse::Request( + 1, + json!({ + "signatures": [ + { + "label": "add(a: number, b: number): number", + "documentation": "Adds two numbers.", + "parameters": [ + { + "label": "a: number", + "documentation": "This is a first number." + }, + { + "label": "b: number", + "documentation": "This is a second number." + } + ] + } + ], + "activeSignature": 0, + "activeParameter": 0 + }), + ), + ), + ( + "signature_help_did_change_notification.json", + LspResponse::None, + ), + ( + "signature_help_request_02.json", + LspResponse::Request( + 2, + json!({ + "signatures": [ + { + "label": "add(a: number, b: number): number", + "documentation": "Adds two numbers.", + "parameters": [ + { + "label": "a: number", + "documentation": "This is a first number." + }, + { + "label": "b: number", + "documentation": "This is a second number." + } + ] + } + ], + "activeSignature": 0, + "activeParameter": 1 + }), + ), + ), + ( + "shutdown_request.json", + LspResponse::Request(3, json!(null)), + ), + ("exit_notification.json", LspResponse::None), + ]); + harness.run().await; + } + + #[tokio::test] async fn test_code_lens_impl_request() { let mut harness = LspTestHarness::new(vec![ ("initialize_request.json", LspResponse::RequestAny), |