summaryrefslogtreecommitdiff
path: root/support/texlab/src/completion/bibtex/entry_type.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/completion/bibtex/entry_type.rs')
-rw-r--r--support/texlab/src/completion/bibtex/entry_type.rs255
1 files changed, 132 insertions, 123 deletions
diff --git a/support/texlab/src/completion/bibtex/entry_type.rs b/support/texlab/src/completion/bibtex/entry_type.rs
index 8deabdb33e..e3b12ef00d 100644
--- a/support/texlab/src/completion/bibtex/entry_type.rs
+++ b/support/texlab/src/completion/bibtex/entry_type.rs
@@ -1,155 +1,164 @@
-use crate::completion::factory;
-use crate::range::RangeExt;
-use crate::syntax::*;
-use crate::workspace::*;
-use futures_boxed::boxed;
-use lsp_types::*;
-
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub struct BibtexEntryTypeCompletionProvider;
-
-impl FeatureProvider for BibtexEntryTypeCompletionProvider {
- type Params = CompletionParams;
- type Output = Vec<CompletionItem>;
-
- #[boxed]
- async fn execute<'a>(&'a self, request: &'a FeatureRequest<Self::Params>) -> Self::Output {
- if let SyntaxTree::Bibtex(tree) = &request.document().tree {
- let position = request.params.text_document_position.position;
- for declaration in &tree.root.children {
- match declaration {
- BibtexDeclaration::Preamble(preamble) => {
- if contains(&preamble.ty, position) {
- return make_items(request, preamble.ty.range());
- }
+use crate::{
+ completion::types::{Item, ItemData},
+ feature::FeatureRequest,
+ protocol::{CompletionParams, Position, Range, RangeExt},
+ syntax::{bibtex, SyntaxNode, LANGUAGE_DATA},
+ workspace::DocumentContent,
+};
+
+pub async fn complete_bibtex_entry_types<'a>(
+ req: &'a FeatureRequest<CompletionParams>,
+ items: &mut Vec<Item<'a>>,
+) {
+ if let DocumentContent::Bibtex(tree) = &req.current().content {
+ let pos = req.params.text_document_position.position;
+ for decl in tree.children(tree.root) {
+ match &tree.graph[decl] {
+ bibtex::Node::Preamble(preamble) => {
+ if contains(&preamble.ty, pos) {
+ make_items(items, preamble.ty.range());
+ return;
}
- BibtexDeclaration::String(string) => {
- if contains(&string.ty, position) {
- return make_items(request, string.ty.range());
- }
+ }
+ bibtex::Node::String(string) => {
+ if contains(&string.ty, pos) {
+ make_items(items, string.ty.range());
+ return;
}
- BibtexDeclaration::Entry(entry) => {
- if contains(&entry.ty, position) {
- return make_items(request, entry.ty.range());
- }
+ }
+ bibtex::Node::Entry(entry) => {
+ if contains(&entry.ty, pos) {
+ make_items(items, entry.ty.range());
+ return;
}
- BibtexDeclaration::Comment(_) => {}
}
+ _ => {}
}
}
- Vec::new()
}
}
-fn contains(ty: &BibtexToken, position: Position) -> bool {
- ty.range().contains(position) && ty.start().character != position.character
+fn contains(ty: &bibtex::Token, pos: Position) -> bool {
+ ty.range().contains(pos) && ty.start().character != pos.character
}
-fn make_items(request: &FeatureRequest<CompletionParams>, mut range: Range) -> Vec<CompletionItem> {
+fn make_items(items: &mut Vec<Item>, mut range: Range) {
range.start.character += 1;
- let mut items = Vec::new();
for ty in &LANGUAGE_DATA.entry_types {
- let text_edit = TextEdit::new(range, (&ty.name).into());
- let item = factory::entry_type(request, ty, text_edit);
+ let item = Item::new(range, ItemData::EntryType { ty });
items.push(item);
}
- items
}
#[cfg(test)]
mod tests {
use super::*;
- use lsp_types::Position;
-
- #[test]
- fn test_before_at_sign() {
- let items = test_feature(
- BibtexEntryTypeCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@")],
- main_file: "foo.bib",
- position: Position::new(0, 0),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ use crate::feature::FeatureTester;
+
+ #[tokio::test]
+ async fn empty_latex_document() {
+ let req = FeatureTester::new()
+ .file("main.tex", "")
+ .main("main.tex")
+ .position(0, 0)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[tokio::test]
+ async fn empty_bibtex_document() {
+ let req = FeatureTester::new()
+ .file("main.bib", "")
+ .main("main.bib")
+ .position(0, 0)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
- #[test]
- fn test_after_at_sign() {
- let items = test_feature(
- BibtexEntryTypeCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@")],
- main_file: "foo.bib",
- position: Position::new(0, 1),
- ..FeatureSpec::default()
- },
- );
- assert!(!items.is_empty());
- assert_eq!(
- items[0].text_edit.as_ref().map(|edit| edit.range),
- Some(Range::new_simple(0, 1, 0, 1))
- );
+ #[tokio::test]
+ async fn before_at_sign() {
+ let req = FeatureTester::new()
+ .file("main.bib", "@")
+ .main("main.bib")
+ .position(0, 0)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
- #[test]
- fn test_inside_entry_type() {
- let items = test_feature(
- BibtexEntryTypeCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@foo")],
- main_file: "foo.bib",
- position: Position::new(0, 2),
- ..FeatureSpec::default()
- },
- );
- assert!(!items.is_empty());
- assert_eq!(
- items[0].text_edit.as_ref().map(|edit| edit.range),
- Some(Range::new_simple(0, 1, 0, 4))
- );
+ #[tokio::test]
+ async fn after_at_sign() {
+ let req = FeatureTester::new()
+ .file("main.bib", "@")
+ .main("main.bib")
+ .position(0, 1)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(!actual_items.is_empty());
+ assert_eq!(actual_items[0].range, Range::new_simple(0, 1, 0, 1));
}
- #[test]
- fn test_inside_entry_key() {
- let items = test_feature(
- BibtexEntryTypeCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo,}")],
- main_file: "foo.bib",
- position: Position::new(0, 11),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ #[tokio::test]
+ async fn inside_entry_type() {
+ let req = FeatureTester::new()
+ .file("main.bib", "@foo")
+ .main("main.bib")
+ .position(0, 2)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(!actual_items.is_empty());
+ assert_eq!(actual_items[0].range, Range::new_simple(0, 1, 0, 4));
}
- #[test]
- fn test_inside_comments() {
- let items = test_feature(
- BibtexEntryTypeCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "foo")],
- main_file: "foo.bib",
- position: Position::new(0, 2),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ #[tokio::test]
+ async fn inside_entry_key() {
+ let req = FeatureTester::new()
+ .file("main.bib", "@article{foo,}")
+ .main("main.bib")
+ .position(0, 11)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
- #[test]
- fn test_latex() {
- let items = test_feature(
- BibtexEntryTypeCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.tex", "@")],
- main_file: "foo.tex",
- position: Position::new(0, 1),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ #[tokio::test]
+ async fn inside_comments() {
+ let req = FeatureTester::new()
+ .file("main.bib", "foo")
+ .main("main.bib")
+ .position(0, 2)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_entry_types(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
}