diff options
Diffstat (limited to 'support/texlab/crates/completion/src/providers/label_def.rs')
-rw-r--r-- | support/texlab/crates/completion/src/providers/label_def.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/support/texlab/crates/completion/src/providers/label_def.rs b/support/texlab/crates/completion/src/providers/label_def.rs new file mode 100644 index 0000000000..a8966ed62f --- /dev/null +++ b/support/texlab/crates/completion/src/providers/label_def.rs @@ -0,0 +1,60 @@ +use base_db::{ + semantics::{ + tex::{Label, LabelKind}, + Span, + }, + util::queries::Object, +}; +use rowan::ast::AstNode; +use rustc_hash::FxHashSet; +use syntax::latex; + +use crate::{ + util::{find_curly_group_word, CompletionBuilder}, + CompletionParams, +}; + +pub fn complete_label_definitions<'a>( + params: &'a CompletionParams<'a>, + builder: &mut CompletionBuilder<'a>, +) -> Option<()> { + let cursor = find_definition(params)?; + + let label_defs: FxHashSet<&str> = Label::find_all(¶ms.feature.project) + .filter(|(_, label)| label.kind == LabelKind::Definition) + .map(|(_, label)| label.name_text()) + .collect(); + + let label_refs: FxHashSet<&str> = Label::find_all(¶ms.feature.project) + .filter(|(_, label)| label.kind == LabelKind::Reference) + .map(|(_, label)| label.name_text()) + .collect(); + + for label in label_refs.difference(&label_defs) { + let Some(score) = builder.matcher.score(label, &cursor.text) else { + continue; + }; + + let data = crate::LabelData { + name: label, + header: None, + footer: None, + object: None, + keywords: label.to_string(), + }; + + builder.items.push(crate::CompletionItem::new_simple( + score, + cursor.range, + crate::CompletionItemData::Label(data), + )); + } + + Some(()) +} + +fn find_definition(params: &CompletionParams) -> Option<Span> { + let (cursor, group) = find_curly_group_word(params)?; + latex::LabelDefinition::cast(group.syntax().parent()?)?; + Some(cursor) +} |