Skip to content

Commit a6884e4

Browse files
committed
refactor(ast): simplify serializing literal types (#8937)
Minimize the amount of hand-written serialization code for literal types (`BooleanLiteral` etc), mostly by using `#[estree(add_fields(...))]`. Also correct the TS type def for `RegExpLiteral`.
1 parent c58f785 commit a6884e4

File tree

4 files changed

+127
-184
lines changed

4 files changed

+127
-184
lines changed

crates/oxc_ast/src/ast/literal.rs

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ use oxc_syntax::number::{BigintBase, NumberBase};
2020
#[ast(visit)]
2121
#[derive(Debug, Clone)]
2222
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
23-
#[estree(rename = "Literal", via = crate::serialize::ESTreeLiteral, add_ts = "raw: string | null")]
23+
#[estree(
24+
rename = "Literal",
25+
add_fields(raw = crate::serialize::boolean_literal_raw(self)),
26+
add_ts = "raw: string | null",
27+
)]
2428
pub struct BooleanLiteral {
2529
/// Node location in source code
2630
pub span: Span,
@@ -34,7 +38,14 @@ pub struct BooleanLiteral {
3438
#[ast(visit)]
3539
#[derive(Debug, Clone)]
3640
#[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
37-
#[estree(rename = "Literal", via = crate::serialize::ESTreeLiteral, add_ts = "value: null, raw: \"null\" | null")]
41+
#[estree(
42+
rename = "Literal",
43+
add_fields(
44+
value = (),
45+
raw = crate::serialize::null_literal_raw(self),
46+
),
47+
add_ts = "value: null, raw: \"null\" | null",
48+
)]
3849
pub struct NullLiteral {
3950
/// Node location in source code
4051
pub span: Span,
@@ -46,7 +57,7 @@ pub struct NullLiteral {
4657
#[ast(visit)]
4758
#[derive(Debug, Clone)]
4859
#[generate_derive(CloneIn, ContentEq, GetSpan, GetSpanMut, ESTree)]
49-
#[estree(rename = "Literal", via = crate::serialize::ESTreeLiteral)]
60+
#[estree(rename = "Literal")]
5061
pub struct NumericLiteral<'a> {
5162
/// Node location in source code
5263
pub span: Span,
@@ -69,7 +80,7 @@ pub struct NumericLiteral<'a> {
6980
#[ast(visit)]
7081
#[derive(Debug, Clone)]
7182
#[generate_derive(CloneIn, ContentEq, GetSpan, GetSpanMut, ESTree)]
72-
#[estree(rename = "Literal", via = crate::serialize::ESTreeLiteral)]
83+
#[estree(rename = "Literal")]
7384
pub struct StringLiteral<'a> {
7485
/// Node location in source code
7586
pub span: Span,
@@ -89,7 +100,14 @@ pub struct StringLiteral<'a> {
89100
#[ast(visit)]
90101
#[derive(Debug, Clone)]
91102
#[generate_derive(CloneIn, ContentEq, GetSpan, GetSpanMut, ESTree)]
92-
#[estree(rename = "Literal", via = crate::serialize::ESTreeLiteral, add_ts = "value: null, bigint: string")]
103+
#[estree(
104+
rename = "Literal",
105+
add_fields(
106+
value = (),
107+
bigint = crate::serialize::bigint_literal_bigint(self),
108+
),
109+
add_ts = "value: null, bigint: string",
110+
)]
93111
pub struct BigIntLiteral<'a> {
94112
/// Node location in source code
95113
pub span: Span,
@@ -109,16 +127,15 @@ pub struct BigIntLiteral<'a> {
109127
#[derive(Debug)]
110128
#[generate_derive(CloneIn, ContentEq, GetSpan, GetSpanMut, ESTree)]
111129
#[estree(
112-
rename = "Literal",
113-
via = crate::serialize::ESTreeLiteral,
114-
add_ts = "value: {} | null, regex: { pattern: string, flags: string }"
130+
rename = "Literal",
131+
add_fields(value = crate::serialize::EmptyObject),
132+
add_ts = "value: {} | null",
115133
)]
116134
pub struct RegExpLiteral<'a> {
117135
/// Node location in source code
118136
pub span: Span,
119137
/// The parsed regular expression. See [`oxc_regular_expression`] for more
120138
/// details.
121-
#[estree(skip)]
122139
pub regex: RegExp<'a>,
123140
/// The regular expression as it appears in source code
124141
///
@@ -136,8 +153,10 @@ pub struct RegExpLiteral<'a> {
136153
#[estree(no_type)]
137154
pub struct RegExp<'a> {
138155
/// The regex pattern between the slashes
156+
#[estree(ts_type = "string")]
139157
pub pattern: RegExpPattern<'a>,
140158
/// Regex flags after the closing slash
159+
#[estree(ts_type = "string")]
141160
pub flags: RegExpFlags,
142161
}
143162

