harper_core/linting/
capitalize_personal_pronouns.rs

1use crate::TokenStringExt;
2
3use super::{Lint, LintKind, Linter, Suggestion};
4
5/// A linter that makes sure you capitalize "I" and its contractions.
6#[derive(Default)]
7pub struct CapitalizePersonalPronouns;
8
9impl Linter for CapitalizePersonalPronouns {
10    fn lint(&mut self, document: &crate::Document) -> Vec<Lint> {
11        document
12            .iter_words()
13            .filter_map(|tok| {
14                let span_content = document.get_span_content(&tok.span);
15
16                if matches!(
17                    span_content,
18                    ['i']
19                        | ['i', '\'', 'd']
20                        | ['i', '\'', 'd', '\\', 'v', 'e']
21                        | ['i', '\'', 'l', 'l']
22                        | ['i', '\'', 'm']
23                        | ['i', '\'', 'v', 'e']
24                ) {
25                    let mut replacement = span_content.to_vec();
26                    replacement[0] = 'I';
27                    Some(Lint {
28                        span: tok.span,
29                        lint_kind: LintKind::Capitalization,
30                        suggestions: vec![Suggestion::ReplaceWith(replacement)],
31                        message: "The first-person singular subject pronoun must be capitalized."
32                            .to_string(),
33                        priority: 31,
34                    })
35                } else {
36                    None
37                }
38            })
39            .collect()
40    }
41
42    fn description(&self) -> &'static str {
43        "Forgetting to capitalize personal pronouns, like \"I\" or \"I'm\" is one of the most common errors. This rule helps with that."
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use crate::linting::tests::{assert_lint_count, assert_suggestion_result};
50
51    use super::CapitalizePersonalPronouns;
52
53    #[test]
54    fn start() {
55        assert_suggestion_result("i am hungry", CapitalizePersonalPronouns, "I am hungry");
56    }
57
58    #[test]
59    fn end() {
60        assert_suggestion_result(
61            "There is no one stronger than i",
62            CapitalizePersonalPronouns,
63            "There is no one stronger than I",
64        );
65    }
66
67    #[test]
68    fn middle() {
69        assert_suggestion_result(
70            "First of all, i am not happy with this.",
71            CapitalizePersonalPronouns,
72            "First of all, I am not happy with this.",
73        );
74    }
75
76    #[test]
77    fn issue_365() {
78        assert_lint_count(
79            "access will succeed, unlike with UDEREF/i386.",
80            CapitalizePersonalPronouns,
81            0,
82        );
83    }
84
85    #[test]
86    fn corrects_id() {
87        assert_suggestion_result("i'd", CapitalizePersonalPronouns, "I'd");
88    }
89
90    #[test]
91    fn correct_real_world_id() {
92        assert_suggestion_result(
93            "Personal Homebrew tap with tools i'd like to use",
94            CapitalizePersonalPronouns,
95            "Personal Homebrew tap with tools I'd like to use",
96        )
97    }
98
99    #[test]
100    fn corrects_idve() {
101        assert_suggestion_result("i'd've", CapitalizePersonalPronouns, "I'd've");
102    }
103
104    #[test]
105    fn correct_real_world_idve() {
106        assert_suggestion_result(
107            "... i'd've loved this even more twice length , but let not get greedy",
108            CapitalizePersonalPronouns,
109            "... I'd've loved this even more twice length , but let not get greedy",
110        )
111    }
112
113    #[test]
114    fn corrects_ill() {
115        assert_suggestion_result("i'll", CapitalizePersonalPronouns, "I'll");
116    }
117
118    #[test]
119    fn correct_real_world_ill() {
120        assert_suggestion_result(
121            "Hey i deploy my contract it give me error and i'll match with the script file both are same if someone have idea how i slove this please ...",
122            CapitalizePersonalPronouns,
123            "Hey I deploy my contract it give me error and I'll match with the script file both are same if someone have idea how I slove this please ...",
124        )
125    }
126
127    #[test]
128    fn corrects_im() {
129        assert_suggestion_result("i'm", CapitalizePersonalPronouns, "I'm");
130    }
131
132    #[test]
133    fn correct_real_world_im() {
134        assert_suggestion_result(
135            "Grid view not working, i'm not using any template",
136            CapitalizePersonalPronouns,
137            "Grid view not working, I'm not using any template",
138        )
139    }
140
141    #[test]
142    fn corrects_ive() {
143        assert_suggestion_result("i've", CapitalizePersonalPronouns, "I've");
144    }
145
146    #[test]
147    fn correct_real_world_ive() {
148        assert_suggestion_result(
149            "Can't use Github Pro although i've verified for student pack",
150            CapitalizePersonalPronouns,
151            "Can't use Github Pro although I've verified for student pack",
152        )
153    }
154}