sqry_core/schema/
unused.rs1use serde::{Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29#[serde(rename_all = "lowercase")]
30#[derive(Default)]
31pub enum UnusedScope {
32 Public,
37
38 Private,
43
44 Function,
48
49 Struct,
53
54 #[default]
58 All,
59}
60
61impl UnusedScope {
62 #[must_use]
64 pub const fn all() -> &'static [Self] {
65 &[
66 Self::Public,
67 Self::Private,
68 Self::Function,
69 Self::Struct,
70 Self::All,
71 ]
72 }
73
74 #[must_use]
76 pub const fn as_str(self) -> &'static str {
77 match self {
78 Self::Public => "public",
79 Self::Private => "private",
80 Self::Function => "function",
81 Self::Struct => "struct",
82 Self::All => "all",
83 }
84 }
85
86 #[must_use]
91 pub fn parse(s: &str) -> Option<Self> {
92 match s.to_lowercase().as_str() {
93 "public" | "pub" | "exported" => Some(Self::Public),
94 "private" | "priv" | "internal" => Some(Self::Private),
95 "function" | "func" | "method" => Some(Self::Function),
96 "struct" | "class" | "type" => Some(Self::Struct),
97 "all" | "*" => Some(Self::All),
98 _ => None,
99 }
100 }
101
102 #[must_use]
104 pub const fn is_visibility_filter(self) -> bool {
105 matches!(self, Self::Public | Self::Private)
106 }
107
108 #[must_use]
110 pub const fn is_kind_filter(self) -> bool {
111 matches!(self, Self::Function | Self::Struct)
112 }
113
114 #[must_use]
116 pub const fn description(self) -> &'static str {
117 match self {
118 Self::Public => "unused public/exported symbols",
119 Self::Private => "unused private/internal symbols",
120 Self::Function => "unused functions and methods",
121 Self::Struct => "unused structs and classes",
122 Self::All => "all unused symbols",
123 }
124 }
125}
126
127impl fmt::Display for UnusedScope {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 f.write_str(self.as_str())
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_as_str() {
139 assert_eq!(UnusedScope::Public.as_str(), "public");
140 assert_eq!(UnusedScope::Private.as_str(), "private");
141 assert_eq!(UnusedScope::Function.as_str(), "function");
142 assert_eq!(UnusedScope::Struct.as_str(), "struct");
143 assert_eq!(UnusedScope::All.as_str(), "all");
144 }
145
146 #[test]
147 fn test_parse() {
148 assert_eq!(UnusedScope::parse("public"), Some(UnusedScope::Public));
149 assert_eq!(UnusedScope::parse("PRIVATE"), Some(UnusedScope::Private));
150 assert_eq!(UnusedScope::parse("func"), Some(UnusedScope::Function));
151 assert_eq!(UnusedScope::parse("class"), Some(UnusedScope::Struct));
152 assert_eq!(UnusedScope::parse("*"), Some(UnusedScope::All));
153 assert_eq!(UnusedScope::parse("unknown"), None);
154 }
155
156 #[test]
157 fn test_display() {
158 assert_eq!(format!("{}", UnusedScope::Public), "public");
159 assert_eq!(format!("{}", UnusedScope::All), "all");
160 }
161
162 #[test]
163 fn test_serde_roundtrip() {
164 for scope in UnusedScope::all() {
165 let json = serde_json::to_string(scope).unwrap();
166 let deserialized: UnusedScope = serde_json::from_str(&json).unwrap();
167 assert_eq!(*scope, deserialized);
168 }
169 }
170
171 #[test]
172 fn test_default() {
173 assert_eq!(UnusedScope::default(), UnusedScope::All);
174 }
175
176 #[test]
177 fn test_classification() {
178 assert!(UnusedScope::Public.is_visibility_filter());
179 assert!(UnusedScope::Private.is_visibility_filter());
180 assert!(!UnusedScope::Function.is_visibility_filter());
181
182 assert!(UnusedScope::Function.is_kind_filter());
183 assert!(UnusedScope::Struct.is_kind_filter());
184 assert!(!UnusedScope::Public.is_kind_filter());
185
186 assert!(!UnusedScope::All.is_visibility_filter());
187 assert!(!UnusedScope::All.is_kind_filter());
188 }
189
190 #[test]
191 fn test_description() {
192 assert!(UnusedScope::Public.description().contains("public"));
193 assert!(UnusedScope::Private.description().contains("private"));
194 assert!(UnusedScope::Function.description().contains("function"));
195 assert!(UnusedScope::Struct.description().contains("struct"));
196 assert!(UnusedScope::All.description().contains("all"));
197 }
198}