harper_core/linting/
pique_interest.rs

1use crate::{
2    CharString, CharStringExt, Token,
3    char_string::char_string,
4    patterns::{Pattern, SequencePattern, WordSet},
5};
6
7use super::{Lint, LintKind, PatternLinter, Suggestion};
8
9pub struct PiqueInterest {
10    pattern: Box<dyn Pattern>,
11}
12
13impl Default for PiqueInterest {
14    fn default() -> Self {
15        let pattern = SequencePattern::default()
16            .then(WordSet::new(&[
17                "peak", "peaked", "peek", "peeked", "peeking", "peaking",
18            ]))
19            .then_whitespace()
20            .then_not_plural_nominal()
21            .then_whitespace()
22            .t_aco("interest");
23
24        Self {
25            pattern: Box::new(pattern),
26        }
27    }
28}
29
30impl PiqueInterest {
31    fn to_correct(word: &str) -> Option<CharString> {
32        Some(match word.to_lowercase().as_str() {
33            "peak" => char_string!("pique"),
34            "peek" => char_string!("pique"),
35            "peeked" => char_string!("piqued"),
36            "peaked" => char_string!("piqued"),
37            "peaking" => char_string!("piquing"),
38            "peeking" => char_string!("piquing"),
39            _ => return None,
40        })
41    }
42}
43
44impl PatternLinter for PiqueInterest {
45    fn pattern(&self) -> &dyn Pattern {
46        self.pattern.as_ref()
47    }
48
49    fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
50        let span = matched_tokens[0].span;
51        let word = span.get_content_string(source).to_lowercase();
52        let correct = Self::to_correct(&word)?;
53
54        Some(Lint {
55            span,
56            lint_kind: LintKind::WordChoice,
57            suggestions: vec![Suggestion::replace_with_match_case(
58                correct.to_vec(),
59                matched_tokens[0].span.get_content(source),
60            )],
61            message: format!(
62                "Did you mean `{}` instead of `{}`?",
63                correct.to_string(),
64                word,
65            ),
66            priority: 31,
67        })
68    }
69
70    fn description(&self) -> &'static str {
71        "Detects incorrect usage of `peak` or `peek` when the intended word is `pique`, as in the phrase `you've peaked my interest`."
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::PiqueInterest;
78    use crate::linting::tests::assert_suggestion_result;
79
80    #[test]
81    fn corrects_peak_interest() {
82        assert_suggestion_result(
83            "The story managed to peak his interest.",
84            PiqueInterest::default(),
85            "The story managed to pique his interest.",
86        );
87    }
88
89    #[test]
90    fn corrects_peeked_interest_at_start() {
91        assert_suggestion_result(
92            "Peeked his interest, did she?",
93            PiqueInterest::default(),
94            "Piqued his interest, did she?",
95        );
96    }
97
98    #[test]
99    fn corrects_peak_interest_in_middle() {
100        assert_suggestion_result(
101            "She tried to peak his interest during the lecture.",
102            PiqueInterest::default(),
103            "She tried to pique his interest during the lecture.",
104        );
105    }
106
107    #[test]
108    fn corrects_peaked_interest_at_end() {
109        assert_suggestion_result(
110            "All along, she hoped she peaked his interest.",
111            PiqueInterest::default(),
112            "All along, she hoped she piqued his interest.",
113        );
114    }
115
116    #[test]
117    fn does_not_correct_unrelated_peak() {
118        assert_suggestion_result(
119            "He reached the peak of the mountain.",
120            PiqueInterest::default(),
121            "He reached the peak of the mountain.",
122        );
123    }
124
125    #[test]
126    fn corrects_peaking_interest() {
127        assert_suggestion_result(
128            "She was peaking his interest with her stories.",
129            PiqueInterest::default(),
130            "She was piquing his interest with her stories.",
131        );
132    }
133}