oxc_ecmascript/
bound_names.rs

1use oxc_ast::ast::{
2    ArrayPattern, AssignmentPattern, BindingIdentifier, BindingPattern, BindingPatternKind,
3    BindingRestElement, Class, Declaration, ExportNamedDeclaration, FormalParameter,
4    FormalParameters, Function, ImportDeclaration, ImportDeclarationSpecifier, ModuleDeclaration,
5    ObjectPattern, VariableDeclaration,
6};
7
8/// [`BoundName`](https://tc39.es/ecma262/#sec-static-semantics-boundnames)
9pub trait BoundName<'a> {
10    fn bound_name<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F);
11}
12
13pub trait BoundNames<'a> {
14    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F);
15}
16
17impl<'a> BoundNames<'a> for BindingPattern<'a> {
18    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
19        match &self.kind {
20            BindingPatternKind::BindingIdentifier(ident) => ident.bound_names(f),
21            BindingPatternKind::ArrayPattern(array) => array.bound_names(f),
22            BindingPatternKind::ObjectPattern(object) => object.bound_names(f),
23            BindingPatternKind::AssignmentPattern(assignment) => assignment.bound_names(f),
24        }
25    }
26}
27
28impl<'a> BoundNames<'a> for BindingIdentifier<'a> {
29    fn bound_names<F: FnMut(&Self)>(&self, f: &mut F) {
30        f(self);
31    }
32}
33
34impl<'a> BoundNames<'a> for ArrayPattern<'a> {
35    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
36        for elem in self.elements.iter().flatten() {
37            elem.bound_names(f);
38        }
39        if let Some(rest) = &self.rest {
40            rest.bound_names(f);
41        }
42    }
43}
44
45impl<'a> BoundNames<'a> for ObjectPattern<'a> {
46    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
47        for p in &self.properties {
48            p.value.bound_names(f);
49        }
50        if let Some(rest) = &self.rest {
51            rest.bound_names(f);
52        }
53    }
54}
55
56impl<'a> BoundNames<'a> for AssignmentPattern<'a> {
57    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
58        self.left.bound_names(f);
59    }
60}
61
62impl<'a> BoundNames<'a> for BindingRestElement<'a> {
63    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
64        self.argument.bound_names(f);
65    }
66}
67
68impl<'a> BoundNames<'a> for FormalParameters<'a> {
69    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
70        for item in &self.items {
71            item.bound_names(f);
72        }
73        if let Some(rest) = &self.rest {
74            rest.bound_names(f);
75        }
76    }
77}
78
79impl<'a> BoundNames<'a> for Declaration<'a> {
80    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
81        match self {
82            Declaration::VariableDeclaration(decl) => decl.bound_names(f),
83            Declaration::FunctionDeclaration(func) => func.bound_names(f),
84            Declaration::ClassDeclaration(decl) => decl.bound_names(f),
85            _ => {}
86        }
87    }
88}
89
90impl<'a> BoundNames<'a> for VariableDeclaration<'a> {
91    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
92        for declarator in &self.declarations {
93            declarator.id.bound_names(f);
94        }
95    }
96}
97
98impl<'a> BoundName<'a> for Function<'a> {
99    fn bound_name<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
100        if let Some(ident) = &self.id {
101            f(ident);
102        }
103    }
104}
105
106impl<'a> BoundNames<'a> for Function<'a> {
107    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
108        self.bound_name(f);
109    }
110}
111
112impl<'a> BoundName<'a> for Class<'a> {
113    fn bound_name<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
114        if let Some(ident) = &self.id {
115            f(ident);
116        }
117    }
118}
119
120impl<'a> BoundNames<'a> for Class<'a> {
121    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
122        self.bound_name(f);
123    }
124}
125
126impl<'a> BoundNames<'a> for FormalParameter<'a> {
127    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
128        self.pattern.bound_names(f);
129    }
130}
131
132impl<'a> BoundNames<'a> for ModuleDeclaration<'a> {
133    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
134        match self {
135            ModuleDeclaration::ImportDeclaration(decl) => decl.bound_names(f),
136            ModuleDeclaration::ExportNamedDeclaration(decl) => decl.bound_names(f),
137            _ => {}
138        }
139    }
140}
141
142impl<'a> BoundNames<'a> for ImportDeclaration<'a> {
143    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
144        if let Some(specifiers) = &self.specifiers {
145            for specifier in specifiers {
146                match specifier {
147                    ImportDeclarationSpecifier::ImportSpecifier(specifier) => {
148                        f(&specifier.local);
149                    }
150                    ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => {
151                        f(&specifier.local);
152                    }
153                    ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => {
154                        f(&specifier.local);
155                    }
156                }
157            }
158        }
159    }
160}
161
162impl<'a> BoundNames<'a> for ExportNamedDeclaration<'a> {
163    fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
164        if let Some(decl) = &self.declaration {
165            decl.bound_names(f);
166        }
167    }
168}