swc_estree_ast/
lit.rs

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                            // TODO(kdy1): This is bad.
78                            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/// Used for serialization/deserialization
137#[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    /// `Literal`.
160    #[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/// Deprecated. Use NumericLiteral instead.
197#[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/// Deprecated. Use RegExpLiteral instead.
231#[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}