harper_core/linting/
nobody.rs1use crate::{
2 Token, TokenStringExt,
3 patterns::{Pattern, SequencePattern},
4};
5
6use super::{Lint, LintKind, PatternLinter, Suggestion};
7
8pub struct Nobody {
9 pattern: Box<dyn Pattern>,
10}
11
12impl Default for Nobody {
13 fn default() -> Self {
14 let pattern = SequencePattern::aco("no")
15 .then_whitespace()
16 .t_aco("body")
17 .then_whitespace()
18 .then_verb();
19 Self {
20 pattern: Box::new(pattern),
21 }
22 }
23}
24
25impl PatternLinter for Nobody {
26 fn pattern(&self) -> &dyn Pattern {
27 self.pattern.as_ref()
28 }
29
30 fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
31 let span = matched_tokens[0..3].span()?;
32 let orig_chars = span.get_content(source);
33 Some(Lint {
34 span,
35 lint_kind: LintKind::WordChoice,
36 suggestions: vec![Suggestion::replace_with_match_case(
37 "nobody".chars().collect(),
38 orig_chars,
39 )],
40 message: format!("Did you mean the closed compound `{}`?", "nobody"),
41 ..Default::default()
42 })
43 }
44
45 fn description(&self) -> &'static str {
46 "Looks for incorrect spacing inside the closed compound `nobody`."
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::linting::tests::assert_suggestion_result;
53
54 use super::Nobody;
55
56 #[test]
57 fn both_valid_and_invalid() {
58 assert_suggestion_result(
59 "No body told me. I have a head but no body.",
60 Nobody::default(),
61 "Nobody told me. I have a head but no body.",
62 );
63 }
64}