harper_core/linting/
dot_initialisms.rs

1use hashbrown::HashMap;
2
3use super::{Lint, LintKind, PatternLinter, Suggestion};
4use crate::patterns::{Pattern, SequencePattern, WordPatternGroup};
5use crate::{Token, TokenStringExt};
6
7pub struct DotInitialisms {
8    pattern: Box<dyn Pattern>,
9    corrections: HashMap<&'static str, &'static str>,
10}
11
12impl Default for DotInitialisms {
13    fn default() -> Self {
14        let mut patterns = WordPatternGroup::default();
15
16        let mut corrections = HashMap::new();
17        corrections.insert("ie", "i.e.");
18        corrections.insert("eg", "e.g.");
19
20        for target in corrections.keys() {
21            let pattern = SequencePattern::default()
22                .then_exact_word(target)
23                .then_punctuation();
24
25            patterns.add(target, Box::new(pattern));
26        }
27
28        Self {
29            pattern: Box::new(patterns),
30            corrections,
31        }
32    }
33}
34
35impl PatternLinter for DotInitialisms {
36    fn pattern(&self) -> &dyn Pattern {
37        self.pattern.as_ref()
38    }
39
40    fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
41        let found_word_tok = matched_tokens.first()?;
42        let found_word = found_word_tok.span.get_content_string(source);
43
44        let correction = self.corrections.get(found_word.as_str())?;
45
46        Some(Lint {
47            span: matched_tokens.span()?,
48            lint_kind: LintKind::Formatting,
49            suggestions: vec![Suggestion::ReplaceWith(correction.chars().collect())],
50            message: "Initialisms should have dot-separated letters.".to_owned(),
51            priority: 63,
52        })
53    }
54
55    fn description(&self) -> &'static str {
56        "Ensures common initialisms (like \"i.e.\") are properly dot-separated."
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::DotInitialisms;
63    use crate::linting::tests::assert_suggestion_result;
64
65    #[test]
66    fn matches_eg() {
67        assert_suggestion_result(
68            "Some text here (eg. more text).",
69            DotInitialisms::default(),
70            "Some text here (e.g. more text).",
71        )
72    }
73}