oxc_traverse/ast_operations/
gather_node_parts.rs

1//! Gather node parts trait.
2//!
3//! Ported from: <https://github.com/babel/babel/blob/419644f27c5c59deb19e71aaabd417a3bc5483ca/packages/babel-traverse/src/scope/index.ts>
4//!
5//! This trait is used to gather all the parts of a node that are identifiers.
6
7use oxc_ast::ast::*;
8use oxc_ecmascript::BoundNames;
9
10use super::to_identifier;
11
12pub fn get_var_name_from_node<'a, N: GatherNodeParts<'a>>(node: &N) -> String {
13    let mut name = String::new();
14    node.gather(&mut |mut part| {
15        if name.is_empty() {
16            part = part.trim_start_matches('_');
17        } else {
18            name.push('$');
19        }
20        name.push_str(part);
21    });
22
23    if name.is_empty() {
24        name = "ref".to_string();
25    } else {
26        name.truncate(20);
27    }
28
29    to_identifier(name)
30}
31
32pub trait GatherNodeParts<'a> {
33    fn gather<F: FnMut(&str)>(&self, f: &mut F);
34}
35
36// -------------------- ModuleDeclaration --------------------
37impl<'a> GatherNodeParts<'a> for ImportDeclaration<'a> {
38    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
39        self.source.gather(f);
40    }
41}
42
43impl<'a> GatherNodeParts<'a> for ExportAllDeclaration<'a> {
44    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
45        self.source.gather(f);
46    }
47}
48
49impl<'a> GatherNodeParts<'a> for ExportNamedDeclaration<'a> {
50    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
51        if let Some(source) = &self.source {
52            source.gather(f);
53        } else if let Some(declaration) = &self.declaration {
54            declaration.gather(f);
55        } else {
56            for specifier in &self.specifiers {
57                specifier.gather(f);
58            }
59        }
60    }
61}
62
63impl<'a> GatherNodeParts<'a> for ExportDefaultDeclaration<'a> {
64    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
65        self.declaration.gather(f);
66    }
67}
68
69impl<'a> GatherNodeParts<'a> for ExportDefaultDeclarationKind<'a> {
70    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
71        match self {
72            ExportDefaultDeclarationKind::FunctionDeclaration(decl) => decl.gather(f),
73            ExportDefaultDeclarationKind::ClassDeclaration(decl) => decl.gather(f),
74            ExportDefaultDeclarationKind::TSInterfaceDeclaration(_) => {}
75            match_expression!(ExportDefaultDeclarationKind) => self.to_expression().gather(f),
76        }
77    }
78}
79
80impl<'a> GatherNodeParts<'a> for ExportSpecifier<'a> {
81    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
82        match &self.local {
83            ModuleExportName::IdentifierName(ident) => ident.gather(f),
84            ModuleExportName::IdentifierReference(ident) => ident.gather(f),
85            ModuleExportName::StringLiteral(lit) => lit.gather(f),
86        }
87    }
88}
89
90impl<'a> GatherNodeParts<'a> for ModuleExportName<'a> {
91    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
92        match self {
93            ModuleExportName::IdentifierName(ident) => ident.gather(f),
94            ModuleExportName::IdentifierReference(ident) => ident.gather(f),
95            ModuleExportName::StringLiteral(lit) => lit.gather(f),
96        }
97    }
98}
99
100impl<'a> GatherNodeParts<'a> for ImportSpecifier<'a> {
101    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
102        self.local.gather(f);
103    }
104}
105
106impl<'a> GatherNodeParts<'a> for ImportDefaultSpecifier<'a> {
107    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
108        self.local.gather(f);
109    }
110}
111
112impl<'a> GatherNodeParts<'a> for ImportNamespaceSpecifier<'a> {
113    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
114        self.local.gather(f);
115    }
116}
117
118// -------------------- Declaration --------------------
119
120impl<'a> GatherNodeParts<'a> for Declaration<'a> {
121    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
122        match self {
123            Self::FunctionDeclaration(decl) => decl.gather(f),
124            Self::ClassDeclaration(decl) => decl.gather(f),
125            _ => (),
126        }
127    }
128}
129
130// -------------------- Function --------------------
131
132impl<'a> GatherNodeParts<'a> for Function<'a> {
133    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
134        if let Some(id) = &self.id {
135            id.gather(f);
136        }
137    }
138}
139
140impl<'a> GatherNodeParts<'a> for BindingRestElement<'a> {
141    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
142        self.argument.gather(f);
143    }
144}
145
146// -------------------- BindingPattern --------------------
147
148impl<'a> GatherNodeParts<'a> for VariableDeclarator<'a> {
149    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
150        self.id.gather(f);
151    }
152}
153
154impl<'a> GatherNodeParts<'a> for BindingPattern<'a> {
155    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
156        self.bound_names(&mut |id| f(id.name.as_str()));
157    }
158}
159
160impl<'a> GatherNodeParts<'a> for ObjectPattern<'a> {
161    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
162        self.bound_names(&mut |id| f(id.name.as_str()));
163    }
164}
165
166impl<'a> GatherNodeParts<'a> for ArrayPattern<'a> {
167    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
168        self.bound_names(&mut |id| f(id.name.as_str()));
169    }
170}
171
172impl<'a> GatherNodeParts<'a> for AssignmentPattern<'a> {
173    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
174        self.bound_names(&mut |id| f(id.name.as_str()));
175    }
176}
177
178// -------------------- Expression --------------------
179
180impl<'a> GatherNodeParts<'a> for Expression<'a> {
181    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
182        match self {
183            match_member_expression!(Self) => self.to_member_expression().gather(f),
184            Self::Identifier(ident) => ident.gather(f),
185            Self::CallExpression(expr) => expr.gather(f),
186            Self::NewExpression(expr) => expr.gather(f),
187            Self::ObjectExpression(expr) => expr.gather(f),
188            Self::ThisExpression(expr) => expr.gather(f),
189            Self::Super(expr) => expr.gather(f),
190            Self::ImportExpression(expr) => expr.gather(f),
191            Self::YieldExpression(expr) => expr.gather(f),
192            Self::AwaitExpression(expr) => expr.gather(f),
193            Self::AssignmentExpression(expr) => expr.gather(f),
194            Self::FunctionExpression(expr) => expr.gather(f),
195            Self::ClassExpression(expr) => expr.gather(f),
196            Self::ParenthesizedExpression(expr) => expr.gather(f),
197            Self::UnaryExpression(expr) => expr.gather(f),
198            Self::UpdateExpression(expr) => expr.gather(f),
199            Self::ChainExpression(expr) => expr.gather(f),
200            Self::MetaProperty(expr) => expr.gather(f),
201            Self::JSXElement(expr) => expr.gather(f),
202            Self::JSXFragment(expr) => expr.gather(f),
203            Self::StringLiteral(expr) => expr.gather(f),
204            Self::NumericLiteral(expr) => expr.gather(f),
205            Self::BooleanLiteral(expr) => expr.gather(f),
206            Self::BigIntLiteral(expr) => expr.gather(f),
207            _ => (),
208        }
209    }
210}
211
212impl<'a> GatherNodeParts<'a> for ChainExpression<'a> {
213    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
214        self.expression.gather(f);
215    }
216}
217
218impl<'a> GatherNodeParts<'a> for ChainElement<'a> {
219    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
220        match self {
221            ChainElement::CallExpression(expr) => expr.gather(f),
222            expr => expr.to_member_expression().gather(f),
223        }
224    }
225}
226
227impl<'a> GatherNodeParts<'a> for MemberExpression<'a> {
228    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
229        match self {
230            MemberExpression::ComputedMemberExpression(expr) => {
231                expr.gather(f);
232            }
233            MemberExpression::StaticMemberExpression(expr) => {
234                expr.gather(f);
235            }
236            MemberExpression::PrivateFieldExpression(expr) => {
237                expr.gather(f);
238            }
239        }
240    }
241}
242
243impl<'a> GatherNodeParts<'a> for ComputedMemberExpression<'a> {
244    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
245        self.object.gather(f);
246        self.expression.gather(f);
247    }
248}
249
250impl<'a> GatherNodeParts<'a> for StaticMemberExpression<'a> {
251    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
252        self.object.gather(f);
253        self.property.gather(f);
254    }
255}
256
257impl<'a> GatherNodeParts<'a> for PrivateFieldExpression<'a> {
258    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
259        self.object.gather(f);
260        self.field.gather(f);
261    }
262}
263
264impl<'a> GatherNodeParts<'a> for CallExpression<'a> {
265    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
266        self.callee.gather(f);
267    }
268}
269
270impl<'a> GatherNodeParts<'a> for NewExpression<'a> {
271    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
272        self.callee.gather(f);
273    }
274}
275
276impl<'a> GatherNodeParts<'a> for ObjectExpression<'a> {
277    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
278        for prop in &self.properties {
279            prop.gather(f);
280        }
281    }
282}
283
284impl GatherNodeParts<'_> for ThisExpression {
285    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
286        f("this");
287    }
288}
289
290impl GatherNodeParts<'_> for Super {
291    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
292        f("super");
293    }
294}
295
296impl<'a> GatherNodeParts<'a> for ImportExpression<'a> {
297    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
298        f("import");
299    }
300}
301
302impl<'a> GatherNodeParts<'a> for YieldExpression<'a> {
303    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
304        f("yield");
305        if let Some(argument) = &self.argument {
306            argument.gather(f);
307        }
308    }
309}
310
311impl<'a> GatherNodeParts<'a> for AwaitExpression<'a> {
312    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
313        f("await");
314        self.argument.gather(f);
315    }
316}
317
318impl<'a> GatherNodeParts<'a> for AssignmentExpression<'a> {
319    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
320        self.left.gather(f);
321    }
322}
323
324impl<'a> GatherNodeParts<'a> for ParenthesizedExpression<'a> {
325    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
326        self.expression.gather(f);
327    }
328}
329
330impl<'a> GatherNodeParts<'a> for UnaryExpression<'a> {
331    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
332        self.argument.gather(f);
333    }
334}
335
336impl<'a> GatherNodeParts<'a> for UpdateExpression<'a> {
337    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
338        self.argument.gather(f);
339    }
340}
341
342impl<'a> GatherNodeParts<'a> for MetaProperty<'a> {
343    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
344        self.meta.gather(f);
345        self.property.gather(f);
346    }
347}
348
349// -------------------- AssignmentTarget --------------------
350impl<'a> GatherNodeParts<'a> for AssignmentTarget<'a> {
351    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
352        match self {
353            match_simple_assignment_target!(Self) => {
354                self.to_simple_assignment_target().gather(f);
355            }
356            match_assignment_target_pattern!(Self) => {}
357        }
358    }
359}
360
361impl<'a> GatherNodeParts<'a> for SimpleAssignmentTarget<'a> {
362    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
363        match self {
364            Self::AssignmentTargetIdentifier(ident) => ident.gather(f),
365            match_member_expression!(Self) => self.to_member_expression().gather(f),
366            _ => {}
367        }
368    }
369}
370
371// -------------------- Classes --------------------
372
373impl<'a> GatherNodeParts<'a> for Class<'a> {
374    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
375        if let Some(id) = &self.id {
376            id.gather(f);
377        }
378    }
379}
380
381impl<'a> GatherNodeParts<'a> for ClassElement<'a> {
382    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
383        match self {
384            ClassElement::PropertyDefinition(def) => def.gather(f),
385            ClassElement::MethodDefinition(def) => def.gather(f),
386            ClassElement::AccessorProperty(def) => def.gather(f),
387            _ => (),
388        }
389    }
390}
391
392impl<'a> GatherNodeParts<'a> for PropertyDefinition<'a> {
393    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
394        self.key.gather(f);
395    }
396}
397
398impl<'a> GatherNodeParts<'a> for MethodDefinition<'a> {
399    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
400        self.key.gather(f);
401    }
402}
403
404impl<'a> GatherNodeParts<'a> for AccessorProperty<'a> {
405    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
406        self.key.gather(f);
407    }
408}
409
410// -------------------- Objects --------------------
411
412impl<'a> GatherNodeParts<'a> for ObjectPropertyKind<'a> {
413    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
414        match self {
415            ObjectPropertyKind::ObjectProperty(prop) => prop.gather(f),
416            ObjectPropertyKind::SpreadProperty(prop) => prop.gather(f),
417        }
418    }
419}
420
421impl<'a> GatherNodeParts<'a> for ObjectProperty<'a> {
422    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
423        self.key.gather(f);
424    }
425}
426
427impl<'a> GatherNodeParts<'a> for PropertyKey<'a> {
428    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
429        match self {
430            PropertyKey::StaticIdentifier(ident) => ident.gather(f),
431            PropertyKey::PrivateIdentifier(ident) => ident.gather(f),
432            match_expression!(Self) => self.to_expression().gather(f),
433        }
434    }
435}
436
437impl<'a> GatherNodeParts<'a> for SpreadElement<'a> {
438    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
439        self.argument.gather(f);
440    }
441}
442
443// -------------------- Identifiers --------------------
444
445impl<'a> GatherNodeParts<'a> for BindingIdentifier<'a> {
446    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
447        f(self.name.as_str());
448    }
449}
450
451impl<'a> GatherNodeParts<'a> for IdentifierReference<'a> {
452    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
453        f(self.name.as_str());
454    }
455}
456
457impl<'a> GatherNodeParts<'a> for IdentifierName<'a> {
458    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
459        f(self.name.as_str());
460    }
461}
462
463impl<'a> GatherNodeParts<'a> for PrivateIdentifier<'a> {
464    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
465        f(self.name.as_str());
466    }
467}
468
469// -------------------- Literals --------------------
470
471impl<'a> GatherNodeParts<'a> for StringLiteral<'a> {
472    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
473        f(self.value.as_str());
474    }
475}
476
477impl<'a> GatherNodeParts<'a> for NumericLiteral<'a> {
478    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
479        f(&self.raw_str());
480    }
481}
482
483impl GatherNodeParts<'_> for BooleanLiteral {
484    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
485        if self.value {
486            f("true");
487        } else {
488            f("false");
489        }
490    }
491}
492
493impl<'a> GatherNodeParts<'a> for BigIntLiteral<'a> {
494    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
495        f(self.value.as_str());
496    }
497}
498
499// -------------------- JSX --------------------
500
501impl<'a> GatherNodeParts<'a> for JSXElement<'a> {
502    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
503        self.opening_element.gather(f);
504    }
505}
506
507impl<'a> GatherNodeParts<'a> for JSXFragment<'a> {
508    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
509        self.opening_fragment.gather(f);
510    }
511}
512
513impl<'a> GatherNodeParts<'a> for JSXOpeningElement<'a> {
514    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
515        self.name.gather(f);
516    }
517}
518
519impl GatherNodeParts<'_> for JSXOpeningFragment {
520    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
521        f("Fragment");
522    }
523}
524
525impl<'a> GatherNodeParts<'a> for JSXElementName<'a> {
526    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
527        match self {
528            JSXElementName::Identifier(ident) => ident.gather(f),
529            JSXElementName::IdentifierReference(ident) => ident.gather(f),
530            JSXElementName::NamespacedName(ns) => ns.gather(f),
531            JSXElementName::MemberExpression(expr) => expr.gather(f),
532            JSXElementName::ThisExpression(expr) => expr.gather(f),
533        }
534    }
535}
536
537impl<'a> GatherNodeParts<'a> for JSXNamespacedName<'a> {
538    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
539        self.namespace.gather(f);
540        self.name.gather(f);
541    }
542}
543
544impl<'a> GatherNodeParts<'a> for JSXMemberExpression<'a> {
545    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
546        self.object.gather(f);
547        self.property.gather(f);
548    }
549}
550
551impl<'a> GatherNodeParts<'a> for JSXMemberExpressionObject<'a> {
552    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
553        match self {
554            JSXMemberExpressionObject::IdentifierReference(ident) => ident.gather(f),
555            JSXMemberExpressionObject::MemberExpression(expr) => expr.gather(f),
556            JSXMemberExpressionObject::ThisExpression(expr) => expr.gather(f),
557        }
558    }
559}
560
561impl<'a> GatherNodeParts<'a> for JSXIdentifier<'a> {
562    fn gather<F: FnMut(&str)>(&self, f: &mut F) {
563        f(self.name.as_str());
564    }
565}