harper_core/linting/
for_noun.rs1use crate::{
2 Token,
3 patterns::{NominalPhrase, OwnedPatternExt, Pattern, SequencePattern, Word},
4};
5
6use super::{Lint, LintKind, PatternLinter, Suggestion};
7
8pub struct ForNoun {
9 pattern: Box<dyn Pattern>,
10}
11
12impl Default for ForNoun {
13 fn default() -> Self {
14 let pattern = SequencePattern::aco("fro")
15 .then_whitespace()
16 .then(NominalPhrase.or(Box::new(Word::new("sure"))));
17
18 Self {
19 pattern: Box::new(pattern),
20 }
21 }
22}
23
24impl PatternLinter for ForNoun {
25 fn pattern(&self) -> &dyn Pattern {
26 self.pattern.as_ref()
27 }
28
29 fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
30 let span = matched_tokens.first()?.span;
31 let problem_chars = span.get_content(source);
32
33 Some(Lint {
34 span,
35 lint_kind: LintKind::WordChoice,
36 suggestions: vec![Suggestion::replace_with_match_case_str(
37 "for",
38 problem_chars,
39 )],
40 message: "`For` is more common in this context.".to_owned(),
41 priority: 31,
42 })
43 }
44
45 fn description(&self) -> &'static str {
46 "Corrects the archaic or mistaken `fro` to `for` when followed by a noun."
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::ForNoun;
53 use crate::linting::tests::{assert_lint_count, assert_suggestion_result};
54
55 #[test]
56 fn corrects_fro_basic_correction() {
57 assert_suggestion_result(
58 "I got a text fro Sarah.",
59 ForNoun::default(),
60 "I got a text for Sarah.",
61 );
62 }
63
64 #[test]
65 fn allows_for_clean() {
66 assert_lint_count("I got a text for Sarah.", ForNoun::default(), 0);
67 }
68
69 #[test]
70 fn corrects_fro_sure() {
71 assert_suggestion_result(
72 "He was away fro sure!",
73 ForNoun::default(),
74 "He was away for sure!",
75 );
76 }
77}