Skip to main content

rs_hack/
visitor.rs

1//! AST visitor that walks syn trees to collect node matches
2//! (structs, enums, functions, match expressions).
3
4use syn::spanned::Spanned;
5use syn::visit::Visit;
6use syn::*;
7
8#[allow(dead_code)]
9pub struct NodeFinder {
10    pub matches: Vec<NodeMatch>,
11}
12
13#[derive(Debug, Clone)]
14#[allow(dead_code)]
15pub enum NodeMatch {
16    Struct {
17        name: String,
18        span: proc_macro2::Span,
19    },
20    Enum {
21        name: String,
22        span: proc_macro2::Span,
23    },
24    Function {
25        name: String,
26        span: proc_macro2::Span,
27    },
28    MatchExpr {
29        span: proc_macro2::Span,
30    },
31}
32
33#[allow(dead_code)]
34impl Default for NodeFinder {
35    fn default() -> Self {
36        Self::new()
37    }
38}
39
40impl NodeFinder {
41    pub const fn new() -> Self {
42        Self {
43            matches: Vec::new(),
44        }
45    }
46}
47
48impl<'ast> Visit<'ast> for NodeFinder {
49    fn visit_item_struct(&mut self, node: &'ast ItemStruct) {
50        self.matches.push(NodeMatch::Struct {
51            name: node.ident.to_string(),
52            span: node.span(),
53        });
54        syn::visit::visit_item_struct(self, node);
55    }
56
57    fn visit_item_enum(&mut self, node: &'ast ItemEnum) {
58        self.matches.push(NodeMatch::Enum {
59            name: node.ident.to_string(),
60            span: node.span(),
61        });
62        syn::visit::visit_item_enum(self, node);
63    }
64
65    fn visit_item_fn(&mut self, node: &'ast ItemFn) {
66        self.matches.push(NodeMatch::Function {
67            name: node.sig.ident.to_string(),
68            span: node.span(),
69        });
70        syn::visit::visit_item_fn(self, node);
71    }
72
73    fn visit_expr_match(&mut self, node: &'ast ExprMatch) {
74        self.matches
75            .push(NodeMatch::MatchExpr { span: node.span() });
76        syn::visit::visit_expr_match(self, node);
77    }
78}