summaryrefslogtreecommitdiff
path: root/support/texlab/crates/references/src/command.rs
blob: f4504641f29f532cf884737203b983a60221a3e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use base_db::{semantics::Span, DocumentLocation};
use rowan::ast::AstNode;
use rustc_hash::FxHashSet;
use syntax::latex;

use crate::{Reference, ReferenceContext, ReferenceKind};

pub(super) fn find_all(context: &mut ReferenceContext) -> Option<()> {
    let data = context.params.feature.document.data.as_tex()?;
    let token = data
        .root_node()
        .token_at_offset(context.params.offset)
        .find(|token| token.kind() == latex::COMMAND_NAME)?;

    let project = &context.params.feature.project;

    for document in &project.documents {
        if let Some(data) = document.data.as_tex() {
            let defs: FxHashSet<Span> = data
                .root_node()
                .descendants()
                .filter_map(|node| {
                    latex::OldCommandDefinition::cast(node.clone())
                        .and_then(|node| node.name())
                        .or_else(|| {
                            latex::NewCommandDefinition::cast(node)
                                .and_then(|node| node.name())
                                .and_then(|group| group.command())
                        })
                        .map(|name| Span::command(&name))
                })
                .collect();

            for command in &data.semantics.commands {
                if command.text == token.text()[1..] {
                    let kind = if defs.contains(command) {
                        ReferenceKind::Definition
                    } else {
                        ReferenceKind::Reference
                    };

                    context.results.push(Reference {
                        location: DocumentLocation::new(document, command.range),
                        kind,
                    });
                }
            }
        }
    }

    Some(())
}