harper_core/linting/
hereby.rs

1use crate::{
2    Token, TokenStringExt,
3    patterns::{Pattern, SequencePattern},
4};
5
6use super::{Lint, LintKind, PatternLinter, Suggestion};
7
8pub struct Hereby {
9    pattern: Box<dyn Pattern>,
10}
11
12impl Default for Hereby {
13    fn default() -> Self {
14        let pattern = SequencePattern::aco("here")
15            .then_whitespace()
16            .t_aco("by")
17            .then_whitespace()
18            .then_verb();
19
20        Self {
21            pattern: Box::new(pattern),
22        }
23    }
24}
25
26impl PatternLinter for Hereby {
27    fn pattern(&self) -> &dyn Pattern {
28        self.pattern.as_ref()
29    }
30
31    fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
32        let span = matched_tokens[0..3].span()?;
33        let orig_chars = span.get_content(source);
34        Some(Lint {
35            span,
36            lint_kind: LintKind::WordChoice,
37            suggestions: vec![Suggestion::replace_with_match_case(
38                "hereby".chars().collect(),
39                orig_chars,
40            )],
41            message: "Did you mean the closed compound `hereby`?".to_owned(),
42            ..Default::default()
43        })
44    }
45
46    fn description(&self) -> &'static str {
47        "`Here by` in some contexts should be `hereby`"
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use crate::linting::tests::assert_suggestion_result;
54
55    use super::Hereby;
56
57    #[test]
58    fn declare() {
59        assert_suggestion_result(
60            "I here by declare this state to be free.",
61            Hereby::default(),
62            "I hereby declare this state to be free.",
63        );
64    }
65}