summaryrefslogtreecommitdiff
path: root/cli/lsp/language_server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r--cli/lsp/language_server.rs454
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(&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 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![
(