1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use oxc_span::Atom;

use crate::ast::*;

// TODO: <https://github.com/babel/babel/blob/419644f27c5c59deb19e71aaabd417a3bc5483ca/packages/babel-traverse/src/scope/index.ts#L61>
pub trait GatherNodeParts<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F);
}

impl<'a> GatherNodeParts<'a> for Expression<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        match self {
            Self::Identifier(ident) => f(ident.name.clone()),
            match_member_expression!(Self) => self.to_member_expression().gather(f),
            Self::AssignmentExpression(expr) => expr.left.gather(f),
            Self::UpdateExpression(expr) => expr.argument.gather(f),
            Self::StringLiteral(lit) => lit.gather(f),
            _ => f(Atom::from("ref")),
        }
    }
}

impl<'a> GatherNodeParts<'a> for MemberExpression<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        match self {
            MemberExpression::ComputedMemberExpression(expr) => {
                expr.object.gather(f);
                expr.expression.gather(f);
            }
            MemberExpression::StaticMemberExpression(expr) => {
                expr.object.gather(f);
                expr.property.gather(f);
            }
            MemberExpression::PrivateFieldExpression(expr) => {
                expr.object.gather(f);
                expr.field.gather(f);
            }
        }
    }
}

impl<'a> GatherNodeParts<'a> for AssignmentTarget<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        match self {
            match_simple_assignment_target!(Self) => {
                self.to_simple_assignment_target().gather(f);
            }
            match_assignment_target_pattern!(Self) => {}
        }
    }
}

impl<'a> GatherNodeParts<'a> for SimpleAssignmentTarget<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        match self {
            Self::AssignmentTargetIdentifier(ident) => ident.gather(f),
            match_member_expression!(Self) => self.to_member_expression().gather(f),
            _ => {}
        }
    }
}

impl<'a> GatherNodeParts<'a> for IdentifierReference<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        f(self.name.clone());
    }
}

impl<'a> GatherNodeParts<'a> for IdentifierName<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        f(self.name.clone());
    }
}

impl<'a> GatherNodeParts<'a> for PrivateIdentifier<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        f(self.name.clone());
    }
}

impl<'a> GatherNodeParts<'a> for StringLiteral<'a> {
    fn gather<F: FnMut(Atom<'a>)>(&self, f: &mut F) {
        f(self.value.clone());
    }
}