1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum IssueKind {
6 UnusedFile,
8 UnusedExport,
10 UnusedType,
12 UnusedDependency,
14 UnusedDevDependency,
16 UnusedEnumMember,
18 UnusedClassMember,
20 UnresolvedImport,
22 UnlistedDependency,
24 DuplicateExport,
26 CodeDuplication,
28 CircularDependency,
30}
31
32impl IssueKind {
33 #[must_use]
35 pub fn parse(s: &str) -> Option<Self> {
36 match s {
37 "unused-file" => Some(Self::UnusedFile),
38 "unused-export" => Some(Self::UnusedExport),
39 "unused-type" => Some(Self::UnusedType),
40 "unused-dependency" => Some(Self::UnusedDependency),
41 "unused-dev-dependency" => Some(Self::UnusedDevDependency),
42 "unused-enum-member" => Some(Self::UnusedEnumMember),
43 "unused-class-member" => Some(Self::UnusedClassMember),
44 "unresolved-import" => Some(Self::UnresolvedImport),
45 "unlisted-dependency" => Some(Self::UnlistedDependency),
46 "duplicate-export" => Some(Self::DuplicateExport),
47 "code-duplication" => Some(Self::CodeDuplication),
48 "circular-dependency" => Some(Self::CircularDependency),
49 _ => None,
50 }
51 }
52
53 #[must_use]
55 pub const fn to_discriminant(self) -> u8 {
56 match self {
57 Self::UnusedFile => 1,
58 Self::UnusedExport => 2,
59 Self::UnusedType => 3,
60 Self::UnusedDependency => 4,
61 Self::UnusedDevDependency => 5,
62 Self::UnusedEnumMember => 6,
63 Self::UnusedClassMember => 7,
64 Self::UnresolvedImport => 8,
65 Self::UnlistedDependency => 9,
66 Self::DuplicateExport => 10,
67 Self::CodeDuplication => 11,
68 Self::CircularDependency => 12,
69 }
70 }
71
72 #[must_use]
74 pub const fn from_discriminant(d: u8) -> Option<Self> {
75 match d {
76 1 => Some(Self::UnusedFile),
77 2 => Some(Self::UnusedExport),
78 3 => Some(Self::UnusedType),
79 4 => Some(Self::UnusedDependency),
80 5 => Some(Self::UnusedDevDependency),
81 6 => Some(Self::UnusedEnumMember),
82 7 => Some(Self::UnusedClassMember),
83 8 => Some(Self::UnresolvedImport),
84 9 => Some(Self::UnlistedDependency),
85 10 => Some(Self::DuplicateExport),
86 11 => Some(Self::CodeDuplication),
87 12 => Some(Self::CircularDependency),
88 _ => None,
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
95pub struct Suppression {
96 pub line: u32,
98 pub kind: Option<IssueKind>,
100}
101
102const _: () = assert!(std::mem::size_of::<Suppression>() == 8);
105const _: () = assert!(std::mem::size_of::<IssueKind>() == 1);
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn issue_kind_from_str_all_variants() {
113 assert_eq!(IssueKind::parse("unused-file"), Some(IssueKind::UnusedFile));
114 assert_eq!(
115 IssueKind::parse("unused-export"),
116 Some(IssueKind::UnusedExport)
117 );
118 assert_eq!(IssueKind::parse("unused-type"), Some(IssueKind::UnusedType));
119 assert_eq!(
120 IssueKind::parse("unused-dependency"),
121 Some(IssueKind::UnusedDependency)
122 );
123 assert_eq!(
124 IssueKind::parse("unused-dev-dependency"),
125 Some(IssueKind::UnusedDevDependency)
126 );
127 assert_eq!(
128 IssueKind::parse("unused-enum-member"),
129 Some(IssueKind::UnusedEnumMember)
130 );
131 assert_eq!(
132 IssueKind::parse("unused-class-member"),
133 Some(IssueKind::UnusedClassMember)
134 );
135 assert_eq!(
136 IssueKind::parse("unresolved-import"),
137 Some(IssueKind::UnresolvedImport)
138 );
139 assert_eq!(
140 IssueKind::parse("unlisted-dependency"),
141 Some(IssueKind::UnlistedDependency)
142 );
143 assert_eq!(
144 IssueKind::parse("duplicate-export"),
145 Some(IssueKind::DuplicateExport)
146 );
147 assert_eq!(
148 IssueKind::parse("code-duplication"),
149 Some(IssueKind::CodeDuplication)
150 );
151 assert_eq!(
152 IssueKind::parse("circular-dependency"),
153 Some(IssueKind::CircularDependency)
154 );
155 }
156
157 #[test]
158 fn issue_kind_from_str_unknown() {
159 assert_eq!(IssueKind::parse("foo"), None);
160 assert_eq!(IssueKind::parse(""), None);
161 }
162
163 #[test]
164 fn issue_kind_from_str_near_misses() {
165 assert_eq!(IssueKind::parse("Unused-File"), None);
167 assert_eq!(IssueKind::parse("UNUSED-EXPORT"), None);
168 assert_eq!(IssueKind::parse("unused_file"), None);
170 assert_eq!(IssueKind::parse("unused-files"), None);
171 }
172
173 #[test]
174 fn discriminant_out_of_range() {
175 assert_eq!(IssueKind::from_discriminant(0), None);
176 assert_eq!(IssueKind::from_discriminant(13), None);
177 assert_eq!(IssueKind::from_discriminant(u8::MAX), None);
178 }
179
180 #[test]
181 fn discriminant_roundtrip() {
182 for kind in [
183 IssueKind::UnusedFile,
184 IssueKind::UnusedExport,
185 IssueKind::UnusedType,
186 IssueKind::UnusedDependency,
187 IssueKind::UnusedDevDependency,
188 IssueKind::UnusedEnumMember,
189 IssueKind::UnusedClassMember,
190 IssueKind::UnresolvedImport,
191 IssueKind::UnlistedDependency,
192 IssueKind::DuplicateExport,
193 IssueKind::CodeDuplication,
194 IssueKind::CircularDependency,
195 ] {
196 assert_eq!(
197 IssueKind::from_discriminant(kind.to_discriminant()),
198 Some(kind)
199 );
200 }
201 assert_eq!(IssueKind::from_discriminant(0), None);
202 assert_eq!(IssueKind::from_discriminant(13), None);
203 }
204}