summaryrefslogtreecommitdiff
path: root/support/texlab/crates/symbols/src/workspace.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/symbols/src/workspace.rs')
-rw-r--r--support/texlab/crates/symbols/src/workspace.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/support/texlab/crates/symbols/src/workspace.rs b/support/texlab/crates/symbols/src/workspace.rs
new file mode 100644
index 0000000000..ad9206b2c5
--- /dev/null
+++ b/support/texlab/crates/symbols/src/workspace.rs
@@ -0,0 +1,47 @@
+mod sort;
+
+use std::cmp::Reverse;
+
+use base_db::Workspace;
+
+use crate::{document_symbols, types::SymbolLocation, SymbolKind};
+
+use self::sort::ProjectOrdering;
+
+pub fn workspace_symbols<'a>(workspace: &'a Workspace, query: &str) -> Vec<SymbolLocation<'a>> {
+ let query = query.split_whitespace().collect::<Vec<_>>();
+ let mut results = Vec::new();
+
+ for document in workspace.iter() {
+ let mut buf = Vec::new();
+ let symbols = document_symbols(workspace, document);
+ for symbol in symbols {
+ symbol.flatten(&mut buf);
+ }
+
+ for symbol in buf
+ .into_iter()
+ .filter(|symbol| symbol.kind != SymbolKind::Field)
+ {
+ let keywords = symbol.keywords();
+ if query.is_empty()
+ || itertools::iproduct!(keywords.iter(), query.iter())
+ .any(|(keyword, query)| keyword.eq_ignore_ascii_case(query))
+ {
+ results.push(SymbolLocation { document, symbol });
+ }
+ }
+ }
+
+ let ordering = ProjectOrdering::from(workspace);
+ results.sort_by_key(|item| {
+ let index = ordering.get(&item.document.uri);
+ let range = item.symbol.full_range;
+ (index, range.start(), Reverse(range.end()))
+ });
+
+ results
+}
+
+#[cfg(test)]
+mod tests;