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