summaryrefslogtreecommitdiff
path: root/support/texlab/src/symbol/bibtex_entry.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/symbol/bibtex_entry.rs')
-rw-r--r--support/texlab/src/symbol/bibtex_entry.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/support/texlab/src/symbol/bibtex_entry.rs b/support/texlab/src/symbol/bibtex_entry.rs
new file mode 100644
index 0000000000..f19c2fb734
--- /dev/null
+++ b/support/texlab/src/symbol/bibtex_entry.rs
@@ -0,0 +1,147 @@
+use super::{LatexSymbol, LatexSymbolKind};
+use crate::syntax::*;
+use crate::workspace::*;
+use futures_boxed::boxed;
+use lsp_types::*;
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct BibtexEntrySymbolProvider;
+
+impl FeatureProvider for BibtexEntrySymbolProvider {
+ type Params = DocumentSymbolParams;
+ type Output = Vec<LatexSymbol>;
+
+ #[boxed]
+ async fn execute<'a>(&'a self, request: &'a FeatureRequest<Self::Params>) -> Self::Output {
+ let mut symbols = Vec::new();
+ if let SyntaxTree::Bibtex(tree) = &request.document().tree {
+ for entry in tree
+ .entries()
+ .iter()
+ .filter(|entry| !entry.is_comment())
+ .filter(|entry| entry.key.is_some())
+ {
+ let category = LANGUAGE_DATA
+ .find_entry_type(&entry.ty.text()[1..])
+ .map(|ty| ty.category)
+ .unwrap_or(BibtexEntryTypeCategory::Misc);
+
+ let key = entry.key.as_ref().unwrap();
+ let symbol = LatexSymbol {
+ name: key.text().to_owned(),
+ label: None,
+ kind: LatexSymbolKind::Entry(category),
+ deprecated: false,
+ full_range: entry.range(),
+ selection_range: key.range(),
+ children: Self::field_symbols(&entry),
+ };
+ symbols.push(symbol);
+ }
+ }
+ symbols
+ }
+}
+
+impl BibtexEntrySymbolProvider {
+ fn field_symbols(entry: &BibtexEntry) -> Vec<LatexSymbol> {
+ let mut symbols = Vec::new();
+ for field in &entry.fields {
+ let symbol = LatexSymbol {
+ name: field.name.text().to_owned(),
+ label: None,
+ kind: LatexSymbolKind::Field,
+ deprecated: false,
+ full_range: field.range(),
+ selection_range: field.name.range(),
+ children: Vec::new(),
+ };
+ symbols.push(symbol);
+ }
+ symbols
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::range::RangeExt;
+
+ #[test]
+ fn test_entry() {
+ let symbols = test_feature(
+ BibtexEntrySymbolProvider,
+ FeatureSpec {
+ files: vec![FeatureSpec::file(
+ "foo.bib",
+ "@article{key, foo = bar, baz = qux}",
+ )],
+ main_file: "foo.bib",
+ ..FeatureSpec::default()
+ },
+ );
+ assert_eq!(
+ symbols,
+ vec![LatexSymbol {
+ name: "key".into(),
+ label: None,
+ kind: LatexSymbolKind::Entry(BibtexEntryTypeCategory::Article),
+ deprecated: false,
+ full_range: Range::new_simple(0, 0, 0, 35),
+ selection_range: Range::new_simple(0, 9, 0, 12),
+ children: vec![
+ LatexSymbol {
+ name: "foo".into(),
+ label: None,
+ kind: LatexSymbolKind::Field,
+ deprecated: false,
+ full_range: Range::new_simple(0, 14, 0, 24),
+ selection_range: Range::new_simple(0, 14, 0, 17),
+ children: Vec::new(),
+ },
+ LatexSymbol {
+ name: "baz".into(),
+ label: None,
+ kind: LatexSymbolKind::Field,
+ deprecated: false,
+ full_range: Range::new_simple(0, 25, 0, 34),
+ selection_range: Range::new_simple(0, 25, 0, 28),
+ children: Vec::new(),
+ },
+ ],
+ }]
+ );
+ }
+
+ #[test]
+ fn test_comment() {
+ let symbols = test_feature(
+ BibtexEntrySymbolProvider,
+ FeatureSpec {
+ files: vec![FeatureSpec::file(
+ "foo.bib",
+ "@comment{key, foo = bar, baz = qux}",
+ )],
+ main_file: "foo.bib",
+ ..FeatureSpec::default()
+ },
+ );
+ assert_eq!(symbols, Vec::new());
+ }
+
+ #[test]
+ fn test_latex() {
+ let symbols = test_feature(
+ BibtexEntrySymbolProvider,
+ FeatureSpec {
+ files: vec![FeatureSpec::file(
+ "foo.tex",
+ "@article{key, foo = bar, baz = qux}",
+ )],
+ main_file: "foo.tex",
+ ..FeatureSpec::default()
+ },
+ );
+ assert_eq!(symbols, Vec::new());
+ }
+}