use rustc_hash::FxHashSet;
use swc_ecma_ast::{
BlockStmtOrExpr, Constructor, Function, GetterProp, Id, Ident, MemberProp, PropName, SetterProp,
};
use swc_ecma_visit::{noop_visit_type, visit_obj_and_computed, Visit, VisitWith};
pub(crate) fn ids_used_by<N>(n: &N) -> FxHashSet<Id>
where
N: VisitWith<IdentUsageCollector>,
{
let mut v = IdentUsageCollector {
ignore_nested: false,
..Default::default()
};
n.visit_with(&mut v);
v.ids
}
pub(crate) fn ids_used_by_ignoring_nested<N>(n: &N) -> FxHashSet<Id>
where
N: VisitWith<IdentUsageCollector>,
{
let mut v = IdentUsageCollector {
ignore_nested: true,
..Default::default()
};
n.visit_with(&mut v);
v.ids
}
#[derive(Default)]
pub(crate) struct IdentUsageCollector {
ids: FxHashSet<Id>,
ignore_nested: bool,
}
impl Visit for IdentUsageCollector {
noop_visit_type!();
visit_obj_and_computed!();
fn visit_block_stmt_or_expr(&mut self, n: &BlockStmtOrExpr) {
if self.ignore_nested {
return;
}
n.visit_children_with(self);
}
fn visit_constructor(&mut self, n: &Constructor) {
if self.ignore_nested {
return;
}
n.visit_children_with(self);
}
fn visit_function(&mut self, n: &Function) {
if self.ignore_nested {
return;
}
n.visit_children_with(self);
}
fn visit_getter_prop(&mut self, n: &GetterProp) {
if self.ignore_nested {
return;
}
n.visit_children_with(self);
}
fn visit_setter_prop(&mut self, n: &SetterProp) {
if self.ignore_nested {
return;
}
n.visit_children_with(self);
}
fn visit_ident(&mut self, n: &Ident) {
self.ids.insert(n.to_id());
}
fn visit_member_prop(&mut self, n: &MemberProp) {
if let MemberProp::Computed(..) = n {
n.visit_children_with(self);
}
}
fn visit_prop_name(&mut self, n: &PropName) {
if let PropName::Computed(..) = n {
n.visit_children_with(self);
}
}
}