diff options
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r-- | cli/lsp/language_server.rs | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 6edfdc74b..58fcf9975 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -718,6 +718,49 @@ impl Inner { self.performance.measure(mark); } + async fn document_symbol( + &self, + params: DocumentSymbolParams, + ) -> LspResult<Option<DocumentSymbolResponse>> { + 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 req = tsc::RequestMethod::GetNavigationTree(specifier); + let navigation_tree: tsc::NavigationTree = self + .ts_server + .request(self.snapshot(), req) + .await + .map_err(|err| { + error!("Failed to request to tsserver {}", err); + LspError::invalid_request() + })?; + + let response = if let Some(child_items) = navigation_tree.child_items { + let mut document_symbols = Vec::<DocumentSymbol>::new(); + for item in child_items { + item.collect_document_symbols(&line_index, &mut document_symbols); + } + Some(DocumentSymbolResponse::Nested(document_symbols)) + } else { + None + }; + self.performance.measure(mark); + Ok(response) + } + async fn formatting( &self, params: DocumentFormattingParams, @@ -2165,6 +2208,13 @@ impl lspower::LanguageServer for LanguageServer { self.0.lock().await.did_change_watched_files(params).await } + async fn document_symbol( + &self, + params: DocumentSymbolParams, + ) -> LspResult<Option<DocumentSymbolResponse>> { + self.0.lock().await.document_symbol(params).await + } + async fn formatting( &self, params: DocumentFormattingParams, @@ -3407,6 +3457,410 @@ mod tests { } #[tokio::test] + async fn test_document_symbol() { + let mut harness = LspTestHarness::new(vec![ + ( + LspFixture::Path("initialize_request.json"), + LspResponse::RequestAny, + ), + ( + LspFixture::Path("initialized_notification.json"), + LspResponse::None, + ), + ( + LspFixture::Path("document_symbol_did_open_notification.json"), + LspResponse::None, + ), + ( + LspFixture::Path("document_symbol_request.json"), + LspResponse::Request( + 2, + json!([ + { + "name": "bar", + "kind": 13, + "range": { + "start": { + "line": 17, + "character": 4 + }, + "end": { + "line": 17, + "character": 26 + } + }, + "selectionRange": { + "start": { + "line": 17, + "character": 4 + }, + "end": { + "line": 17, + "character": 7 + } + } + }, + { + "name": "Bar", + "kind": 5, + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 13, + "character": 1 + } + }, + "selectionRange": { + "start": { + "line": 4, + "character": 6 + }, + "end": { + "line": 4, + "character": 9 + } + }, + "children": [ + { + "name": "constructor", + "kind": 9, + "range": { + "start": { + "line": 5, + "character": 2 + }, + "end": { + "line": 5, + "character": 35 + } + }, + "selectionRange": { + "start": { + "line": 5, + "character": 2 + }, + "end": { + "line": 5, + "character": 35 + } + } + }, + { + "name": "baz", + "kind": 6, + "tags": [ + 1 + ], + "range": { + "start": { + "line": 8, + "character": 2 + }, + "end": { + "line": 8, + "character": 25 + } + }, + "selectionRange": { + "start": { + "line": 8, + "character": 2 + }, + "end": { + "line": 8, + "character": 5 + } + } + }, + { + "name": "foo", + "kind": 6, + "range": { + "start": { + "line": 6, + "character": 2 + }, + "end": { + "line": 6, + "character": 24 + } + }, + "selectionRange": { + "start": { + "line": 6, + "character": 2 + }, + "end": { + "line": 6, + "character": 5 + } + } + }, + { + "name": "getStaticBar", + "kind": 6, + "range": { + "start": { + "line": 12, + "character": 2 + }, + "end": { + "line": 12, + "character": 57 + } + }, + "selectionRange": { + "start": { + "line": 12, + "character": 17 + }, + "end": { + "line": 12, + "character": 29 + } + } + }, + { + "name": "staticBar", + "kind": 7, + "range": { + "start": { + "line": 11, + "character": 2 + }, + "end": { + "line": 11, + "character": 32 + } + }, + "selectionRange": { + "start": { + "line": 11, + "character": 9 + }, + "end": { + "line": 11, + "character": 18 + } + } + }, + { + "name": "value", + "kind": 7, + "range": { + "start": { + "line": 9, + "character": 2 + }, + "end": { + "line": 9, + "character": 35 + } + }, + "selectionRange": { + "start": { + "line": 9, + "character": 6 + }, + "end": { + "line": 9, + "character": 11 + } + } + }, + { + "name": "value", + "kind": 7, + "range": { + "start": { + "line": 10, + "character": 2 + }, + "end": { + "line": 10, + "character": 42 + } + }, + "selectionRange": { + "start": { + "line": 10, + "character": 6 + }, + "end": { + "line": 10, + "character": 11 + } + } + }, + { + "name": "x", + "kind": 7, + "range": { + "start": { + "line": 5, + "character": 14 + }, + "end": { + "line": 5, + "character": 30 + } + }, + "selectionRange": { + "start": { + "line": 5, + "character": 21 + }, + "end": { + "line": 5, + "character": 22 + } + } + } + ] + }, + { + "name": "IFoo", + "kind": 11, + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 2, + "character": 1 + } + }, + "selectionRange": { + "start": { + "line": 0, + "character": 10 + }, + "end": { + "line": 0, + "character": 14 + } + }, + "children": [ + { + "name": "foo", + "kind": 6, + "range": { + "start": { + "line": 1, + "character": 2 + }, + "end": { + "line": 1, + "character": 17 + } + }, + "selectionRange": { + "start": { + "line": 1, + "character": 2 + }, + "end": { + "line": 1, + "character": 5 + } + } + } + ] + }, + { + "name": "Values", + "kind": 10, + "range": { + "start": { + "line": 15, + "character": 0 + }, + "end": { + "line": 15, + "character": 30 + } + }, + "selectionRange": { + "start": { + "line": 15, + "character": 5 + }, + "end": { + "line": 15, + "character": 11 + } + }, + "children": [ + { + "name": "value1", + "kind": 13, + "range": { + "start": { + "line": 15, + "character": 14 + }, + "end": { + "line": 15, + "character": 20 + } + }, + "selectionRange": { + "start": { + "line": 15, + "character": 14 + }, + "end": { + "line": 15, + "character": 20 + } + } + }, + { + "name": "value2", + "kind": 13, + "range": { + "start": { + "line": 15, + "character": 22 + }, + "end": { + "line": 15, + "character": 28 + } + }, + "selectionRange": { + "start": { + "line": 15, + "character": 22 + }, + "end": { + "line": 15, + "character": 28 + } + } + } + ] + } + ]), + ), + ), + ( + LspFixture::Path("shutdown_request.json"), + LspResponse::Request(3, json!(null)), + ), + ( + LspFixture::Path("exit_notification.json"), + LspResponse::None, + ), + ]); + harness.run().await; + } + + #[tokio::test] async fn test_folding_range() { let mut harness = LspTestHarness::new(vec![ ( |