harper_core/linting/
dot_initialisms.rs1use 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}