diff options
Diffstat (limited to 'support/texlab/src/features/completion/citation.rs')
-rw-r--r-- | support/texlab/src/features/completion/citation.rs | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/support/texlab/src/features/completion/citation.rs b/support/texlab/src/features/completion/citation.rs index 6df3364099..0a7cc26b10 100644 --- a/support/texlab/src/features/completion/citation.rs +++ b/support/texlab/src/features/completion/citation.rs @@ -26,12 +26,14 @@ pub fn complete_citations<'a>( let token = context.cursor.as_latex()?; let range = if token.kind() == latex::WORD { - token.text_range() + latex::Key::cast(token.parent()) + .map(|key| key.small_range()) + .or_else(|| latex::Text::cast(token.parent()).map(|text| text.small_range()))? } else { TextRange::empty(context.offset) }; - check_citation(context, token).or_else(|| check_acronym(token))?; + check_citation(context).or_else(|| check_acronym(context))?; for document in &context.request.subset.documents { if let Some(data) = document.data.as_bibtex() { for entry in data.root.children().filter_map(bibtex::Entry::cast) { @@ -46,20 +48,17 @@ pub fn complete_citations<'a>( Some(()) } -fn check_citation( - context: &CursorContext<CompletionParams>, - token: &latex::SyntaxToken, -) -> Option<()> { - let group = latex::CurlyGroupWordList::cast(token.parent()) - .filter(|group| context.is_inside_latex_curly(group))?; +fn check_citation(context: &CursorContext<CompletionParams>) -> Option<()> { + let (_, _, group) = context.find_curly_group_word_list()?; latex::Citation::cast(group.syntax().parent()?)?; Some(()) } -fn check_acronym(token: &latex::SyntaxToken) -> Option<()> { +fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> { + let token = context.cursor.as_latex()?; + let pair = token.ancestors().find_map(latex::KeyValuePair::cast)?; - let mut key_words = pair.key()?.words(); - if key_words.next()?.text() != "cite" || key_words.next().is_some() { + if pair.key()?.to_string() != "cite" { return None; } @@ -72,7 +71,7 @@ fn make_item<'a>( entry: bibtex::Entry<'a>, range: TextRange, ) -> Option<InternalCompletionItem<'a>> { - let key = entry.key()?.text(); + let key = entry.key()?.to_string(); let ty = LANGUAGE_DATA .find_entry_type(&entry.ty()?.text()[1..]) .map(|ty| Structure::Entry(ty.category)) @@ -98,7 +97,7 @@ fn make_item<'a>( range, InternalCompletionItemData::Citation { uri: Arc::clone(&document.uri), - key: key.into(), + key, text, ty, }, @@ -171,6 +170,29 @@ mod tests { } #[test] + fn test_latex_two_words() { + let request = FeatureTester::builder() + .files(vec![ + ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"), + ("main.bib", "@article{foo bar,}"), + ]) + .main("main.tex") + .line(1) + .character(6) + .build() + .completion(); + + let context = CursorContext::new(request); + let mut actual_items = Vec::new(); + complete_citations(&context, &mut actual_items, CancellationToken::none()); + + assert!(!actual_items.is_empty()); + for item in actual_items { + assert_eq!(item.range, TextRange::new(32.into(), 35.into())); + } + } + + #[test] fn test_latex_open_brace() { let request = FeatureTester::builder() .files(vec![ @@ -241,4 +263,30 @@ mod tests { assert_eq!(item.range, TextRange::new(54.into(), 54.into())); } } + + #[test] + fn test_latex_acronym_two_words() { + let request = FeatureTester::builder() + .files(vec![ + ( + "main.tex", + "\\addbibresource{main.bib}\n\\DeclareAcronym{foo}{cite={\na b}}", + ), + ("main.bib", "@article{foo,}"), + ]) + .main("main.tex") + .line(2) + .character(0) + .build() + .completion(); + + let context = CursorContext::new(request); + let mut actual_items = Vec::new(); + complete_citations(&context, &mut actual_items, CancellationToken::none()); + + assert!(!actual_items.is_empty()); + for item in actual_items { + assert_eq!(item.range, TextRange::new(54.into(), 57.into())); + } + } } |