aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkjeremy <[email protected]>2020-04-24 15:11:57 +0100
committerkjeremy <[email protected]>2020-04-24 15:11:57 +0100
commit0619c67ac6b2f503750058437ce0af08d17d1018 (patch)
tree8d3a9545087bce774d5cbec4216512c585c8eeb4
parentae1f77e5e9aef59aed9cd5a146114e37a74e3316 (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.rs37
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};
21use ra_ide::{ 21use 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
264fn 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
254pub fn handle_workspace_symbol( 283pub fn handle_workspace_symbol(