summaryrefslogtreecommitdiff
path: root/support/texlab/crates/diagnostics/src/manager.rs
blob: 1ce5e194b8e21040cdb6bce075280e08c361d9b2 (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
73
74
75
use base_db::{util::filter_regex_patterns, Document, Owner, Workspace};
use multimap::MultiMap;
use rustc_hash::FxHashMap;
use url::Url;

use crate::types::Diagnostic;

/// Manages all diagnostics for a workspace.
#[derive(Debug, Default)]
pub struct Manager {
    grammar: MultiMap<Url, Diagnostic>,
    chktex: FxHashMap<Url, Vec<Diagnostic>>,
    build_log: FxHashMap<Url, MultiMap<Url, Diagnostic>>,
}

impl Manager {
    /// Updates the syntax-based diagnostics for the given document.
    pub fn update_syntax(&mut self, workspace: &Workspace, document: &Document) {
        self.grammar.remove(&document.uri);
        super::grammar::tex::update(document, workspace.config(), &mut self.grammar);
        super::grammar::bib::update(document, &mut self.grammar);

        self.build_log.remove(&document.uri);
        super::build_log::update(workspace, document, &mut self.build_log);
    }

    /// Updates the ChkTeX diagnostics for the given document.
    pub fn update_chktex(&mut self, uri: Url, diagnostics: Vec<Diagnostic>) {
        self.chktex.insert(uri, diagnostics);
    }

    /// Returns all filtered diagnostics for the given workspace.
    pub fn get(&self, workspace: &Workspace) -> MultiMap<Url, Diagnostic> {
        let mut results = MultiMap::default();
        for (uri, diagnostics) in &self.grammar {
            results.insert_many_from_slice(uri.clone(), diagnostics);
        }

        for (uri, diagnostics) in self.build_log.values().flatten() {
            results.insert_many_from_slice(uri.clone(), diagnostics);
        }

        for (uri, diagnostics) in &self.chktex {
            if workspace
                .lookup(uri)
                .map_or(false, |document| document.owner == Owner::Client)
            {
                results.insert_many_from_slice(uri.clone(), diagnostics);
            }
        }

        for document in workspace.iter() {
            let project = workspace.project(document);
            super::citations::detect_undefined_citations(&project, document, &mut results);
            super::citations::detect_unused_entries(&project, document, &mut results);
        }

        super::citations::detect_duplicate_entries(workspace, &mut results);
        super::labels::detect_duplicate_labels(workspace, &mut results);
        super::labels::detect_undefined_and_unused_labels(workspace, &mut results);

        let config = &workspace.config().diagnostics;
        for (_, diagnostics) in &mut results {
            diagnostics.retain(|diagnostic| {
                filter_regex_patterns(
                    &diagnostic.message(),
                    &config.allowed_patterns,
                    &config.ignored_patterns,
                )
            });
        }

        results
    }
}