1
+use crate::{
2
+ AssignmentTarget, Expression, ExpressionOrSpread, ForInInit, ForInit, Function, FunctionBody,
3
+ Identifier, ImportDeclarationSpecifier, ImportOrExportDeclaration, Literal, ModuleItem,
4
+ Pattern, Program, Statement, SwitchCase, VariableDeclarator,
5
+};
6
+
7
+/// Trait for visiting an estree
8
+pub trait Visitor<'ast> {
9
+ fn visit_lvalue<F>(&mut self, f: F)
10
+ where
11
+ F: FnOnce(&mut Self) -> (),
12
+ {
13
+ f(self);
14
+ }
15
+
16
+ fn visit_program(&mut self, program: &'ast Program) {
17
+ for item in &program.body {
18
+ self.visit_module_item(item);
19
+ }
20
+ }
21
+
22
+ fn visit_function(&mut self, function: &'ast Function) {
23
+ self.default_visit_function(function);
24
+ }
25
+
26
+ fn default_visit_function(&mut self, function: &'ast Function) {
27
+ // todo: params and such
28
+ match &function.body {
29
+ Some(FunctionBody::BlockStatement(body)) => {
30
+ for stmt in &body.body {
31
+ self.visit_statement(stmt)
32
+ }
33
+ }
34
+ Some(FunctionBody::Expression(body)) => self.visit_expression(body),
35
+ None => {}
36
+ }
37
+ }
38
+
39
+ fn visit_module_item(&mut self, item: &'ast ModuleItem) {
40
+ match item {
41
+ ModuleItem::Statement(item) => self.visit_statement(item),
42
+ ModuleItem::ImportOrExportDeclaration(item) => {
43
+ self.visit_import_or_export_declaration(item)
44
+ }
45
+ }
46
+ }
47
+
48
+ fn visit_import_or_export_declaration(&mut self, declaration: &'ast ImportOrExportDeclaration) {
49
+ match declaration {
50
+ ImportOrExportDeclaration::ImportDeclaration(declaration) => {
51
+ self.visit_lvalue(|visitor| {
52
+ for specifier in &declaration.specifiers {
53
+ visitor.visit_import_declaration_specifier(specifier, &declaration.source)
54
+ }
55
+ });
56
+ self.visit_import_source(&declaration.source);
57
+ }
58
+ }
59
+ }
60
+
61
+ fn visit_import_declaration_specifier(
62
+ &mut self,
63
+ specifier: &'ast ImportDeclarationSpecifier,
64
+ _source: &'ast Literal,
65
+ ) {
66
+ match specifier {
67
+ ImportDeclarationSpecifier::ImportSpecifier(specifier) => {
68
+ self.visit_identifier(&specifier.local);
69
+ }
70
+ ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => {
71
+ self.visit_identifier(&specifier.local);
72
+ }
73
+ ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => {
74
+ self.visit_identifier(&specifier.local);
75
+ }
76
+ }
77
+ }
78
+
79
+ fn visit_statement(&mut self, stmt: &'ast Statement) {
80
+ self.default_visit_statement(stmt);
81
+ }
82
+
83
+ fn default_visit_statement(&mut self, stmt: &'ast Statement) {
84
+ match stmt {
85
+ Statement::BlockStatement(stmt) => {
86
+ for stmt in &stmt.body {
87
+ self.visit_statement(stmt)
88
+ }
89
+ }
90
+ Statement::BreakStatement(_stmt) => {
91
+ // todo
92
+ }
93
+ Statement::ContinueStatement(_stmt) => {
94
+ // todo
95
+ }
96
+ Statement::DebuggerStatement(_stmt) => {
97
+ // todo
98
+ }
99
+ Statement::DoWhileStatement(stmt) => {
100
+ self.visit_statement(&stmt.body);
101
+ self.visit_expression(&stmt.test);
102
+ }
103
+ Statement::EmptyStatement(_stmt) => {
104
+ // nothing to do
105
+ }
106
+ Statement::ExpressionStatement(stmt) => {
107
+ self.visit_expression(&stmt.expression);
108
+ }
109
+ Statement::ForInStatement(stmt) => {
110
+ self.visit_for_in_init(&stmt.left);
111
+ self.visit_expression(&stmt.right);
112
+ self.visit_statement(&stmt.body);
113
+ }
114
+ Statement::ForOfStatement(stmt) => {
115
+ self.visit_for_in_init(&stmt.left);
116
+ self.visit_expression(&stmt.right);
117
+ self.visit_statement(&stmt.body);
118
+ }
119
+ Statement::ForStatement(stmt) => {
120
+ if let Some(init) = &stmt.init {
121
+ self.visit_for_init(init);
122
+ }
123
+ if let Some(test) = &stmt.test {
124
+ self.visit_expression(test);
125
+ }
126
+ if let Some(update) = &stmt.update {
127
+ self.visit_expression(update);
128
+ }
129
+ self.visit_statement(&stmt.body);
130
+ }
131
+ Statement::FunctionDeclaration(stmt) => {
132
+ self.visit_function(&stmt.function);
133
+ }
134
+ Statement::IfStatement(stmt) => {
135
+ self.visit_expression(&stmt.test);
136
+ self.visit_statement(&stmt.consequent);
137
+ if let Some(alternate) = &stmt.alternate {
138
+ self.visit_statement(alternate);
139
+ }
140
+ }
141
+ Statement::LabeledStatement(stmt) => {
142
+ self.visit_statement(&stmt.body);
143
+ }
144
+ Statement::ReturnStatement(stmt) => {
145
+ if let Some(argument) = &stmt.argument {
146
+ self.visit_expression(argument);
147
+ }
148
+ }
149
+ Statement::SwitchStatement(stmt) => {
150
+ self.visit_expression(&stmt.discriminant);
151
+ for case_ in &stmt.cases {
152
+ self.visit_case(case_);
153
+ }
154
+ }
155
+ Statement::ThrowStatement(stmt) => {
156
+ self.visit_expression(&stmt.argument);
157
+ }
158
+ Statement::TryStatement(stmt) => {
159
+ for item in &stmt.block.body {
160
+ self.visit_statement(item);
161
+ }
162
+ if let Some(handler) = &stmt.handler {
163
+ self.visit_lvalue(|visitor| visitor.visit_pattern(&handler.param));
164
+ for item in &handler.body.body {
165
+ self.visit_statement(item);
166
+ }
167
+ }
168
+ if let Some(finalizer) = &stmt.finalizer {
169
+ for item in &finalizer.body {
170
+ self.visit_statement(item);
171
+ }
172
+ }
173
+ }
174
+ Statement::VariableDeclaration(stmt) => {
175
+ for decl in &stmt.declarations {
176
+ self.visit_variable_declarator(decl);
177
+ }
178
+ }
179
+ Statement::WhileStatement(stmt) => {
180
+ self.visit_expression(&stmt.test);
181
+ self.visit_statement(&stmt.body);
182
+ }
183
+ Statement::WithStatement(stmt) => {
184
+ self.visit_expression(&stmt.object);
185
+ self.visit_statement(&stmt.body);
186
+ }
187
+ }
188
+ }
189
+
190
+ fn visit_case(&mut self, case_: &'ast SwitchCase) {
191
+ if let Some(test) = &case_.test {
192
+ self.visit_expression(test);
193
+ }
194
+ for stmt in &case_.consequent {
195
+ self.visit_statement(stmt)
196
+ }
197
+ }
198
+
199
+ fn visit_for_init(&mut self, init: &'ast ForInit) {
200
+ match init {
201
+ ForInit::Expression(init) => {
202
+ self.visit_expression(init);
203
+ }
204
+ ForInit::VariableDeclaration(init) => {
205
+ for decl in &init.declarations {
206
+ self.visit_variable_declarator(decl);
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ fn visit_for_in_init(&mut self, init: &'ast ForInInit) {
213
+ match init {
214
+ ForInInit::Pattern(init) => {
215
+ self.visit_pattern(init);
216
+ }
217
+ ForInInit::VariableDeclaration(init) => {
218
+ for decl in &init.declarations {
219
+ self.visit_variable_declarator(decl);
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ fn visit_pattern(&mut self, pattern: &'ast Pattern) {
226
+ match pattern {
227
+ Pattern::Identifier(pattern) => self.visit_identifier(pattern),
228
+ }
229
+ }
230
+
231
+ fn visit_variable_declarator(&mut self, decl: &'ast VariableDeclarator) {
232
+ self.visit_lvalue(|visitor| {
233
+ visitor.visit_pattern(&decl.id);
234
+ });
235
+ if let Some(init) = &decl.init {
236
+ self.visit_expression(init);
237
+ }
238
+ }
239
+
240
+ fn visit_assignment_target(&mut self, target: &'ast AssignmentTarget) {
241
+ match target {
242
+ AssignmentTarget::Expression(target) => {
243
+ self.visit_expression(target);
244
+ }
245
+ AssignmentTarget::Pattern(target) => self.visit_pattern(target),
246
+ }
247
+ }
248
+
249
+ fn visit_expression(&mut self, expr: &'ast Expression) {
250
+ self.visit_expression(expr);
251
+ }
252
+
253
+ fn default_visit_expression(&mut self, expr: &'ast Expression) {
254
+ match expr {
255
+ Expression::ArrayExpression(expr) => {
256
+ for item in &expr.elements {
257
+ match item {
258
+ Some(ExpressionOrSpread::SpreadElement(item)) => {
259
+ self.visit_expression(&item.argument)
260
+ }
261
+ Some(ExpressionOrSpread::Expression(item)) => self.visit_expression(item),
262
+ _ => {}
263
+ }
264
+ }
265
+ }
266
+ Expression::AssignmentExpression(expr) => {
267
+ self.visit_lvalue(|visitor| visitor.visit_assignment_target(&expr.left));
268
+ self.visit_expression(&expr.right);
269
+ }
270
+ Expression::BinaryExpression(expr) => {
271
+ self.visit_expression(&expr.left);
272
+ self.visit_expression(&expr.right);
273
+ }
274
+ Expression::Identifier(expr) => {
275
+ self.visit_identifier(expr);
276
+ }
277
+ Expression::Literal(expr) => self.visit_literal(expr),
278
+ Expression::FunctionExpression(expr) => self.visit_function(&expr.function),
279
+ _ => {
280
+ todo!("more expression types")
281
+ }
282
+ }
283
+ }
284
+
285
+ fn visit_identifier(&mut self, _identifier: &'ast Identifier) {
286
+ // nothing to do unless overridden
287
+ }
288
+
289
+ fn visit_import_source(&mut self, literal: &'ast Literal) {
290
+ self.visit_literal(literal);
291
+ }
292
+
293
+ fn visit_literal(&mut self, _literal: &'ast Literal) {
294
+ // nothing to do unless overridden
295
+ }
296
+}