use rspack_cacheable::{cacheable, with::AsPreset};
use swc_core::{
atoms::Atom,
ecma::{
ast::{ClassExpr, Ident, ObjectPatProp, Prop},
visit::{Visit, VisitWith, noop_visit_type},
},
};
use crate::DependencyRange;
#[derive(Clone, Debug)]
pub struct ConcatenatedModuleIdent {
pub id: Ident,
pub shorthand: bool,
pub is_class_expr_with_ident: bool,
}
#[cacheable]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ConcatenationScopeIdentKind {
TopLevel,
Global,
UsedName,
}
#[cacheable]
#[derive(Clone, Debug)]
pub struct ConcatenationScopeIdent {
pub range: DependencyRange,
pub shorthand: bool,
pub kind: ConcatenationScopeIdentKind,
}
#[cacheable]
#[derive(Clone, Debug)]
pub struct ConcatenationScopeCanonicalName {
pub range: DependencyRange,
#[cacheable(with=AsPreset)]
pub name: Atom,
}
#[cacheable]
#[derive(Clone, Debug)]
pub struct AnalyzedConcatenationScopeInfo {
pub module_ctxt: u32,
pub global_ctxt: u32,
pub idents: Vec<ConcatenationScopeIdent>,
pub canonical_names: Vec<ConcatenationScopeCanonicalName>,
}
#[cacheable]
#[derive(Clone, Debug)]
pub enum PendingConcatenationScopeInfo {
Analyzed(AnalyzedConcatenationScopeInfo),
Generated,
}
#[derive(Default)]
pub struct IdentCollector {
pub ids: Vec<ConcatenatedModuleIdent>,
}
impl IdentCollector {}
impl Visit for IdentCollector {
noop_visit_type!();
fn visit_ident(&mut self, node: &Ident) {
self.ids.push(ConcatenatedModuleIdent {
id: node.clone(),
shorthand: false,
is_class_expr_with_ident: false,
});
}
fn visit_object_pat_prop(&mut self, n: &ObjectPatProp) {
match n {
ObjectPatProp::Assign(assign) => {
self.ids.push(ConcatenatedModuleIdent {
id: assign.key.clone().into(),
shorthand: true,
is_class_expr_with_ident: false,
});
assign.value.visit_with(self);
}
ObjectPatProp::KeyValue(_) | ObjectPatProp::Rest(_) => {
n.visit_children_with(self);
}
}
}
fn visit_prop(&mut self, node: &Prop) {
match node {
Prop::Shorthand(node) => {
self.ids.push(ConcatenatedModuleIdent {
id: node.clone(),
shorthand: true,
is_class_expr_with_ident: false,
});
}
_ => {
node.visit_children_with(self);
}
}
}
fn visit_class_expr(&mut self, node: &ClassExpr) {
if let Some(ref ident) = node.ident
&& node.class.super_class.is_some()
{
self.ids.push(ConcatenatedModuleIdent {
id: ident.clone(),
shorthand: false,
is_class_expr_with_ident: true,
});
}
node.class.visit_with(self);
}
}