summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/symbol/bibtex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/features/symbol/bibtex.rs')
-rw-r--r--support/texlab/src/features/symbol/bibtex.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/support/texlab/src/features/symbol/bibtex.rs b/support/texlab/src/features/symbol/bibtex.rs
new file mode 100644
index 0000000000..e030195880
--- /dev/null
+++ b/support/texlab/src/features/symbol/bibtex.rs
@@ -0,0 +1,88 @@
+use cancellation::CancellationToken;
+
+use crate::{
+ syntax::{
+ bibtex::{self, HasType},
+ CstNode,
+ },
+ BibtexEntryTypeCategory, LineIndexExt, WorkspaceSubset, LANGUAGE_DATA,
+};
+
+use super::types::{InternalSymbol, InternalSymbolKind};
+
+pub fn find_bibtex_symbols(
+ subset: &WorkspaceSubset,
+ buf: &mut Vec<InternalSymbol>,
+ token: &CancellationToken,
+) -> Option<()> {
+ let main_document = subset.documents.first()?;
+ let data = main_document.data.as_bibtex()?;
+
+ for node in data.root.children() {
+ if token.is_canceled() {
+ return None;
+ }
+
+ if let Some(string) = bibtex::String::cast(node) {
+ if let Some(name) = string.name() {
+ buf.push(InternalSymbol {
+ name: name.text().into(),
+ label: None,
+ kind: InternalSymbolKind::String,
+ deprecated: false,
+ full_range: main_document
+ .line_index
+ .line_col_lsp_range(string.small_range()),
+ selection_range: main_document
+ .line_index
+ .line_col_lsp_range(name.text_range()),
+ children: Vec::new(),
+ })
+ }
+ } else if let Some(entry) = bibtex::Entry::cast(node) {
+ if let Some(ty) = entry.ty() {
+ if let Some(key) = entry.key() {
+ let mut children = Vec::new();
+ for field in entry.fields() {
+ if let Some(name) = field.name() {
+ let symbol = InternalSymbol {
+ name: name.text().to_string(),
+ label: None,
+ kind: InternalSymbolKind::Field,
+ deprecated: false,
+ full_range: main_document
+ .line_index
+ .line_col_lsp_range(field.small_range()),
+ selection_range: main_document
+ .line_index
+ .line_col_lsp_range(name.text_range()),
+ children: Vec::new(),
+ };
+ children.push(symbol);
+ }
+ }
+
+ let category = LANGUAGE_DATA
+ .find_entry_type(&ty.text()[1..])
+ .map(|ty| ty.category)
+ .unwrap_or(BibtexEntryTypeCategory::Misc);
+
+ buf.push(InternalSymbol {
+ name: key.text().to_string(),
+ label: None,
+ kind: InternalSymbolKind::Entry(category),
+ deprecated: false,
+ full_range: main_document
+ .line_index
+ .line_col_lsp_range(entry.small_range()),
+ selection_range: main_document
+ .line_index
+ .line_col_lsp_range(key.text_range()),
+ children,
+ });
+ }
+ }
+ }
+ }
+ Some(())
+}