1use paste::paste;
2use ra_ap_syntax::{
3 ast::{self, AstNode},
4 SyntaxKind, SyntaxNode,
5};
6
7pub(crate) const INTERNAL_ERR: &'static str =
8 "Internal error message in rust-visitor. Please create an issue on https://github.com/automa-app/cargo-up";
9
10pub use ra_ap_syntax;
11
12#[derive(Default, Debug)]
13pub struct Options {
14 skip_children: bool,
15}
16
17macro_rules! visiting {
18 () => {};
19 ($($kind:ident,)*) => {
20 trait Visitable: Sized {
21 fn accept<T: Visitor>(&self, visitor: &mut T);
22 }
23
24 impl Visitable for SyntaxNode {
25 fn accept<T: Visitor>(&self, visitor: &mut T) {
26 let mut options = Options::default();
27
28 visitor.pre_visit(self);
29
30 paste! {
31 match self.kind() {
32 $(SyntaxKind::$kind => visitor.[<visit_ $kind:lower>](
33 &ast::[<$kind:camel>]::cast((*self).clone()).expect(INTERNAL_ERR),
34 &mut options,
35 ),)*
36 _ => {},
37 };
38 };
39
40 if !options.skip_children {
41 for child in self.children() {
42 child.accept(visitor);
43 }
44 }
45
46 visitor.post_visit(self);
47 }
48 }
49
50 pub trait Visitor: Sized {
51 fn walk(&mut self, node: &SyntaxNode) {
53 node.accept(self);
54 }
55
56 fn pre_visit(&mut self, _node: &SyntaxNode) {}
58
59 fn post_visit(&mut self, _node: &SyntaxNode) {}
61
62 paste! {
63 $(
64 #[doc = " This method is called when visiting a `" $kind "` node."]
65 fn [<visit_ $kind:lower>](&mut self, _node: &ast::[<$kind:camel>], _options: &mut Options) {}
66 )*
67 }
68 }
69 };
70}
71
72visiting!(
73 SOURCE_FILE,
74 STRUCT,
75 UNION,
76 ENUM,
77 FN,
78 RET_TYPE,
79 EXTERN_CRATE,
80 MODULE,
81 USE,
82 STATIC,
83 CONST,
84 TRAIT,
85 IMPL,
86 TYPE_ALIAS,
87 MACRO_CALL,
88 MACRO_RULES,
89 TOKEN_TREE,
90 MACRO_DEF,
91 PAREN_TYPE,
92 TUPLE_TYPE,
93 MACRO_TYPE,
94 NEVER_TYPE,
95 PATH_TYPE,
96 PTR_TYPE,
97 ARRAY_TYPE,
98 SLICE_TYPE,
99 REF_TYPE,
100 INFER_TYPE,
101 FN_PTR_TYPE,
102 FOR_TYPE,
103 IMPL_TRAIT_TYPE,
104 DYN_TRAIT_TYPE,
105 OR_PAT,
106 PAREN_PAT,
107 REF_PAT,
108 BOX_PAT,
109 IDENT_PAT,
110 WILDCARD_PAT,
111 REST_PAT,
112 PATH_PAT,
113 RECORD_PAT,
114 RECORD_PAT_FIELD_LIST,
115 RECORD_PAT_FIELD,
116 TUPLE_STRUCT_PAT,
117 TUPLE_PAT,
118 SLICE_PAT,
119 RANGE_PAT,
120 LITERAL_PAT,
121 MACRO_PAT,
122 CONST_BLOCK_PAT,
123 TUPLE_EXPR,
124 ARRAY_EXPR,
125 PAREN_EXPR,
126 PATH_EXPR,
127 CLOSURE_EXPR,
128 IF_EXPR,
129 WHILE_EXPR,
130 CONDITION,
131 LOOP_EXPR,
132 FOR_EXPR,
133 CONTINUE_EXPR,
134 BREAK_EXPR,
135 LABEL,
136 BLOCK_EXPR,
137 STMT_LIST,
138 RETURN_EXPR,
139 YIELD_EXPR,
140 MATCH_EXPR,
141 MATCH_ARM_LIST,
142 MATCH_ARM,
143 MATCH_GUARD,
144 RECORD_EXPR,
145 RECORD_EXPR_FIELD_LIST,
146 RECORD_EXPR_FIELD,
147 BOX_EXPR,
148 CALL_EXPR,
149 INDEX_EXPR,
150 METHOD_CALL_EXPR,
151 FIELD_EXPR,
152 AWAIT_EXPR,
153 TRY_EXPR,
154 CAST_EXPR,
155 REF_EXPR,
156 PREFIX_EXPR,
157 RANGE_EXPR,
158 BIN_EXPR,
159 EXTERN_BLOCK,
160 EXTERN_ITEM_LIST,
161 VARIANT,
162 RECORD_FIELD_LIST,
163 RECORD_FIELD,
164 TUPLE_FIELD_LIST,
165 TUPLE_FIELD,
166 VARIANT_LIST,
167 ITEM_LIST,
168 ASSOC_ITEM_LIST,
169 ATTR,
170 META,
171 USE_TREE,
172 USE_TREE_LIST,
173 PATH,
174 PATH_SEGMENT,
175 LITERAL,
176 RENAME,
177 VISIBILITY,
178 WHERE_CLAUSE,
179 WHERE_PRED,
180 ABI,
181 NAME,
182 NAME_REF,
183 LET_STMT,
184 LET_ELSE,
185 EXPR_STMT,
186 GENERIC_PARAM_LIST,
187 GENERIC_PARAM,
188 LIFETIME_PARAM,
189 TYPE_PARAM,
190 CONST_PARAM,
191 GENERIC_ARG_LIST,
192 LIFETIME,
193 LIFETIME_ARG,
194 TYPE_ARG,
195 ASSOC_TYPE_ARG,
196 CONST_ARG,
197 PARAM_LIST,
198 PARAM,
199 SELF_PARAM,
200 ARG_LIST,
201 TYPE_BOUND,
202 TYPE_BOUND_LIST,
203 MACRO_ITEMS,
204 MACRO_STMTS,
205);