summaryrefslogtreecommitdiff
path: root/support/texlab/src/completion/bibtex
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/completion/bibtex')
-rw-r--r--support/texlab/src/completion/bibtex/cmd.rs177
-rw-r--r--support/texlab/src/completion/bibtex/command.rs112
-rw-r--r--support/texlab/src/completion/bibtex/entry_type.rs255
-rw-r--r--support/texlab/src/completion/bibtex/field_name.rs308
-rw-r--r--support/texlab/src/completion/bibtex/mod.rs2
5 files changed, 471 insertions, 383 deletions
diff --git a/support/texlab/src/completion/bibtex/cmd.rs b/support/texlab/src/completion/bibtex/cmd.rs
new file mode 100644
index 0000000000..eab905386a
--- /dev/null
+++ b/support/texlab/src/completion/bibtex/cmd.rs
@@ -0,0 +1,177 @@
+use crate::{
+ completion::types::{Item, ItemData},
+ components::COMPONENT_DATABASE,
+ feature::FeatureRequest,
+ protocol::{CompletionParams, RangeExt},
+ syntax::SyntaxNode,
+ workspace::DocumentContent,
+};
+
+pub async fn complete_bibtex_commands<'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;
+ if let Some(cmd) = tree
+ .find(pos)
+ .into_iter()
+ .last()
+ .and_then(|node| tree.as_command(node))
+ {
+ if cmd.token.range().contains(pos) && cmd.token.start().character != pos.character {
+ let mut range = cmd.range();
+ range.start.character += 1;
+ for cmd in &COMPONENT_DATABASE.kernel().commands {
+ let item = Item::new(
+ range,
+ ItemData::ComponentCommand {
+ name: &cmd.name,
+ image: cmd.image.as_deref(),
+ glyph: cmd.glyph.as_deref(),
+ file_names: &[],
+ },
+ );
+ items.push(item);
+ }
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{feature::FeatureTester, protocol::Range};
+ use indoc::indoc;
+
+ #[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_commands(&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_commands(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[tokio::test]
+ async fn inside_comment() {
+ let req = FeatureTester::new()
+ .file("main.bib", r#"\"#)
+ .main("main.bib")
+ .position(0, 1)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_commands(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[tokio::test]
+ async fn inside_command() {
+ let req = FeatureTester::new()
+ .file(
+ "main.bib",
+ indoc!(
+ r#"
+ @article{foo, bar=
+ \}
+ "#
+ ),
+ )
+ .main("main.bib")
+ .position(1, 1)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_commands(&req, &mut actual_items).await;
+
+ assert!(!actual_items.is_empty());
+ assert_eq!(actual_items[0].range, Range::new_simple(1, 1, 1, 2));
+ }
+
+ #[tokio::test]
+ async fn start_of_command() {
+ let req = FeatureTester::new()
+ .file(
+ "main.bib",
+ indoc!(
+ r#"
+ @article{foo, bar=
+ \}
+ "#
+ ),
+ )
+ .main("main.bib")
+ .position(1, 0)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_commands(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[tokio::test]
+ async fn inside_text() {
+ let req = FeatureTester::new()
+ .file(
+ "main.bib",
+ indoc!(
+ r#"
+ @article{foo, bar=
+ }
+ "#
+ ),
+ )
+ .main("main.bib")
+ .position(1, 0)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_commands(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[tokio::test]
+ async fn inside_latex_command() {
+ let req = FeatureTester::new()
+ .file("main.tex", r#"\"#)
+ .main("main.tex")
+ .position(0, 1)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_commands(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
+ }
+}
diff --git a/support/texlab/src/completion/bibtex/command.rs b/support/texlab/src/completion/bibtex/command.rs
deleted file mode 100644
index 5d61a8e568..0000000000
--- a/support/texlab/src/completion/bibtex/command.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-use crate::completion::factory::{self, LatexComponentId};
-use crate::completion::DATABASE;
-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 BibtexCommandCompletionProvider;
-
-impl FeatureProvider for BibtexCommandCompletionProvider {
- type Params = CompletionParams;
- type Output = Vec<CompletionItem>;
-
- #[boxed]
- async fn execute<'a>(&'a self, request: &'a FeatureRequest<Self::Params>) -> Self::Output {
- let mut items = Vec::new();
- if let SyntaxTree::Bibtex(tree) = &request.document().tree {
- let position = request.params.text_document_position.position;
- if let Some(BibtexNode::Command(command)) = tree.find(position).last() {
- if command.token.range().contains(position)
- && command.token.start().character != position.character
- {
- let mut range = command.range();
- range.start.character += 1;
-
- let component = LatexComponentId::kernel();
- for command in &DATABASE.kernel().commands {
- let text_edit = TextEdit::new(range, (&command.name).into());
- let item = factory::command(
- request,
- (&command.name).into(),
- command.image.as_ref().map(AsRef::as_ref),
- command.glyph.as_ref().map(AsRef::as_ref),
- text_edit,
- &component,
- );
- items.push(item);
- }
- }
- }
- }
- items
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use lsp_types::{Position, Range};
-
- #[test]
- fn test_inside_command() {
- let items = test_feature(
- BibtexCommandCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo, bar=\n\\}")],
- main_file: "foo.bib",
- position: Position::new(1, 1),
- ..FeatureSpec::default()
- },
- );
- assert!(!items.is_empty());
- assert_eq!(
- items[0].text_edit.as_ref().map(|edit| edit.range),
- Some(Range::new_simple(1, 1, 1, 2))
- );
- }
-
- #[test]
- fn test_start_of_command() {
- let items = test_feature(
- BibtexCommandCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo, bar=\n\\}")],
- main_file: "foo.bib",
- position: Position::new(1, 0),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
- }
-
- #[test]
- fn test_inside_text() {
- let items = test_feature(
- BibtexCommandCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo, bar=\n}")],
- main_file: "foo.bib",
- position: Position::new(1, 0),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
- }
-
- #[test]
- fn test_latex() {
- let items = test_feature(
- BibtexCommandCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.tex", "\\")],
- main_file: "foo.tex",
- position: Position::new(0, 1),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
- }
-}
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());
}
}
diff --git a/support/texlab/src/completion/bibtex/field_name.rs b/support/texlab/src/completion/bibtex/field_name.rs
index abddad4f5a..039cc5d6b3 100644
--- a/support/texlab/src/completion/bibtex/field_name.rs
+++ b/support/texlab/src/completion/bibtex/field_name.rs
@@ -1,176 +1,190 @@
-use crate::completion::factory;
-use crate::range::RangeExt;
-use crate::syntax::*;
-use crate::workspace::*;
-use futures_boxed::boxed;
-use lsp_types::{CompletionItem, CompletionParams, Range, TextEdit};
-
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub struct BibtexFieldNameCompletionProvider;
-
-impl FeatureProvider for BibtexFieldNameCompletionProvider {
- 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;
- match tree.find(position).last() {
- Some(BibtexNode::Field(field)) => {
- if field.name.range().contains(position) {
- return make_items(request, field.name.range());
- }
+use crate::{
+ completion::types::{Item, ItemData},
+ feature::FeatureRequest,
+ protocol::{CompletionParams, Range, RangeExt},
+ syntax::{bibtex, SyntaxNode, LANGUAGE_DATA},
+ workspace::DocumentContent,
+};
+
+pub async fn complete_bibtex_fields<'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;
+ match tree
+ .find(pos)
+ .into_iter()
+ .last()
+ .map(|node| &tree.graph[node])
+ {
+ Some(bibtex::Node::Field(field)) => {
+ if field.name.range().contains(pos) {
+ make_items(items, field.name.range());
+ return;
}
- Some(BibtexNode::Entry(entry)) => {
- if !entry.is_comment() && !entry.ty.range().contains(position) {
- let edit_range = Range::new(position, position);
- if let Some(key) = &entry.key {
- if !key.range().contains(position) {
- return make_items(request, edit_range);
- }
- } else {
- return make_items(request, edit_range);
+ }
+ Some(bibtex::Node::Entry(entry)) => {
+ if !entry.is_comment() && !entry.ty.range().contains(pos) {
+ let range = Range::new(pos, pos);
+ if let Some(key) = &entry.key {
+ if !key.range().contains(pos) {
+ make_items(items, range);
+ return;
}
+ } else {
+ make_items(items, range);
+ return;
}
}
- _ => {}
}
+ _ => (),
}
- Vec::new()
}
}
-fn make_items(
- request: &FeatureRequest<CompletionParams>,
- edit_range: Range,
-) -> Vec<CompletionItem> {
- let mut items = Vec::new();
+fn make_items(items: &mut Vec<Item>, range: Range) {
for field in &LANGUAGE_DATA.fields {
- let text_edit = TextEdit::new(edit_range, (&field.name).into());
- let item = factory::field_name(request, field, text_edit);
+ let item = Item::new(range, ItemData::Field { field });
items.push(item);
}
- items
}
#[cfg(test)]
mod tests {
use super::*;
- use lsp_types::Position;
-
- #[test]
- fn test_inside_first_field() {
- let items = test_feature(
- BibtexFieldNameCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo,\nbar}")],
- main_file: "foo.bib",
- position: Position::new(1, 1),
- ..FeatureSpec::default()
- },
- );
- assert!(!items.is_empty());
- assert_eq!(
- items[0].text_edit.as_ref().map(|edit| edit.range),
- Some(Range::new_simple(1, 0, 1, 3))
- );
+ use crate::{feature::FeatureTester, protocol::Range};
+ use indoc::indoc;
+
+ #[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_fields(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
- #[test]
- fn test_inside_second_field() {
- let items = test_feature(
- BibtexFieldNameCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file(
- "foo.bib",
- "@article{foo, bar = {baz}, qux}",
- )],
- main_file: "foo.bib",
- position: Position::new(0, 27),
- ..FeatureSpec::default()
- },
- );
- assert!(!items.is_empty());
- assert_eq!(
- items[0].text_edit.as_ref().map(|edit| edit.range),
- Some(Range::new_simple(0, 27, 0, 30))
- );
+ #[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_fields(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
- #[test]
- fn test_inside_entry() {
- let items = test_feature(
- BibtexFieldNameCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo, \n}")],
- main_file: "foo.bib",
- position: Position::new(1, 0),
- ..FeatureSpec::default()
- },
- );
- assert!(!items.is_empty());
- assert_eq!(
- items[0].text_edit.as_ref().map(|edit| edit.range),
- Some(Range::new_simple(1, 0, 1, 0))
- );
+ #[tokio::test]
+ async fn inside_first_field() {
+ let req = FeatureTester::new()
+ .file(
+ "main.bib",
+ indoc!(
+ r#"
+ @article{foo,
+ bar}
+ "#
+ ),
+ )
+ .main("main.bib")
+ .position(1, 1)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_fields(&req, &mut actual_items).await;
+
+ assert!(!actual_items.is_empty());
+ assert_eq!(actual_items[0].range, Range::new_simple(1, 0, 1, 3));
}
- #[test]
- fn test_inside_content() {
- let items = test_feature(
- BibtexFieldNameCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo,\nbar = {baz}}")],
- main_file: "foo.bib",
- position: Position::new(1, 7),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ #[tokio::test]
+ async fn inside_second_field() {
+ let req = FeatureTester::new()
+ .file("main.bib", "@article{foo, bar = {baz}, qux}")
+ .main("main.bib")
+ .position(0, 27)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_fields(&req, &mut actual_items).await;
+
+ assert!(!actual_items.is_empty());
+ assert_eq!(actual_items[0].range, Range::new_simple(0, 27, 0, 30));
+ }
+
+ #[tokio::test]
+ async fn inside_entry() {
+ let req = FeatureTester::new()
+ .file(
+ "main.bib",
+ indoc!(
+ r#"
+ @article{foo,
+ }
+ "#
+ ),
+ )
+ .main("main.bib")
+ .position(1, 0)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_fields(&req, &mut actual_items).await;
+
+ assert!(!actual_items.is_empty());
+ assert_eq!(actual_items[0].range, Range::new_simple(1, 0, 1, 0));
}
- #[test]
- fn test_inside_entry_type() {
- let items = test_feature(
- BibtexFieldNameCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.bib", "@article{foo,}")],
- main_file: "foo.bib",
- position: Position::new(0, 3),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ #[tokio::test]
+ async fn inside_content() {
+ let req = FeatureTester::new()
+ .file(
+ "main.bib",
+ indoc!(
+ r#"
+ @article{foo,
+ bar = {baz}}
+ "#
+ ),
+ )
+ .main("main.bib")
+ .position(1, 7)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_fields(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
- // TODO: Improve behavior of this provider
- //
- // #[test]
- // fn test_after_equals_sign() {
- // let items = test_feature(
- // BibtexFieldNameCompletionProvider,
- // FeatureSpec {
- // files: vec![FeatureSpec::file("foo.bib", "@article{foo, bar = \n}")],
- // main_file: "foo.bib",
- // position: Position::new(1, 0),
- // ..FeatureSpec::default()
- // },
- // );
- // assert!(items.is_empty());
- // }
-
- #[test]
- fn test_inside_latex() {
- let items = test_feature(
- BibtexFieldNameCompletionProvider,
- FeatureSpec {
- files: vec![FeatureSpec::file("foo.tex", "@article{foo,}")],
- main_file: "foo.tex",
- position: Position::new(0, 3),
- ..FeatureSpec::default()
- },
- );
- assert!(items.is_empty());
+ #[tokio::test]
+ async fn inside_entry_type() {
+ let req = FeatureTester::new()
+ .file("main.bib", "@article{foo,}")
+ .main("main.bib")
+ .position(0, 3)
+ .test_completion_request()
+ .await;
+ let mut actual_items = Vec::new();
+
+ complete_bibtex_fields(&req, &mut actual_items).await;
+
+ assert!(actual_items.is_empty());
}
}
diff --git a/support/texlab/src/completion/bibtex/mod.rs b/support/texlab/src/completion/bibtex/mod.rs
index 9117d7f266..96f3a94932 100644
--- a/support/texlab/src/completion/bibtex/mod.rs
+++ b/support/texlab/src/completion/bibtex/mod.rs
@@ -1,3 +1,3 @@
-pub mod command;
+pub mod cmd;
pub mod entry_type;
pub mod field_name;