1use std::{
2 fmt,
3 sync::atomic::{AtomicU32, Ordering::SeqCst},
4};
5
6use rustc_hash::FxHashMap;
7use swc_atoms::Atom;
8use swc_common::{sync::Lock, FileName, Mark, SyntaxContext, DUMMY_SP};
9use swc_ecma_ast::{Expr, Ident};
10use swc_ecma_utils::ident::IdentLike;
11
12#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct ModuleId(u32);
14
15impl fmt::Display for ModuleId {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 fmt::Display::fmt(&self.0, f)
18 }
19}
20
21impl fmt::Debug for ModuleId {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 write!(f, "ModuleId({})", self.0)?;
24 Ok(())
25 }
26}
27
28#[derive(Debug, Default)]
29pub(crate) struct ModuleIdGenerator {
30 v: AtomicU32,
31 cache: Lock<FxHashMap<FileName, (ModuleId, Mark, Mark)>>,
33}
34
35impl ModuleIdGenerator {
36 pub fn gen(&self, file_name: &FileName) -> (ModuleId, Mark, Mark) {
37 let mut w = self.cache.lock();
38 if let Some(v) = w.get(file_name) {
39 return *v;
40 }
41
42 let id = ModuleId(self.v.fetch_add(1, SeqCst));
43 let local_mark = Mark::fresh(Mark::root());
44 let export_mark = Mark::fresh(Mark::root());
45 let v = (id, local_mark, export_mark);
46 w.insert(file_name.clone(), v);
47 (id, local_mark, export_mark)
48 }
49}
50
51#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
52pub struct Id(Atom, SyntaxContext);
53
54impl fmt::Debug for Id {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 write!(f, "{}{:?}", self.0, self.1)
57 }
58}
59
60impl Id {
61 pub fn new(sym: Atom, ctxt: SyntaxContext) -> Self {
62 Id(sym, ctxt)
63 }
64
65 pub fn sym(&self) -> &Atom {
66 &self.0
67 }
68
69 pub fn ctxt(&self) -> SyntaxContext {
70 self.1
71 }
72
73 pub fn into_ident(self) -> Ident {
74 Ident::new(self.0, DUMMY_SP, self.1)
75 }
76
77 pub fn with_ctxt(mut self, ctxt: SyntaxContext) -> Self {
78 self.1 = ctxt;
79 self
80 }
81}
82
83impl IdentLike for Id {
84 fn from_ident(i: &Ident) -> Self {
85 i.into()
86 }
87
88 fn to_id(&self) -> (Atom, SyntaxContext) {
89 (self.0.clone(), self.1)
90 }
91
92 fn into_id(self) -> (Atom, SyntaxContext) {
93 (self.0, self.1)
94 }
95}
96
97impl From<Ident> for Id {
98 fn from(i: Ident) -> Self {
99 Id(i.sym, i.ctxt)
100 }
101}
102
103impl From<&Ident> for Id {
104 fn from(i: &Ident) -> Self {
105 Id(i.sym.clone(), i.ctxt)
106 }
107}
108
109impl PartialEq<Ident> for Id {
110 fn eq(&self, other: &Ident) -> bool {
111 self.0 == other.sym && self.1 == other.ctxt
112 }
113}
114
115impl PartialEq<Atom> for Id {
116 fn eq(&self, other: &Atom) -> bool {
117 self.0 == *other
118 }
119}
120
121impl From<Id> for Ident {
122 #[inline]
123 fn from(id: Id) -> Self {
124 id.into_ident()
125 }
126}
127
128impl From<Id> for Expr {
129 #[inline]
130 fn from(id: Id) -> Self {
131 id.into_ident().into()
132 }
133}