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 TypeParameter,
132
133 Annotation,
135
136 AnnotationValue,
138
139 LambdaTarget,
141
142 JavaModule,
144
145 EnumConstant,
147
148 #[serde(other)]
154 Other,
155}
156
157impl NodeKind {
158 #[inline]
160 #[must_use]
161 pub const fn is_callable(self) -> bool {
162 matches!(self, Self::Function | Self::Method | Self::Macro)
163 }
164
165 #[inline]
167 #[must_use]
168 pub const fn is_type_definition(self) -> bool {
169 matches!(
170 self,
171 Self::Class | Self::Interface | Self::Trait | Self::Struct | Self::Enum | Self::Type
172 )
173 }
174
175 #[inline]
177 #[must_use]
178 pub const fn is_container(self) -> bool {
179 matches!(
180 self,
181 Self::Class
182 | Self::Interface
183 | Self::Trait
184 | Self::Struct
185 | Self::Module
186 | Self::Enum
187 | Self::StyleRule
188 | Self::StyleAtRule
189 | Self::JavaModule
190 )
191 }
192
193 #[inline]
195 #[must_use]
196 pub const fn is_boundary(self) -> bool {
197 matches!(self, Self::Import | Self::Export)
198 }
199
200 #[inline]
202 #[must_use]
203 pub const fn is_lifetime(self) -> bool {
204 matches!(self, Self::Lifetime)
205 }
206
207 #[must_use]
209 pub const fn as_str(self) -> &'static str {
210 match self {
211 Self::Function => "function",
212 Self::Method => "method",
213 Self::Class => "class",
214 Self::Interface => "interface",
215 Self::Trait => "trait",
216 Self::Module => "module",
217 Self::Variable => "variable",
218 Self::Constant => "constant",
219 Self::Type => "type",
220 Self::Struct => "struct",
221 Self::Enum => "enum",
222 Self::EnumVariant => "enum_variant",
223 Self::Macro => "macro",
224 Self::Parameter => "parameter",
225 Self::Property => "property",
226 Self::CallSite => "call_site",
227 Self::Import => "import",
228 Self::Export => "export",
229 Self::StyleRule => "style_rule",
230 Self::StyleAtRule => "style_at_rule",
231 Self::StyleVariable => "style_variable",
232 Self::Lifetime => "lifetime",
233 Self::Component => "component",
234 Self::Service => "service",
235 Self::Resource => "resource",
236 Self::Endpoint => "endpoint",
237 Self::Test => "test",
238 Self::TypeParameter => "type_parameter",
239 Self::Annotation => "annotation",
240 Self::AnnotationValue => "annotation_value",
241 Self::LambdaTarget => "lambda_target",
242 Self::JavaModule => "java_module",
243 Self::EnumConstant => "enum_constant",
244 Self::Other => "other",
245 }
246 }
247
248 #[must_use]
252 pub fn parse(s: &str) -> Option<Self> {
253 match s {
254 "function" => Some(Self::Function),
255 "method" => Some(Self::Method),
256 "class" => Some(Self::Class),
257 "interface" => Some(Self::Interface),
258 "trait" => Some(Self::Trait),
259 "module" => Some(Self::Module),
260 "variable" => Some(Self::Variable),
261 "constant" => Some(Self::Constant),
262 "type" => Some(Self::Type),
263 "struct" => Some(Self::Struct),
264 "enum" => Some(Self::Enum),
265 "enum_variant" => Some(Self::EnumVariant),
266 "macro" => Some(Self::Macro),
267 "parameter" => Some(Self::Parameter),
268 "property" => Some(Self::Property),
269 "call_site" => Some(Self::CallSite),
270 "import" => Some(Self::Import),
271 "export" => Some(Self::Export),
272 "style_rule" => Some(Self::StyleRule),
273 "style_at_rule" => Some(Self::StyleAtRule),
274 "style_variable" => Some(Self::StyleVariable),
275 "lifetime" => Some(Self::Lifetime),
276 "component" => Some(Self::Component),
277 "service" => Some(Self::Service),
278 "resource" => Some(Self::Resource),
279 "endpoint" => Some(Self::Endpoint),
280 "test" => Some(Self::Test),
281 "type_parameter" => Some(Self::TypeParameter),
282 "annotation" => Some(Self::Annotation),
283 "annotation_value" => Some(Self::AnnotationValue),
284 "lambda_target" => Some(Self::LambdaTarget),
285 "java_module" => Some(Self::JavaModule),
286 "enum_constant" => Some(Self::EnumConstant),
287 "other" => Some(Self::Other),
288 _ => None,
289 }
290 }
291}
292
293impl fmt::Display for NodeKind {
294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 f.write_str(self.as_str())
296 }
297}
298
299impl Default for NodeKind {
300 fn default() -> Self {
302 Self::Function
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn test_node_kind_as_str() {
312 assert_eq!(NodeKind::Function.as_str(), "function");
313 assert_eq!(NodeKind::Method.as_str(), "method");
314 assert_eq!(NodeKind::Class.as_str(), "class");
315 assert_eq!(NodeKind::CallSite.as_str(), "call_site");
316 assert_eq!(NodeKind::EnumVariant.as_str(), "enum_variant");
317 }
318
319 #[test]
320 fn test_node_kind_parse() {
321 assert_eq!(NodeKind::parse("function"), Some(NodeKind::Function));
322 assert_eq!(NodeKind::parse("call_site"), Some(NodeKind::CallSite));
323 assert_eq!(NodeKind::parse("unknown"), None);
324 }
325
326 #[test]
327 fn test_node_kind_display() {
328 assert_eq!(format!("{}", NodeKind::Function), "function");
329 assert_eq!(format!("{}", NodeKind::EnumVariant), "enum_variant");
330 }
331
332 #[test]
333 fn test_is_callable() {
334 assert!(NodeKind::Function.is_callable());
335 assert!(NodeKind::Method.is_callable());
336 assert!(NodeKind::Macro.is_callable());
337 assert!(!NodeKind::Class.is_callable());
338 assert!(!NodeKind::Variable.is_callable());
339 }
340
341 #[test]
342 fn test_is_type_definition() {
343 assert!(NodeKind::Class.is_type_definition());
344 assert!(NodeKind::Interface.is_type_definition());
345 assert!(NodeKind::Trait.is_type_definition());
346 assert!(NodeKind::Struct.is_type_definition());
347 assert!(NodeKind::Enum.is_type_definition());
348 assert!(NodeKind::Type.is_type_definition());
349 assert!(!NodeKind::Function.is_type_definition());
350 assert!(!NodeKind::Variable.is_type_definition());
351 }
352
353 #[test]
354 fn test_is_container() {
355 assert!(NodeKind::Class.is_container());
356 assert!(NodeKind::Module.is_container());
357 assert!(NodeKind::Struct.is_container());
358 assert!(!NodeKind::Function.is_container());
359 assert!(!NodeKind::Variable.is_container());
360 }
361
362 #[test]
363 fn test_is_boundary() {
364 assert!(NodeKind::Import.is_boundary());
365 assert!(NodeKind::Export.is_boundary());
366 assert!(!NodeKind::Function.is_boundary());
367 }
368
369 #[test]
370 fn test_is_lifetime() {
371 assert!(NodeKind::Lifetime.is_lifetime());
372 assert!(!NodeKind::Function.is_lifetime());
373 assert!(!NodeKind::Variable.is_lifetime());
374 }
375
376 #[test]
377 fn test_lifetime_serialization() {
378 assert_eq!(NodeKind::Lifetime.as_str(), "lifetime");
379 assert_eq!(NodeKind::parse("lifetime"), Some(NodeKind::Lifetime));
380
381 let json = serde_json::to_string(&NodeKind::Lifetime).unwrap();
383 assert_eq!(json, "\"lifetime\"");
384 let deserialized: NodeKind = serde_json::from_str(&json).unwrap();
385 assert_eq!(deserialized, NodeKind::Lifetime);
386 }
387
388 #[test]
389 fn test_default() {
390 assert_eq!(NodeKind::default(), NodeKind::Function);
391 }
392
393 #[test]
394 fn test_serde_roundtrip() {
395 let kinds = [
396 NodeKind::Function,
397 NodeKind::Method,
398 NodeKind::Class,
399 NodeKind::CallSite,
400 NodeKind::EnumVariant,
401 ];
402
403 for kind in kinds {
404 let json = serde_json::to_string(&kind).unwrap();
406 let deserialized: NodeKind = serde_json::from_str(&json).unwrap();
407 assert_eq!(kind, deserialized);
408
409 let bytes = postcard::to_allocvec(&kind).unwrap();
411 let deserialized: NodeKind = postcard::from_bytes(&bytes).unwrap();
412 assert_eq!(kind, deserialized);
413 }
414 }
415
416 #[test]
417 fn test_json_format() {
418 assert_eq!(
420 serde_json::to_string(&NodeKind::Function).unwrap(),
421 "\"function\""
422 );
423 assert_eq!(
424 serde_json::to_string(&NodeKind::CallSite).unwrap(),
425 "\"call_site\""
426 );
427 assert_eq!(
428 serde_json::to_string(&NodeKind::EnumVariant).unwrap(),
429 "\"enum_variant\""
430 );
431 }
432
433 #[test]
434 fn test_hash() {
435 use std::collections::HashSet;
436
437 let mut set = HashSet::new();
438 set.insert(NodeKind::Function);
439 set.insert(NodeKind::Method);
440 set.insert(NodeKind::Class);
441
442 assert!(set.contains(&NodeKind::Function));
443 assert!(!set.contains(&NodeKind::Variable));
444 assert_eq!(set.len(), 3);
445 }
446
447 #[test]
448 #[allow(clippy::clone_on_copy)] fn test_copy_clone() {
450 let kind = NodeKind::Function;
451 let copied = kind;
452 let cloned = kind.clone();
453
454 assert_eq!(kind, copied);
455 assert_eq!(kind, cloned);
456 }
457}