next_custom_transforms/transforms/
import_analyzer.rs1use rustc_hash::{FxHashMap, FxHashSet};
2use swc_core::{
3 atoms::Atom,
4 ecma::{
5 ast::{
6 Expr, Id, ImportDecl, ImportNamedSpecifier, ImportSpecifier, MemberExpr, MemberProp,
7 Module, ModuleExportName,
8 },
9 visit::{noop_visit_type, Visit, VisitWith},
10 },
11};
12
13#[derive(Debug, Default)]
14pub(crate) struct ImportMap {
15 imports: FxHashMap<Id, (Atom, Atom)>,
17
18 namespace_imports: FxHashMap<Id, Atom>,
19
20 imported_modules: FxHashSet<Atom>,
21}
22
23#[allow(unused)]
24impl ImportMap {
25 pub fn is_module_imported(&mut self, module: &Atom) -> bool {
26 self.imported_modules.contains(module)
27 }
28
29 pub fn is_import(&self, e: &Expr, module: &str, orig_name: &str) -> bool {
31 match e {
32 Expr::Ident(i) => {
33 if let Some((i_src, i_sym)) = self.imports.get(&i.to_id()) {
34 i_src == module && i_sym == orig_name
35 } else {
36 false
37 }
38 }
39
40 Expr::Member(MemberExpr {
41 obj: box Expr::Ident(obj),
42 prop: MemberProp::Ident(prop),
43 ..
44 }) => {
45 if let Some(obj_src) = self.namespace_imports.get(&obj.to_id()) {
46 obj_src == module && prop.sym == *orig_name
47 } else {
48 false
49 }
50 }
51
52 _ => false,
53 }
54 }
55
56 pub fn analyze(m: &Module) -> Self {
57 let mut data = ImportMap::default();
58
59 m.visit_with(&mut Analyzer { data: &mut data });
60
61 data
62 }
63}
64
65struct Analyzer<'a> {
66 data: &'a mut ImportMap,
67}
68
69impl Visit for Analyzer<'_> {
70 noop_visit_type!();
71
72 fn visit_import_decl(&mut self, import: &ImportDecl) {
73 self.data.imported_modules.insert(import.src.value.clone());
74
75 for s in &import.specifiers {
76 let (local, orig_sym) = match s {
77 ImportSpecifier::Named(ImportNamedSpecifier {
78 local, imported, ..
79 }) => match imported {
80 Some(imported) => (local.to_id(), orig_name(imported)),
81 _ => (local.to_id(), local.sym.clone()),
82 },
83 ImportSpecifier::Default(s) => (s.local.to_id(), "default".into()),
84 ImportSpecifier::Namespace(s) => {
85 self.data
86 .namespace_imports
87 .insert(s.local.to_id(), import.src.value.clone());
88 continue;
89 }
90 };
91
92 self.data
93 .imports
94 .insert(local, (import.src.value.clone(), orig_sym));
95 }
96 }
97}
98
99fn orig_name(n: &ModuleExportName) -> Atom {
100 match n {
101 ModuleExportName::Ident(v) => v.sym.clone(),
102 ModuleExportName::Str(v) => v.value.clone(),
103 }
104}