diff options
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r-- | cli/lsp/language_server.rs | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 3c3d82b3b..5489a0b9b 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -1590,6 +1590,48 @@ impl Inner { } } + async fn selection_range( + &self, + params: SelectionRangeParams, + ) -> LspResult<Option<Vec<SelectionRange>>> { + if !self.enabled() { + return Ok(None); + } + let mark = self.performance.mark("selection_range"); + let specifier = self.url_map.normalize_url(¶ms.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 mut selection_ranges = Vec::<SelectionRange>::new(); + for position in params.positions { + let req = tsc::RequestMethod::GetSmartSelectionRange(( + specifier.clone(), + line_index.offset_tsc(position)?, + )); + + let selection_range: tsc::SelectionRange = self + .ts_server + .request(self.snapshot(), req) + .await + .map_err(|err| { + error!("Failed to request to tsserver {}", err); + LspError::invalid_request() + })?; + + selection_ranges.push(selection_range.to_selection_range(&line_index)); + } + self.performance.measure(mark); + Ok(Some(selection_ranges)) + } + async fn signature_help( &self, params: SignatureHelpParams, @@ -1794,6 +1836,13 @@ impl lspower::LanguageServer for LanguageServer { self.0.lock().await.request_else(method, params).await } + async fn selection_range( + &self, + params: SelectionRangeParams, + ) -> LspResult<Option<Vec<SelectionRange>>> { + self.0.lock().await.selection_range(params).await + } + async fn signature_help( &self, params: SignatureHelpParams, @@ -2412,6 +2461,114 @@ mod tests { } #[tokio::test] + async fn test_selection_range() { + let mut harness = LspTestHarness::new(vec![ + ("initialize_request.json", LspResponse::RequestAny), + ("initialized_notification.json", LspResponse::None), + ( + "selection_range_did_open_notification.json", + LspResponse::None, + ), + ( + "selection_range_request.json", + LspResponse::Request( + 2, + json!([{ + "range": { + "start": { + "line": 2, + "character": 8 + }, + "end": { + "line": 2, + "character": 9 + } + }, + "parent": { + "range": { + "start": { + "line": 2, + "character": 8 + }, + "end": { + "line": 2, + "character": 15 + } + }, + "parent": { + "range": { + "start": { + "line": 2, + "character": 4 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "parent": { + "range": { + "start": { + "line": 1, + "character": 13 + }, + "end": { + "line": 6, + "character": 2 + } + }, + "parent": { + "range": { + "start": { + "line": 1, + "character": 2 + }, + "end": { + "line": 6, + "character": 3 + } + }, + "parent": { + "range": { + "start": { + "line": 0, + "character": 11 + }, + "end": { + "line": 7, + "character": 0 + } + }, + "parent": { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 7, + "character": 1 + } + } + } + } + } + } + } + } + }]), + ), + ), + ( + "shutdown_request.json", + LspResponse::Request(3, json!(null)), + ), + ("exit_notification.json", LspResponse::None), + ]); + harness.run().await; + } + + #[tokio::test] async fn test_code_lens_request() { let mut harness = LspTestHarness::new(vec![ ("initialize_request.json", LspResponse::RequestAny), |