1use std::borrow::Cow;
2
3use serde::{ser::SerializeMap, Deserialize, Serialize};
4use swc_atoms::Atom;
5use swc_common::ast_serde;
6
7use crate::{common::BaseNode, expr::Expression, flavor::Flavor, typescript::TSType};
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum Literal {
11 String(StringLiteral),
12 Numeric(NumericLiteral),
13 Null(NullLiteral),
14 Boolean(BooleanLiteral),
15 RegExp(RegExpLiteral),
16 Template(TemplateLiteral),
17 BigInt(BigIntLiteral),
18 Decimal(DecimalLiteral),
19}
20#[derive(Serialize)]
21struct AcornRegex<'a> {
22 flags: &'a str,
23 pattern: &'a str,
24}
25
26#[derive(Serialize)]
27struct Empty {}
28
29impl Serialize for Literal {
30 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31 where
32 S: serde::Serializer,
33 {
34 match Flavor::current() {
35 Flavor::Babel => {
36 let b = match self {
37 Literal::String(l) => BabelLiteral::String(l.clone()),
38 Literal::Numeric(l) => BabelLiteral::Numeric(l.clone()),
39 Literal::Null(l) => BabelLiteral::Null(l.clone()),
40 Literal::Boolean(l) => BabelLiteral::Boolean(l.clone()),
41 Literal::RegExp(l) => BabelLiteral::RegExp(l.clone()),
42 Literal::Template(l) => BabelLiteral::Template(l.clone()),
43 Literal::BigInt(l) => BabelLiteral::BigInt(l.clone()),
44 Literal::Decimal(l) => BabelLiteral::Decimal(l.clone()),
45 };
46 BabelLiteral::serialize(&b, serializer)
47 }
48 Flavor::Acorn { .. } => {
49 let (base, value, raw) = match self {
50 Literal::String(l) => (
51 &l.base,
52 AcornLiteralValue::String(l.value.clone()),
53 Cow::Owned(l.raw.to_string()),
54 ),
55 Literal::Numeric(l) => (
56 &l.base,
57 AcornLiteralValue::Numeric(l.value),
58 Cow::Owned(l.value.to_string()),
59 ),
60 Literal::Null(l) => (
61 &l.base,
62 AcornLiteralValue::Null(None),
63 Cow::Borrowed("null"),
64 ),
65 Literal::Boolean(l) => (
66 &l.base,
67 AcornLiteralValue::Boolean(l.value),
68 if l.value {
69 Cow::Borrowed("true")
70 } else {
71 Cow::Borrowed("false")
72 },
73 ),
74 Literal::RegExp(l) => {
75 let mut s = serializer.serialize_map(None)?;
76 {
77 l.base
79 .serialize(crate::flat_map_serializer::FlatMapSerializer(&mut s))?;
80 }
81 s.serialize_entry("type", "Literal")?;
82
83 s.serialize_entry(
84 "regex",
85 &AcornRegex {
86 flags: &l.flags,
87 pattern: &l.pattern,
88 },
89 )?;
90 s.serialize_entry("value", &Empty {})?;
91 return s.end();
92 }
93 Literal::Template(..) => todo!(),
94 Literal::BigInt(l) => (
95 &l.base,
96 AcornLiteralValue::BigInt(l.value.clone()),
97 Cow::Owned(l.value.to_string()),
98 ),
99 Literal::Decimal(l) => (
100 &l.base,
101 AcornLiteralValue::Decimal(l.value.clone()),
102 Cow::Owned(l.value.to_string()),
103 ),
104 };
105 let acorn = AcornLiteral {
106 type_: "Literal",
107 raw: &raw,
108 base,
109 value,
110 };
111
112 AcornLiteral::serialize(&acorn, serializer)
113 }
114 }
115 }
116}
117
118impl<'de> Deserialize<'de> for Literal {
119 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120 where
121 D: serde::Deserializer<'de>,
122 {
123 BabelLiteral::deserialize(deserializer).map(|b| match b {
124 BabelLiteral::String(l) => Literal::String(l),
125 BabelLiteral::Numeric(l) => Literal::Numeric(l),
126 BabelLiteral::Null(l) => Literal::Null(l),
127 BabelLiteral::Boolean(l) => Literal::Boolean(l),
128 BabelLiteral::RegExp(l) => Literal::RegExp(l),
129 BabelLiteral::Template(l) => Literal::Template(l),
130 BabelLiteral::BigInt(l) => Literal::BigInt(l),
131 BabelLiteral::Decimal(l) => Literal::Decimal(l),
132 })
133 }
134}
135
136#[ast_serde]
138enum BabelLiteral {
139 #[tag("StringLiteral")]
140 String(StringLiteral),
141 #[tag("NumericLiteral")]
142 Numeric(NumericLiteral),
143 #[tag("NullLiteral")]
144 Null(NullLiteral),
145 #[tag("BooleanLiteral")]
146 Boolean(BooleanLiteral),
147 #[tag("RegExpLiteral")]
148 RegExp(RegExpLiteral),
149 #[tag("TemplateLiteral")]
150 Template(TemplateLiteral),
151 #[tag("BigIntLiteral")]
152 BigInt(BigIntLiteral),
153 #[tag("DecimalLiteral")]
154 Decimal(DecimalLiteral),
155}
156
157#[derive(Serialize)]
158struct AcornLiteral<'a> {
159 #[serde(rename = "type")]
161 type_: &'a str,
162 raw: &'a str,
163 #[serde(flatten)]
164 base: &'a BaseNode,
165 value: AcornLiteralValue,
166}
167
168#[derive(Serialize)]
169#[serde(untagged)]
170enum AcornLiteralValue {
171 String(Atom),
172 Numeric(f64),
173 Null(Option<()>),
174 Boolean(bool),
175 BigInt(String),
176 Decimal(Atom),
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
180#[serde(tag = "type")]
181pub struct StringLiteral {
182 #[serde(flatten)]
183 pub base: BaseNode,
184 pub value: Atom,
185 pub raw: Atom,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
189#[serde(tag = "type")]
190pub struct NumericLiteral {
191 #[serde(flatten)]
192 pub base: BaseNode,
193 pub value: f64,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
198#[serde(tag = "type")]
199pub struct NumberLiteral {
200 #[serde(flatten)]
201 pub base: BaseNode,
202 pub value: f64,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
206#[serde(tag = "type")]
207pub struct NullLiteral {
208 #[serde(flatten)]
209 pub base: BaseNode,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
213#[serde(tag = "type")]
214pub struct BooleanLiteral {
215 #[serde(flatten)]
216 pub base: BaseNode,
217 pub value: bool,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
221#[serde(tag = "type")]
222pub struct RegExpLiteral {
223 #[serde(flatten)]
224 pub base: BaseNode,
225 pub pattern: Atom,
226 #[serde(default)]
227 pub flags: Atom,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
232#[serde(tag = "type")]
233pub struct RegexLiteral {
234 #[serde(flatten)]
235 pub base: BaseNode,
236 pub pattern: Atom,
237 #[serde(default)]
238 pub flags: Atom,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
242pub struct TemplateElVal {
243 #[serde(default)]
244 pub raw: Atom,
245 #[serde(default)]
246 pub cooked: Option<Atom>,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
250#[serde(tag = "type")]
251pub struct TemplateElement {
252 #[serde(flatten)]
253 pub base: BaseNode,
254 pub value: TemplateElVal,
255 #[serde(default)]
256 pub tail: bool,
257}
258
259#[derive(Debug, Clone, PartialEq)]
260#[ast_serde]
261pub enum TemplateLiteralExpr {
262 #[tag("TSAnyKeyword")]
263 #[tag("TSBooleanKeyword")]
264 #[tag("TSBigIntKeyword")]
265 #[tag("TSIntrinsicKeyword")]
266 #[tag("TSNeverKeyword")]
267 #[tag("TSNullKeyword")]
268 #[tag("TSNumberKeyword")]
269 #[tag("TSObjectKeyword")]
270 #[tag("TSStringKeyword")]
271 #[tag("TSSymbolKeyword")]
272 #[tag("TSUndefinedKeyword")]
273 #[tag("TSUnknownKeyword")]
274 #[tag("TSVoidKeyword")]
275 #[tag("TSThisType")]
276 #[tag("TSFunctionType")]
277 #[tag("TSConstructorType")]
278 #[tag("TSTypeReference")]
279 #[tag("TSTypePredicate")]
280 #[tag("TSTypeQuery")]
281 #[tag("TSTypeLiteral")]
282 #[tag("TSArrayType")]
283 #[tag("TSTupleType")]
284 #[tag("TSOptionalType")]
285 #[tag("TSRestType")]
286 #[tag("TSUnionType")]
287 #[tag("TSIntersectionType")]
288 #[tag("TSConditionalType")]
289 #[tag("TSInferType")]
290 #[tag("TSParenthesizedType")]
291 #[tag("TSTypeOperator")]
292 #[tag("TSIndexedAccessType")]
293 #[tag("TSMappedType")]
294 #[tag("TSLiteralType")]
295 #[tag("TSExpressionWithTypeArguments")]
296 #[tag("TSImportType")]
297 TSType(TSType),
298 #[tag("*")]
299 Expr(Box<Expression>),
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
303#[serde(tag = "type")]
304pub struct TemplateLiteral {
305 #[serde(flatten)]
306 pub base: BaseNode,
307 #[serde(default)]
308 pub quasis: Vec<TemplateElement>,
309 #[serde(default)]
310 pub expressions: Vec<TemplateLiteralExpr>,
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
314#[serde(tag = "type")]
315pub struct BigIntLiteral {
316 #[serde(flatten)]
317 pub base: BaseNode,
318 #[serde(default)]
319 pub value: String,
320 #[serde(default)]
321 pub raw: Atom,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
325#[serde(tag = "type")]
326pub struct DecimalLiteral {
327 #[serde(flatten)]
328 pub base: BaseNode,
329 #[serde(default)]
330 pub value: Atom,
331}