1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
use base_db::{data::BibtexEntryTypeCategory, Document, Workspace};
use lsp_types::{
ClientCapabilities, DocumentSymbol, DocumentSymbolResponse, Location, WorkspaceSymbolResponse,
};
use crate::util::{capabilities::ClientCapabilitiesExt, line_index_ext::LineIndexExt};
pub fn document_symbols(
workspace: &Workspace,
document: &Document,
capabilities: &ClientCapabilities,
) -> DocumentSymbolResponse {
let symbols = symbols::document_symbols(workspace, document);
if capabilities.has_hierarchical_document_symbol_support() {
let results = symbols
.into_iter()
.filter_map(|symbol| convert_to_nested_symbol(symbol, document))
.collect();
DocumentSymbolResponse::Nested(results)
} else {
let mut results = Vec::new();
for symbol in symbols {
convert_to_flat_symbols(symbol, document, &mut results);
}
DocumentSymbolResponse::Flat(results)
}
}
pub fn workspace_symbols(workspace: &Workspace, query: &str) -> WorkspaceSymbolResponse {
let symbols = symbols::workspace_symbols(workspace, query);
let mut results = Vec::new();
for symbols::SymbolLocation { symbol, document } in symbols {
convert_to_flat_symbols(symbol, document, &mut results);
}
WorkspaceSymbolResponse::Flat(results)
}
fn convert_to_nested_symbol(
symbol: symbols::Symbol,
document: &Document,
) -> Option<DocumentSymbol> {
let children = symbol
.children
.into_iter()
.filter_map(|child| convert_to_nested_symbol(child, document))
.collect();
#[allow(deprecated)]
Some(DocumentSymbol {
name: symbol.name,
detail: symbol.label.map(|label| label.text),
kind: convert_symbol_kind(symbol.kind),
deprecated: Some(false),
range: document.line_index.line_col_lsp_range(symbol.full_range)?,
selection_range: document
.line_index
.line_col_lsp_range(symbol.selection_range)?,
children: Some(children),
tags: None,
})
}
fn convert_to_flat_symbols(
symbol: symbols::Symbol,
document: &Document,
results: &mut Vec<lsp_types::SymbolInformation>,
) {
let Some(range) = document.line_index.line_col_lsp_range(symbol.full_range) else {
return;
};
#[allow(deprecated)]
results.push(lsp_types::SymbolInformation {
name: symbol.name,
kind: convert_symbol_kind(symbol.kind),
deprecated: Some(false),
location: Location::new(document.uri.clone(), range),
tags: None,
container_name: None,
});
for child in symbol.children {
convert_to_flat_symbols(child, document, results);
}
}
fn convert_symbol_kind(value: symbols::SymbolKind) -> lsp_types::SymbolKind {
match value {
symbols::SymbolKind::Section => lsp_types::SymbolKind::MODULE,
symbols::SymbolKind::Figure => lsp_types::SymbolKind::METHOD,
symbols::SymbolKind::Algorithm => lsp_types::SymbolKind::METHOD,
symbols::SymbolKind::Table => lsp_types::SymbolKind::METHOD,
symbols::SymbolKind::Listing => lsp_types::SymbolKind::METHOD,
symbols::SymbolKind::Enumeration => lsp_types::SymbolKind::ENUM,
symbols::SymbolKind::EnumerationItem => lsp_types::SymbolKind::ENUM_MEMBER,
symbols::SymbolKind::Theorem => lsp_types::SymbolKind::VARIABLE,
symbols::SymbolKind::Equation => lsp_types::SymbolKind::CONSTANT,
symbols::SymbolKind::Entry(category) => match category {
BibtexEntryTypeCategory::Misc => lsp_types::SymbolKind::INTERFACE,
BibtexEntryTypeCategory::String => lsp_types::SymbolKind::STRING,
BibtexEntryTypeCategory::Article => lsp_types::SymbolKind::EVENT,
BibtexEntryTypeCategory::Thesis => lsp_types::SymbolKind::OBJECT,
BibtexEntryTypeCategory::Book => lsp_types::SymbolKind::STRUCT,
BibtexEntryTypeCategory::Part => lsp_types::SymbolKind::OPERATOR,
BibtexEntryTypeCategory::Collection => lsp_types::SymbolKind::TYPE_PARAMETER,
},
symbols::SymbolKind::Field => lsp_types::SymbolKind::FIELD,
}
}
|