@@ -147,6 +166,7 @@ pub struct RegExp<'a> {
147166
#[ast]
148167
#[derive(Debug)]
149168
#[generate_derive(CloneIn, ESTree)]
169+
#[estree(custom_serialize, no_ts_def)]
150170
pub enum RegExpPattern<'a> {
151171
/// Unparsed pattern. Contains string slice of the pattern.
152172
/// Pattern was not parsed, so may be valid or invalid.
@@ -204,28 +224,6 @@ bitflags! {
204224
/// Dummy type to communicate the content of `RegExpFlags` to `oxc_ast_tools`.
205225
#[ast(foreign = RegExpFlags)]
206226
#[generate_derive(ESTree)]
207-
#[estree(
208-
custom_serialize,
209-
custom_ts_def = "
210-
type RegExpFlags = {
211-
/** Global flag */
212-
G: 1;
213-
/** Ignore case flag */
214-
I: 2;
215-
/** Multiline flag */
216-
M: 4;
217-
/** DotAll flag */
218-
S: 8;
219-
/** Unicode flag */
220-
U: 16;
221-
/** Sticky flag */
222-
Y: 32;
223-
/** Indices flag */
224-
D: 64;
225-
/** Unicode sets flag */
226-
V: 128;
227-
}
228-
"
229-
)]
227+
#[estree(custom_serialize, no_ts_def)]
230228
#[expect(dead_code)]
231229
struct RegExpFlagsAlias(u8);

crates/oxc_ast/src/generated/derive_estree.rs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,37 +1886,75 @@ impl Serialize for ModuleExportName<'_> {
18861886

18871887
impl Serialize for BooleanLiteral {
18881888
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1889-
crate::serialize::ESTreeLiteral::from(self).serialize(serializer)
1889+
let mut map = serializer.serialize_map(None)?;
1890+
map.serialize_entry("type", "Literal")?;
1891+
map.serialize_entry("start", &self.span.start)?;
1892+
map.serialize_entry("end", &self.span.end)?;
1893+
map.serialize_entry("value", &self.value)?;
1894+
map.serialize_entry("raw", &crate::serialize::boolean_literal_raw(self))?;
1895+
map.end()
18901896
}
18911897
}
18921898

18931899
impl Serialize for NullLiteral {
18941900
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1895-
crate::serialize::ESTreeLiteral::from(self).serialize(serializer)
1901+
let mut map = serializer.serialize_map(None)?;
1902+
map.serialize_entry("type", "Literal")?;
1903+
map.serialize_entry("start", &self.span.start)?;
1904+
map.serialize_entry("end", &self.span.end)?;
1905+
map.serialize_entry("value", &())?;
1906+
map.serialize_entry("raw", &crate::serialize::null_literal_raw(self))?;
1907+
map.end()
18961908
}
18971909
}
18981910

18991911
impl Serialize for NumericLiteral<'_> {
19001912
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1901-
crate::serialize::ESTreeLiteral::from(self).serialize(serializer)
1913+
let mut map = serializer.serialize_map(None)?;
1914+
map.serialize_entry("type", "Literal")?;
1915+
map.serialize_entry("start", &self.span.start)?;
1916+
map.serialize_entry("end", &self.span.end)?;
1917+
map.serialize_entry("value", &self.value)?;
1918+
map.serialize_entry("raw", &self.raw)?;
1919+
map.end()
19021920
}
19031921
}
19041922

19051923
impl Serialize for StringLiteral<'_> {
19061924
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1907-
crate::serialize::ESTreeLiteral::from(self).serialize(serializer)
1925+
let mut map = serializer.serialize_map(None)?;
1926+
map.serialize_entry("type", "Literal")?;
1927+
map.serialize_entry("start", &self.span.start)?;
1928+
map.serialize_entry("end", &self.span.end)?;
1929+
map.serialize_entry("value", &self.value)?;
1930+
map.serialize_entry("raw", &self.raw)?;
1931+
map.end()
19081932
}
19091933
}
19101934

19111935
impl Serialize for BigIntLiteral<'_> {
19121936
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1913-
crate::serialize::ESTreeLiteral::from(self).serialize(serializer)
1937+
let mut map = serializer.serialize_map(None)?;
1938+
map.serialize_entry("type", "Literal")?;
1939+
map.serialize_entry("start", &self.span.start)?;
1940+
map.serialize_entry("end", &self.span.end)?;
1941+
map.serialize_entry("raw", &self.raw)?;
1942+
map.serialize_entry("value", &())?;
1943+
map.serialize_entry("bigint", &crate::serialize::bigint_literal_bigint(self))?;
1944+
map.end()
19141945
}
19151946
}
19161947

19171948
impl Serialize for RegExpLiteral<'_> {
19181949
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1919-
crate::serialize::ESTreeLiteral::from(self).serialize(serializer)
1950+
let mut map = serializer.serialize_map(None)?;
1951+
map.serialize_entry("type", "Literal")?;
1952+
map.serialize_entry("start", &self.span.start)?;
1953+
map.serialize_entry("end", &self.span.end)?;
1954+
map.serialize_entry("regex", &self.regex)?;
1955+
map.serialize_entry("raw", &self.raw)?;
1956+
map.serialize_entry("value", &crate::serialize::EmptyObject)?;
1957+
map.end()
19201958
}
19211959
}
19221960

@@ -1929,16 +1967,6 @@ impl Serialize for RegExp<'_> {
19291967
}
19301968
}
19311969

1932-
impl Serialize for RegExpPattern<'_> {
1933-
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1934-
match self {
1935-
RegExpPattern::Raw(it) => it.serialize(serializer),
1936-
RegExpPattern::Invalid(it) => it.serialize(serializer),
1937-
RegExpPattern::Pattern(it) => it.serialize(serializer),
1938-
}
1939-
}
1940-
}
1941-
19421970
impl Serialize for JSXElement<'_> {
19431971
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
19441972
let mut map = serializer.serialize_map(None)?;

0 commit comments

Comments
 (0)