sqry_core/graph/unified/node/
kind.rs1use std::fmt;
15
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
29#[serde(rename_all = "snake_case")]
30pub enum NodeKind {
31 Function,
34
35 Method,
37
38 Class,
40
41 Interface,
43
44 Trait,
46
47 Module,
49
50 Variable,
53
54 Constant,
56
57 Type,
59
60 Struct,
62
63 Enum,
65
66 EnumVariant,
68
69 Macro,
71
72 Parameter,
74
75 Property,
77
78 CallSite,
84
85 Import,
87
88 Export,
90
91 StyleRule,
94
95 StyleAtRule,
97
98 StyleVariable,
100
101 Lifetime,
112
113 Component,
116
117 Service,
119
120 Resource,
122
123 Endpoint,
125
126 Test,
128
129 #[serde(other)]
135 Other,
136}
137
138impl NodeKind {
139 #[inline]
141 #[must_use]
142 pub const fn is_callable(self) -> bool {
143 matches!(self, Self::Function | Self::Method | Self::Macro)
144 }
145
146 #[inline]
148 #[must_use]
149 pub const fn is_type_definition(self) -> bool {
150 matches!(
151 self,
152 Self::Class | Self::Interface | Self::Trait | Self::Struct | Self::Enum | Self::Type
153 )
154 }
155
156 #[inline]
158 #[must_use]
159 pub const fn is_container(self) -> bool {
160 matches!(
161 self,
162 Self::Class
163 | Self::Interface
164 | Self::Trait
165 | Self::Struct
166 | Self::Module
167 | Self::Enum
168 | Self::StyleRule
169 | Self::StyleAtRule
170 )
171 }
172
173 #[inline]
175 #[must_use]
176 pub const fn is_boundary(self) -> bool {
177 matches!(self, Self::Import | Self::Export)
178 }
179
180 #[inline]
182 #[must_use]
183 pub const fn is_lifetime(self) -> bool {
184 matches!(self, Self::Lifetime)
185 }
186
187 #[must_use]
189 pub const fn as_str(self) -> &'static str {
190 match self {
191 Self::Function => "function",
192 Self::Method => "method",
193 Self::Class => "class",
194 Self::Interface => "interface",
195 Self::Trait => "trait",
196 Self::Module => "module",
197 Self::Variable => "variable",
198 Self::Constant => "constant",
199 Self::Type => "type",
200 Self::Struct => "struct",
201 Self::Enum => "enum",
202 Self::EnumVariant => "enum_variant",
203 Self::Macro => "macro",
204 Self::Parameter => "parameter",
205 Self::Property => "property",
206 Self::CallSite => "call_site",
207 Self::Import => "import",
208 Self::Export => "export",
209 Self::StyleRule => "style_rule",
210 Self::StyleAtRule => "style_at_rule",
211 Self::StyleVariable => "style_variable",
212 Self::Lifetime => "lifetime",
213 Self::Component => "component",
214 Self::Service => "service",
215 Self::Resource => "resource",
216 Self::Endpoint => "endpoint",
217 Self::Test => "test",
218 Self::Other => "other",
219 }
220 }
221
222 #[must_use]
226 pub fn parse(s: &str) -> Option<Self> {
227 match s {
228 "function" => Some(Self::Function),
229 "method" => Some(Self::Method),
230 "class" => Some(Self::Class),
231 "interface" => Some(Self::Interface),
232 "trait" => Some(Self::Trait),
233 "module" => Some(Self::Module),
234 "variable" => Some(Self::Variable),
235 "constant" => Some(Self::Constant),
236 "type" => Some(Self::Type),
237 "struct" => Some(Self::Struct),
238 "enum" => Some(Self::Enum),
239 "enum_variant" => Some(Self::EnumVariant),
240 "macro" => Some(Self::Macro),
241 "parameter" => Some(Self::Parameter),
242 "property" => Some(Self::Property),
243 "call_site" => Some(Self::CallSite),
244 "import" => Some(Self::Import),
245 "export" => Some(Self::Export),
246 "style_rule" => Some(Self::StyleRule),
247 "style_at_rule" => Some(Self::StyleAtRule),
248 "style_variable" => Some(Self::StyleVariable),
249 "lifetime" => Some(Self::Lifetime),
250 "component" => Some(Self::Component),
251 "service" => Some(Self::Service),
252 "resource" => Some(Self::Resource),
253 "endpoint" => Some(Self::Endpoint),
254 "test" => Some(Self::Test),
255 "other" => Some(Self::Other),
256 _ => None,
257 }
258 }
259}
260
261impl fmt::Display for NodeKind {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 f.write_str(self.as_str())
264 }
265}
266
267impl Default for NodeKind {
268 fn default() -> Self {
270 Self::Function
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::*;
277
278 #[test]
279 fn test_node_kind_as_str() {
280 assert_eq!(NodeKind::Function.as_str(), "function");
281 assert_eq!(NodeKind::Method.as_str(), "method");
282 assert_eq!(NodeKind::Class.as_str(), "class");
283 assert_eq!(NodeKind::CallSite.as_str(), "call_site");
284 assert_eq!(NodeKind::EnumVariant.as_str(), "enum_variant");
285 }
286
287 #[test]
288 fn test_node_kind_parse() {
289 assert_eq!(NodeKind::parse("function"), Some(NodeKind::Function));
290 assert_eq!(NodeKind::parse("call_site"), Some(NodeKind::CallSite));
291 assert_eq!(NodeKind::parse("unknown"), None);
292 }
293
294 #[test]
295 fn test_node_kind_display() {
296 assert_eq!(format!("{}", NodeKind::Function), "function");
297 assert_eq!(format!("{}", NodeKind::EnumVariant), "enum_variant");
298 }
299
300 #[test]
301 fn test_is_callable() {
302 assert!(NodeKind::Function.is_callable());
303 assert!(NodeKind::Method.is_callable());
304 assert!(NodeKind::Macro.is_callable());
305 assert!(!NodeKind::Class.is_callable());
306 assert!(!NodeKind::Variable.is_callable());
307 }
308
309 #[test]
310 fn test_is_type_definition() {
311 assert!(NodeKind::Class.is_type_definition());
312 assert!(NodeKind::Interface.is_type_definition());
313 assert!(NodeKind::Trait.is_type_definition());
314 assert!(NodeKind::Struct.is_type_definition());
315 assert!(NodeKind::Enum.is_type_definition());
316 assert!(NodeKind::Type.is_type_definition());
317 assert!(!NodeKind::Function.is_type_definition());
318 assert!(!NodeKind::Variable.is_type_definition());
319 }
320
321 #[test]
322 fn test_is_container() {
323 assert!(NodeKind::Class.is_container());
324 assert!(NodeKind::Module.is_container());
325 assert!(NodeKind::Struct.is_container());
326 assert!(!NodeKind::Function.is_container());
327 assert!(!NodeKind::Variable.is_container());
328 }
329
330 #[test]
331 fn test_is_boundary() {
332 assert!(NodeKind::Import.is_boundary());
333 assert!(NodeKind::Export.is_boundary());
334 assert!(!NodeKind::Function.is_boundary());
335 }
336
337 #[test]
338 fn test_is_lifetime() {
339 assert!(NodeKind::Lifetime.is_lifetime());
340 assert!(!NodeKind::Function.is_lifetime());
341 assert!(!NodeKind::Variable.is_lifetime());
342 }
343
344 #[test]
345 fn test_lifetime_serialization() {
346 assert_eq!(NodeKind::Lifetime.as_str(), "lifetime");
347 assert_eq!(NodeKind::parse("lifetime"), Some(NodeKind::Lifetime));
348
349 let json = serde_json::to_string(&NodeKind::Lifetime).unwrap();
351 assert_eq!(json, "\"lifetime\"");
352 let deserialized: NodeKind = serde_json::from_str(&json).unwrap();
353 assert_eq!(deserialized, NodeKind::Lifetime);
354 }
355
356 #[test]
357 fn test_default() {
358 assert_eq!(NodeKind::default(), NodeKind::Function);
359 }
360
361 #[test]
362 fn test_serde_roundtrip() {
363 let kinds = [
364 NodeKind::Function,
365 NodeKind::Method,
366 NodeKind::Class,
367 NodeKind::CallSite,
368 NodeKind::EnumVariant,
369 ];
370
371 for kind in kinds {
372 let json = serde_json::to_string(&kind).unwrap();
374 let deserialized: NodeKind = serde_json::from_str(&json).unwrap();
375 assert_eq!(kind, deserialized);
376
377 let bytes = postcard::to_allocvec(&kind).unwrap();
379 let deserialized: NodeKind = postcard::from_bytes(&bytes).unwrap();
380 assert_eq!(kind, deserialized);
381 }
382 }
383
384 #[test]
385 fn test_json_format() {
386 assert_eq!(
388 serde_json::to_string(&NodeKind::Function).unwrap(),
389 "\"function\""
390 );
391 assert_eq!(
392 serde_json::to_string(&NodeKind::CallSite).unwrap(),
393 "\"call_site\""
394 );
395 assert_eq!(
396 serde_json::to_string(&NodeKind::EnumVariant).unwrap(),
397 "\"enum_variant\""
398 );
399 }
400
401 #[test]
402 fn test_hash() {
403 use std::collections::HashSet;
404
405 let mut set = HashSet::new();
406 set.insert(NodeKind::Function);
407 set.insert(NodeKind::Method);
408 set.insert(NodeKind::Class);
409
410 assert!(set.contains(&NodeKind::Function));
411 assert!(!set.contains(&NodeKind::Variable));
412 assert_eq!(set.len(), 3);
413 }
414
415 #[test]
416 #[allow(clippy::clone_on_copy)] fn test_copy_clone() {
418 let kind = NodeKind::Function;
419 let copied = kind;
420 let cloned = kind.clone();
421
422 assert_eq!(kind, copied);
423 assert_eq!(kind, cloned);
424 }
425}