diff options
author | kjeremy <[email protected]> | 2020-04-24 15:11:57 +0100 |
---|---|---|
committer | kjeremy <[email protected]> | 2020-04-24 15:11:57 +0100 |
commit | 0619c67ac6b2f503750058437ce0af08d17d1018 (patch) | |
tree | 8d3a9545087bce774d5cbec4216512c585c8eeb4 | |
parent | ae1f77e5e9aef59aed9cd5a146114e37a74e3316 (diff) |
Support returning non-hierarchical symbols
If `hierarchicalDocumentSymbolSupport` is not true in the client capabilites
then it does not support the `DocumentSymbol[]` return type from the
`textDocument/documentSymbol` request and we must fall back to `SymbolInformation[]`.
This is one of the few requests that use the client capabilities to
differentiate between return types and could cause problems for clients.
See https://github.com/microsoft/language-server-protocol/pull/538#issuecomment-442510767 for more context.
Found while looking at #144
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 41d9fe344..246085005 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -16,7 +16,7 @@ use lsp_types::{ | |||
16 | Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, | 16 | Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, |
17 | Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams, | 17 | Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams, |
18 | SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, | 18 | SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, |
19 | TextEdit, WorkspaceEdit, | 19 | TextEdit, Url, WorkspaceEdit, |
20 | }; | 20 | }; |
21 | use ra_ide::{ | 21 | use ra_ide::{ |
22 | Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, | 22 | Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, |
@@ -219,6 +219,7 @@ pub fn handle_document_symbol( | |||
219 | let _p = profile("handle_document_symbol"); | 219 | let _p = profile("handle_document_symbol"); |
220 | let file_id = params.text_document.try_conv_with(&world)?; | 220 | let file_id = params.text_document.try_conv_with(&world)?; |
221 | let line_index = world.analysis().file_line_index(file_id)?; | 221 | let line_index = world.analysis().file_line_index(file_id)?; |
222 | let url = file_id.try_conv_with(&world)?; | ||
222 | 223 | ||
223 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); | 224 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); |
224 | 225 | ||
@@ -234,10 +235,10 @@ pub fn handle_document_symbol( | |||
234 | }; | 235 | }; |
235 | parents.push((doc_symbol, symbol.parent)); | 236 | parents.push((doc_symbol, symbol.parent)); |
236 | } | 237 | } |
237 | let mut res = Vec::new(); | 238 | let mut document_symbols = Vec::new(); |
238 | while let Some((node, parent)) = parents.pop() { | 239 | while let Some((node, parent)) = parents.pop() { |
239 | match parent { | 240 | match parent { |
240 | None => res.push(node), | 241 | None => document_symbols.push(node), |
241 | Some(i) => { | 242 | Some(i) => { |
242 | let children = &mut parents[i].0.children; | 243 | let children = &mut parents[i].0.children; |
243 | if children.is_none() { | 244 | if children.is_none() { |
@@ -248,7 +249,35 @@ pub fn handle_document_symbol( | |||
248 | } | 249 | } |
249 | } | 250 | } |
250 | 251 | ||
251 | Ok(Some(res.into())) | 252 | if world.config.client_caps.hierarchical_symbols { |
253 | Ok(Some(document_symbols.into())) | ||
254 | } else { | ||
255 | let mut symbol_information = Vec::<SymbolInformation>::new(); | ||
256 | for symbol in document_symbols { | ||
257 | flatten_document_symbol(&symbol, None, &url, &mut symbol_information); | ||
258 | } | ||
259 | |||
260 | Ok(Some(symbol_information.into())) | ||
261 | } | ||
262 | } | ||
263 | |||
264 | fn flatten_document_symbol( | ||
265 | symbol: &DocumentSymbol, | ||
266 | container_name: Option<String>, | ||
267 | url: &Url, | ||
268 | res: &mut Vec<SymbolInformation>, | ||
269 | ) { | ||
270 | res.push(SymbolInformation { | ||
271 | name: symbol.name.clone(), | ||
272 | kind: symbol.kind, | ||
273 | deprecated: symbol.deprecated, | ||
274 | location: Location::new(url.clone(), symbol.range), | ||
275 | container_name: container_name, | ||
276 | }); | ||
277 | |||
278 | for child in symbol.children.iter().flatten() { | ||
279 | flatten_document_symbol(child, Some(symbol.name.clone()), url, res); | ||
280 | } | ||
252 | } | 281 | } |
253 | 282 | ||
254 | pub fn handle_workspace_symbol( | 283 | pub fn handle_workspace_symbol( |