harper_core/linting/
lint_kind.rs

1use std::fmt::Display;
2
3use is_macro::Is;
4use serde::{Deserialize, Serialize};
5
6/// The general category a [`Lint`](super::Lint) falls into.
7/// There's no reason not to add a new item here if you are adding a new rule that doesn't fit
8/// the existing categories.
9#[derive(Debug, Clone, Copy, Serialize, Deserialize, Is, Default, Hash, PartialEq, Eq)]
10pub enum LintKind {
11    Agreement,
12    /// For errors where words are joined or split at the wrong boundaries
13    /// (e.g., "each and everyone" vs. "each and every one")
14    BoundaryError,
15    Capitalization,
16    /// For cases where a word or phrase is misused for a similar-sounding word or phrase,
17    /// where the incorrect version makes logical sense (e.g., 'egg corn' for 'acorn',
18    /// 'on mass' for 'en masse').
19    Eggcorn,
20    /// For suggesting improvements that enhance clarity or impact without fixing errors
21    Enhancement,
22    Formatting,
23    Grammar,
24    /// For cases where a word is mistakenly used for a similar-sounding word with a different meaning
25    /// (e.g., 'eluded to' instead of 'alluded to'). Unlike eggcorns, these don't create new meanings.
26    Malapropism,
27    /// For any other lint that doesn't fit neatly into the other categories
28    #[default]
29    Miscellaneous,
30    Nonstandard,
31    /// For issues with punctuation, including hyphenation in compound adjectives
32    /// (e.g., "face first" vs. "face-first" when used before a noun)
33    Punctuation,
34    Readability,
35    /// For cases where words duplicate meaning that's already expressed
36    /// (e.g., "basic fundamentals" → "fundamentals", "free gift" → "gift")
37    Redundancy,
38    /// For variations that are standard in some regions or dialects but not others
39    Regionalism,
40    Repetition,
41    /// When your brain doesn't know the right spelling.
42    /// This should only be used by linters doing spellcheck on individual words.
43    Spelling,
44    /// For cases where multiple options are correct but one is preferred for style or clarity,
45    /// such as expanding abbreviations in formal writing (e.g., 'min' → 'minimum')
46    Style,
47    /// When your brain knows the right spelling but your fingers made a mistake.
48    /// (e.g., 'can be seem' → 'can be seen')
49    Typo,
50    /// For conventional word usage and standard collocations
51    /// (e.g., 'by accident' vs. 'on accident' in standard English)
52    Usage,
53    /// For choosing between different words or phrases in a given context
54    WordChoice,
55}
56
57impl LintKind {
58    /// Produce a string representation, which can be used as keys in a map or CSS variables.
59    pub fn to_string_key(&self) -> String {
60        match self {
61            LintKind::Agreement => "Agreement",
62            LintKind::BoundaryError => "BoundaryError",
63            LintKind::Capitalization => "Capitalization",
64            LintKind::Eggcorn => "Eggcorn",
65            LintKind::Enhancement => "Enhancement",
66            LintKind::Formatting => "Formatting",
67            LintKind::Grammar => "Grammar",
68            LintKind::Malapropism => "Malapropism",
69            LintKind::Miscellaneous => "Miscellaneous",
70            LintKind::Nonstandard => "Nonstandard",
71            LintKind::Punctuation => "Punctuation",
72            LintKind::Readability => "Readability",
73            LintKind::Redundancy => "Redundancy",
74            LintKind::Regionalism => "Regionalism",
75            LintKind::Repetition => "Repetition",
76            LintKind::Spelling => "Spelling",
77            LintKind::Style => "Style",
78            LintKind::Typo => "Typo",
79            LintKind::Usage => "Usage",
80            LintKind::WordChoice => "WordChoice",
81        }
82        .to_owned()
83    }
84}
85
86impl Display for LintKind {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        let s = match self {
89            LintKind::Agreement => "Agreement",
90            LintKind::BoundaryError => "BoundaryError",
91            LintKind::Capitalization => "Capitalization",
92            LintKind::Eggcorn => "Eggcorn",
93            LintKind::Enhancement => "Enhancement",
94            LintKind::Formatting => "Formatting",
95            LintKind::Grammar => "Grammar",
96            LintKind::Malapropism => "Malapropism",
97            LintKind::Miscellaneous => "Miscellaneous",
98            LintKind::Nonstandard => "Nonstandard",
99            LintKind::Punctuation => "Punctuation",
100            LintKind::Readability => "Readability",
101            LintKind::Redundancy => "Redundancy",
102            LintKind::Regionalism => "Regionalism",
103            LintKind::Repetition => "Repetition",
104            LintKind::Spelling => "Spelling",
105            LintKind::Style => "Style",
106            LintKind::Typo => "Typo",
107            LintKind::Usage => "Usage",
108            LintKind::WordChoice => "Word Choice",
109        };
110
111        write!(f, "{s}")
112    }
113}