summaryrefslogtreecommitdiff
path: root/support/texlab/src/syntax/latex/analysis/explicit_link.rs
blob: f177354ac769ad9fd6c0781bf6ebc8f3fe20847f (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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use std::sync::Arc;

use crate::syntax::{latex, CstNode};

use super::{
    distro_file::resolve_distro_file, ExplicitLink, ExplicitLinkKind, LatexAnalyzerContext,
};

pub fn analyze_include(context: &mut LatexAnalyzerContext, node: &latex::SyntaxNode) -> Option<()> {
    let include = latex::Include::cast(node)?;
    let kind = match include.syntax().kind() {
        latex::LATEX_INCLUDE => ExplicitLinkKind::Latex,
        latex::BIBLATEX_INCLUDE | latex::BIBTEX_INCLUDE => ExplicitLinkKind::Bibtex,
        latex::PACKAGE_INCLUDE => ExplicitLinkKind::Package,
        latex::CLASS_INCLUDE => ExplicitLinkKind::Class,
        _ => return None,
    };

    let extensions = match kind {
        ExplicitLinkKind::Latex => &["tex"],
        ExplicitLinkKind::Bibtex => &["bib"],
        ExplicitLinkKind::Package => &["sty"],
        ExplicitLinkKind::Class => &["cls"],
    };

    for path in include.path_list()?.keys() {
        let stem = path.to_string();
        let mut targets = vec![Arc::new(context.base_uri.join(&stem).ok()?.into())];
        for extension in extensions {
            let path = format!("{}.{}", stem, extension);
            targets.push(Arc::new(context.base_uri.join(&path).ok()?.into()));
        }

        resolve_distro_file(&context.inner.resolver.lock().unwrap(), &stem, extensions)
            .into_iter()
            .for_each(|target| targets.push(Arc::new(target)));

        context.extras.explicit_links.push(ExplicitLink {
            kind,
            stem: stem.into(),
            stem_range: path.small_range(),
            targets,
        });
    }

    Some(())
}

pub fn analyze_import(context: &mut LatexAnalyzerContext, node: &latex::SyntaxNode) -> Option<()> {
    let import = latex::Import::cast(node)?;

    let mut targets = Vec::new();
    let directory = context
        .base_uri
        .join(&import.directory()?.key()?.to_string())
        .ok()?;

    let file = import.file()?.key()?;
    let stem = file.to_string();
    targets.push(Arc::new(directory.join(&stem).ok()?.into()));
    targets.push(Arc::new(
        directory.join(&format!("{}.tex", stem)).ok()?.into(),
    ));

    context.extras.explicit_links.push(ExplicitLink {
        stem: stem.into(),
        stem_range: file.small_range(),
        targets,
        kind: ExplicitLinkKind::Latex,
    });
    Some(())
}