diff options
Diffstat (limited to 'support/texlab/crates/symbols/src/document/bib.rs')
-rw-r--r-- | support/texlab/crates/symbols/src/document/bib.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/support/texlab/crates/symbols/src/document/bib.rs b/support/texlab/crates/symbols/src/document/bib.rs new file mode 100644 index 0000000000..1e5d934a0d --- /dev/null +++ b/support/texlab/crates/symbols/src/document/bib.rs @@ -0,0 +1,64 @@ +use base_db::data::{BibtexEntryType, BibtexEntryTypeCategory}; +use rowan::ast::AstNode; +use syntax::bibtex::{self, HasName, HasType}; + +use crate::{Symbol, SymbolKind}; + +#[derive(Debug)] +pub struct SymbolBuilder; + +impl SymbolBuilder { + pub fn visit(&self, node: &bibtex::SyntaxNode) -> Option<Symbol> { + if let Some(string) = bibtex::StringDef::cast(node.clone()) { + self.visit_string(&string) + } else if let Some(entry) = bibtex::Entry::cast(node.clone()) { + self.visit_entry(&entry) + } else { + None + } + } + + fn visit_string(&self, string: &bibtex::StringDef) -> Option<Symbol> { + let name = string.name_token()?; + Some(Symbol { + name: name.text().into(), + kind: SymbolKind::Entry(BibtexEntryTypeCategory::String), + label: None, + full_range: string.syntax().text_range(), + selection_range: name.text_range(), + children: Vec::new(), + }) + } + + fn visit_entry(&self, entry: &bibtex::Entry) -> Option<Symbol> { + let ty = entry.type_token()?; + let key = entry.name_token()?; + + let children = entry + .fields() + .filter_map(|field| self.visit_field(&field)) + .collect(); + + let category = BibtexEntryType::find(&ty.text()[1..]) + .map_or(BibtexEntryTypeCategory::Misc, |ty| ty.category); + + Some(Symbol { + name: key.text().into(), + kind: SymbolKind::Entry(category), + label: None, + full_range: entry.syntax().text_range(), + selection_range: key.text_range(), + children, + }) + } + + fn visit_field(&self, field: &bibtex::Field) -> Option<Symbol> { + let name = field.name_token()?; + Some(Symbol::new_simple( + name.text().into(), + SymbolKind::Field, + field.syntax().text_range(), + name.text_range(), + )) + } +} |