harper_core/linting/
possessive_your.rs1use crate::{
2 Token,
3 patterns::{Pattern, SequencePattern},
4};
5
6use super::{Lint, LintKind, PatternLinter, Suggestion};
7
8pub struct PossessiveYour {
9 pattern: Box<dyn Pattern>,
10}
11
12impl Default for PossessiveYour {
13 fn default() -> Self {
14 let pattern =
15 SequencePattern::aco("you")
16 .then_whitespace()
17 .then(|tok: &Token, source: &[char]| {
18 if tok.kind.is_nominal() && !tok.kind.is_likely_homograph() {
19 let word = tok.span.get_content_string(source).to_lowercase();
20 return !matches!(word.as_str(), "guys" | "what's");
21 }
22 false
23 });
24
25 Self {
26 pattern: Box::new(pattern),
27 }
28 }
29}
30
31impl PatternLinter for PossessiveYour {
32 fn pattern(&self) -> &dyn Pattern {
33 self.pattern.as_ref()
34 }
35
36 fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
37 let span = matched_tokens.first()?.span;
38 let orig_chars = span.get_content(source);
39
40 Some(Lint {
41 span,
42 lint_kind: LintKind::WordChoice,
43 suggestions: vec![
44 Suggestion::replace_with_match_case("your".chars().collect(), orig_chars),
45 Suggestion::replace_with_match_case("you're a".chars().collect(), orig_chars),
46 Suggestion::replace_with_match_case("you're an".chars().collect(), orig_chars),
47 ],
48 message: "The possessive version of this word is more common in this context."
49 .to_owned(),
50 ..Default::default()
51 })
52 }
53
54 fn description(&self) -> &'static str {
55 "The possessive form of `you` is more likely before nouns."
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use crate::linting::tests::{
62 assert_lint_count, assert_suggestion_result, assert_top3_suggestion_result,
63 };
64
65 use super::PossessiveYour;
66
67 #[test]
68 fn your_comments() {
69 assert_suggestion_result(
70 "You comments may end up in the documentation.",
71 PossessiveYour::default(),
72 "Your comments may end up in the documentation.",
73 );
74 }
75
76 #[test]
77 fn allow_intro_page() {
78 assert_lint_count(
79 "You can try out an editor that uses Harper under-the-hood here.",
80 PossessiveYour::default(),
81 0,
82 );
83 }
84
85 #[test]
86 fn allow_you_guys() {
87 assert_lint_count(
88 "I mean I'm pretty sure you guys can't do anything with this stuff.",
89 PossessiveYour::default(),
90 0,
91 );
92 }
93
94 #[test]
95 fn test_top3_suggestion_your() {
96 assert_top3_suggestion_result(
97 "You combination of artist and teacher.",
98 PossessiveYour::default(),
99 "Your combination of artist and teacher.",
100 );
101 }
102
103 #[test]
104 fn test_top3_suggestion_youre_a() {
105 assert_top3_suggestion_result(
106 "You combination of artist and teacher.",
107 PossessiveYour::default(),
108 "You're a combination of artist and teacher.",
109 );
110 }
111
112 #[test]
113 #[ignore]
114 fn test_top3_suggestion_multiple() {
115 assert_top3_suggestion_result(
116 "You knowledge. You imagination. You icosahedron",
117 PossessiveYour::default(),
118 "Your knowledge. Your imagination. You're an icosahedron",
119 );
120 }
121
122 #[test]
123 fn dont_flag_just_showing_you() {
124 assert_lint_count(
125 "I'm just showing you what's available and how to use it.",
126 PossessiveYour::default(),
127 0,
128 );
129 }
130}