oxc_traverse/ast_operations/
gather_node_parts.rs1use 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
36impl<'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
118impl<'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
130impl<'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
146impl<'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
178impl<'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
349impl<'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
371impl<'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
410impl<'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
443impl<'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
469impl<'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
499impl<'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}