Skip to content

Commit 0619c67

Browse files
committed
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 microsoft/language-server-protocol#538 (comment) for more context. Found while looking at #144
1 parent ae1f77e commit 0619c67

File tree

1 file changed

+33
-4
lines changed

1 file changed

+33
-4
lines changed

crates/rust-analyzer/src/main_loop/handlers.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use lsp_types::{
1616
Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse,
1717
Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams,
1818
SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier,
19-
TextEdit, WorkspaceEdit,
19+
TextEdit, Url, WorkspaceEdit,
2020
};
2121
use ra_ide::{
2222
Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
@@ -219,6 +219,7 @@ pub fn handle_document_symbol(
219219
let _p = profile("handle_document_symbol");
220220
let file_id = params.text_document.try_conv_with(&world)?;
221221
let line_index = world.analysis().file_line_index(file_id)?;
222+
let url = file_id.try_conv_with(&world)?;
222223

223224
let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();
224225

@@ -234,10 +235,10 @@ pub fn handle_document_symbol(
234235
};
235236
parents.push((doc_symbol, symbol.parent));
236237
}
237-
let mut res = Vec::new();
238+
let mut document_symbols = Vec::new();
238239
while let Some((node, parent)) = parents.pop() {
239240
match parent {
240-
None => res.push(node),
241+
None => document_symbols.push(node),
241242
Some(i) => {
242243
let children = &mut parents[i].0.children;
243244
if children.is_none() {
@@ -248,7 +249,35 @@ pub fn handle_document_symbol(
248249
}
249250
}
250251

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+
}
252281
}
253282

254283
pub fn handle_workspace_symbol(

0 commit comments

Comments
 (0)