Skip to content

Commit 9a2548a

Browse files
bacarybrunoautofix-ci[bot]overlookmotel
authored
feat(napi/parser)!: add range option (#11728)
Part of #10307. Add `range` option to `oxc-parser`, to add `range` property to nodes in ESTree AST. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
1 parent 692fb6c commit 9a2548a

File tree

23 files changed

+921
-68
lines changed

23 files changed

+921
-68
lines changed

crates/oxc_allocator/src/boxed.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ mod test {
243243
let allocator = Allocator::default();
244244
let b = Box::new_in("x", &allocator);
245245

246-
let mut serializer = CompactTSSerializer::new();
246+
let mut serializer = CompactTSSerializer::new(false);
247247
b.serialize(&mut serializer);
248248
let s = serializer.into_string();
249249
assert_eq!(s, r#""x""#);

crates/oxc_allocator/src/vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ mod test {
311311
let mut v = Vec::new_in(&allocator);
312312
v.push("x");
313313

314-
let mut serializer = CompactTSSerializer::new();
314+
let mut serializer = CompactTSSerializer::new(false);
315315
v.serialize(&mut serializer);
316316
let s = serializer.into_string();
317317
assert_eq!(s, r#"["x"]"#);

crates/oxc_ast/src/generated/derive_estree.rs

Lines changed: 716 additions & 0 deletions
Large diffs are not rendered by default.

crates/oxc_ast/src/serialize/mod.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,62 +47,62 @@ const JSON_CAPACITY_RATIO_PRETTY: usize = 80;
4747

4848
impl Program<'_> {
4949
/// Serialize AST to ESTree JSON, including TypeScript fields.
50-
pub fn to_estree_ts_json(&self) -> String {
50+
pub fn to_estree_ts_json(&self, ranges: bool) -> String {
5151
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_COMPACT;
52-
let mut serializer = CompactTSSerializer::with_capacity(capacity);
52+
let mut serializer = CompactTSSerializer::with_capacity(capacity, ranges);
5353
self.serialize(&mut serializer);
5454
serializer.into_string()
5555
}
5656

5757
/// Serialize AST to ESTree JSON, without TypeScript fields.
58-
pub fn to_estree_js_json(&self) -> String {
58+
pub fn to_estree_js_json(&self, ranges: bool) -> String {
5959
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_COMPACT;
60-
let mut serializer = CompactJSSerializer::with_capacity(capacity);
60+
let mut serializer = CompactJSSerializer::with_capacity(capacity, ranges);
6161
self.serialize(&mut serializer);
6262
serializer.into_string()
6363
}
6464

6565
/// Serialize AST to pretty-printed ESTree JSON, including TypeScript fields.
66-
pub fn to_pretty_estree_ts_json(&self) -> String {
66+
pub fn to_pretty_estree_ts_json(&self, ranges: bool) -> String {
6767
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_PRETTY;
68-
let mut serializer = PrettyTSSerializer::with_capacity(capacity);
68+
let mut serializer = PrettyTSSerializer::with_capacity(capacity, ranges);
6969
self.serialize(&mut serializer);
7070
serializer.into_string()
7171
}
7272

7373
/// Serialize AST to pretty-printed ESTree JSON, without TypeScript fields.
74-
pub fn to_pretty_estree_js_json(&self) -> String {
74+
pub fn to_pretty_estree_js_json(&self, ranges: bool) -> String {
7575
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_PRETTY;
76-
let mut serializer = PrettyJSSerializer::with_capacity(capacity);
76+
let mut serializer = PrettyJSSerializer::with_capacity(capacity, ranges);
7777
self.serialize(&mut serializer);
7878
serializer.into_string()
7979
}
8080

8181
/// Serialize AST to ESTree JSON, including TypeScript fields, with list of fixes.
82-
pub fn to_estree_ts_json_with_fixes(&self) -> String {
82+
pub fn to_estree_ts_json_with_fixes(&self, ranges: bool) -> String {
8383
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_COMPACT;
84-
let serializer = CompactFixesTSSerializer::with_capacity(capacity);
84+
let serializer = CompactFixesTSSerializer::with_capacity(capacity, ranges);
8585
serializer.serialize_with_fixes(self)
8686
}
8787

8888
/// Serialize AST to ESTree JSON, without TypeScript fields, with list of fixes.
89-
pub fn to_estree_js_json_with_fixes(&self) -> String {
89+
pub fn to_estree_js_json_with_fixes(&self, ranges: bool) -> String {
9090
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_COMPACT;
91-
let serializer = CompactFixesJSSerializer::with_capacity(capacity);
91+
let serializer = CompactFixesJSSerializer::with_capacity(capacity, ranges);
9292
serializer.serialize_with_fixes(self)
9393
}
9494

9595
/// Serialize AST to pretty-printed ESTree JSON, including TypeScript fields, with list of fixes.
96-
pub fn to_pretty_estree_ts_json_with_fixes(&self) -> String {
96+
pub fn to_pretty_estree_ts_json_with_fixes(&self, ranges: bool) -> String {
9797
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_PRETTY;
98-
let serializer = PrettyFixesTSSerializer::with_capacity(capacity);
98+
let serializer = PrettyFixesTSSerializer::with_capacity(capacity, ranges);
9999
serializer.serialize_with_fixes(self)
100100
}
101101

102102
/// Serialize AST to pretty-printed ESTree JSON, without TypeScript fields, with list of fixes.
103-
pub fn to_pretty_estree_js_json_with_fixes(&self) -> String {
103+
pub fn to_pretty_estree_js_json_with_fixes(&self, ranges: bool) -> String {
104104
let capacity = self.source_text.len() * JSON_CAPACITY_RATIO_PRETTY;
105-
let serializer = PrettyFixesJSSerializer::with_capacity(capacity);
105+
let serializer = PrettyFixesJSSerializer::with_capacity(capacity, ranges);
106106
serializer.serialize_with_fixes(self)
107107
}
108108
}
@@ -168,13 +168,17 @@ impl ESTree for ProgramConverter<'_, '_> {
168168
let span_start =
169169
if S::INCLUDE_TS_FIELDS { get_ts_start_span(program) } else { program.span.start };
170170

171+
let ranges = serializer.ranges();
171172
let mut state = serializer.serialize_struct();
172173
state.serialize_field("type", &JsonSafeString("Program"));
173174
state.serialize_field("start", &span_start);
174175
state.serialize_field("end", &program.span.end);
175176
state.serialize_field("body", &Concat2(&program.directives, &program.body));
176177
state.serialize_field("sourceType", &program.source_type.module_kind());
177178
state.serialize_field("hashbang", &program.hashbang);
179+
if ranges {
180+
state.serialize_field("range", &[span_start, program.span.end]);
181+
}
178182
state.end();
179183
}
180184
}

crates/oxc_estree/src/serialize/blanket.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ mod tests {
5757
let cases = [(&"foo", r#""foo""#), (&&"bar", r#""bar""#)];
5858

5959
for (input, output) in cases {
60-
let mut serializer = CompactTSSerializer::new();
60+
let mut serializer = CompactTSSerializer::new(false);
6161
input.serialize(&mut serializer);
6262
let s = serializer.into_string();
6363
assert_eq!(&s, output);
@@ -69,7 +69,7 @@ mod tests {
6969
let cases = [(&mut "foo", r#""foo""#), (&mut &mut "bar", r#""bar""#)];
7070

7171
for (input, output) in cases {
72-
let mut serializer = CompactTSSerializer::new();
72+
let mut serializer = CompactTSSerializer::new(false);
7373
input.serialize(&mut serializer);
7474
let s = serializer.into_string();
7575
assert_eq!(&s, output);
@@ -81,7 +81,7 @@ mod tests {
8181
let cases = [(None, "null"), (Some(123.0f64), "123")];
8282

8383
for (input, output) in cases {
84-
let mut serializer = CompactTSSerializer::new();
84+
let mut serializer = CompactTSSerializer::new(false);
8585
input.serialize(&mut serializer);
8686
let s = serializer.into_string();
8787
assert_eq!(&s, output);
@@ -94,7 +94,7 @@ mod tests {
9494
[(Cow::Borrowed("foo"), r#""foo""#), (Cow::Owned("bar".to_string()), r#""bar""#)];
9595

9696
for (input, output) in cases {
97-
let mut serializer = CompactTSSerializer::new();
97+
let mut serializer = CompactTSSerializer::new(false);
9898
input.serialize(&mut serializer);
9999
let s = serializer.into_string();
100100
assert_eq!(&s, output);

crates/oxc_estree/src/serialize/config.rs

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,88 @@ pub trait Config {
55
/// `true` if should record paths to `Literal` nodes that need fixing on JS side
66
const FIXES: bool;
77

8-
fn new() -> Self;
8+
fn new(ranges: bool) -> Self;
9+
10+
/// Whether to include range information in the serialized output
11+
fn ranges(&self) -> bool;
912
}
1013

11-
/// Config for serializing AST with TypeScript fields,
12-
pub struct ConfigTS;
14+
/// Config for serializing AST with TypeScript fields.
15+
pub struct ConfigTS {
16+
ranges: bool,
17+
}
1318

1419
impl Config for ConfigTS {
1520
const INCLUDE_TS_FIELDS: bool = true;
1621
const FIXES: bool = false;
1722

1823
#[inline(always)]
19-
fn new() -> Self {
20-
Self
24+
fn new(ranges: bool) -> Self {
25+
Self { ranges }
26+
}
27+
28+
#[inline(always)]
29+
fn ranges(&self) -> bool {
30+
self.ranges
2131
}
2232
}
2333

2434
/// Config for serializing AST without TypeScript fields.
25-
pub struct ConfigJS;
35+
pub struct ConfigJS {
36+
ranges: bool,
37+
}
2638

2739
impl Config for ConfigJS {
2840
const INCLUDE_TS_FIELDS: bool = false;
2941
const FIXES: bool = false;
3042

3143
#[inline(always)]
32-
fn new() -> Self {
33-
Self
44+
fn new(ranges: bool) -> Self {
45+
Self { ranges }
46+
}
47+
48+
#[inline(always)]
49+
fn ranges(&self) -> bool {
50+
self.ranges
3451
}
3552
}
3653

3754
/// Config for serializing AST with TypeScript fields, with fixes.
38-
pub struct ConfigFixesTS;
55+
pub struct ConfigFixesTS {
56+
ranges: bool,
57+
}
3958

4059
impl Config for ConfigFixesTS {
4160
const INCLUDE_TS_FIELDS: bool = true;
4261
const FIXES: bool = true;
4362

4463
#[inline(always)]
45-
fn new() -> Self {
46-
Self
64+
fn new(ranges: bool) -> Self {
65+
Self { ranges }
66+
}
67+
68+
#[inline(always)]
69+
fn ranges(&self) -> bool {
70+
self.ranges
4771
}
4872
}
4973

5074
/// Config for serializing AST without TypeScript fields, with fixes.
51-
pub struct ConfigFixesJS;
75+
pub struct ConfigFixesJS {
76+
ranges: bool,
77+
}
5278

5379
impl Config for ConfigFixesJS {
5480
const INCLUDE_TS_FIELDS: bool = false;
5581
const FIXES: bool = true;
5682

5783
#[inline(always)]
58-
fn new() -> Self {
59-
Self
84+
fn new(ranges: bool) -> Self {
85+
Self { ranges }
86+
}
87+
88+
#[inline(always)]
89+
fn ranges(&self) -> bool {
90+
self.ranges
6091
}
6192
}

crates/oxc_estree/src/serialize/mod.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub trait Serializer: SerializerPrivate {
4444
/// Type of sequence serializer this serializer uses.
4545
type SequenceSerializer: SequenceSerializer;
4646

47+
fn ranges(&self) -> bool;
48+
4749
/// Serialize struct.
4850
fn serialize_struct(self) -> Self::StructSerializer;
4951

@@ -100,30 +102,29 @@ pub struct ESTreeSerializer<C: Config, F: Formatter> {
100102
formatter: F,
101103
trace_path: NonEmptyStack<TracePathPart>,
102104
fixes_buffer: CodeBuffer,
103-
#[expect(unused)]
104105
config: C,
105106
}
106107

107108
impl<C: Config, F: Formatter> ESTreeSerializer<C, F> {
108109
/// Create new [`ESTreeSerializer`].
109-
pub fn new() -> Self {
110+
pub fn new(ranges: bool) -> Self {
110111
Self {
111112
buffer: CodeBuffer::new(),
112113
formatter: F::new(),
113114
trace_path: NonEmptyStack::new(TracePathPart::Index(0)),
114115
fixes_buffer: CodeBuffer::new(),
115-
config: C::new(),
116+
config: C::new(ranges),
116117
}
117118
}
118119

119120
/// Create new [`ESTreeSerializer`] with specified buffer capacity.
120-
pub fn with_capacity(capacity: usize) -> Self {
121+
pub fn with_capacity(capacity: usize, ranges: bool) -> Self {
121122
Self {
122123
buffer: CodeBuffer::with_capacity(capacity),
123124
formatter: F::new(),
124125
trace_path: NonEmptyStack::new(TracePathPart::Index(0)),
125126
fixes_buffer: CodeBuffer::new(),
126-
config: C::new(),
127+
config: C::new(ranges),
127128
}
128129
}
129130

@@ -168,7 +169,7 @@ impl<C: Config, F: Formatter> ESTreeSerializer<C, F> {
168169
impl<C: Config, F: Formatter> Default for ESTreeSerializer<C, F> {
169170
#[inline(always)]
170171
fn default() -> Self {
171-
Self::new()
172+
Self::new(false)
172173
}
173174
}
174175

@@ -179,6 +180,10 @@ impl<'s, C: Config, F: Formatter> Serializer for &'s mut ESTreeSerializer<C, F>
179180
type StructSerializer = ESTreeStructSerializer<'s, C, F>;
180181
type SequenceSerializer = ESTreeSequenceSerializer<'s, C, F>;
181182

183+
fn ranges(&self) -> bool {
184+
self.config.ranges()
185+
}
186+
182187
/// Serialize struct.
183188
#[inline(always)]
184189
fn serialize_struct(self) -> ESTreeStructSerializer<'s, C, F> {

crates/oxc_estree/src/serialize/primitives.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ mod tests {
7878

7979
fn run_test<T: ESTree>(cases: &[(T, &str)]) {
8080
for (input, output) in cases {
81-
let mut serializer = CompactTSSerializer::new();
81+
let mut serializer = CompactTSSerializer::new(false);
8282
input.serialize(&mut serializer);
8383
let s = serializer.into_string();
8484
assert_eq!(&s, output);

crates/oxc_estree/src/serialize/sequences.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@ mod tests {
121121

122122
let foo = Foo { none: &[], one: &["one"], two: ["two one", "two two"] };
123123

124-
let mut serializer = CompactTSSerializer::new();
124+
let mut serializer = CompactTSSerializer::new(false);
125125
foo.serialize(&mut serializer);
126126
let s = serializer.into_string();
127127
assert_eq!(&s, r#"{"none":[],"one":["one"],"two":["two one","two two"]}"#);
128128

129-
let mut serializer = PrettyTSSerializer::new();
129+
let mut serializer = PrettyTSSerializer::new(false);
130130
foo.serialize(&mut serializer);
131131
let s = serializer.into_string();
132132
assert_eq!(

crates/oxc_estree/src/serialize/strings.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ mod tests {
483483
];
484484

485485
for (input, output) in cases {
486-
let mut serializer = CompactTSSerializer::new();
486+
let mut serializer = CompactTSSerializer::new(false);
487487
input.serialize(&mut serializer);
488488
let s = serializer.into_string();
489489
assert_eq!(&s, output);
@@ -495,7 +495,7 @@ mod tests {
495495
let cases = [(String::new(), r#""""#), ("foobar".to_string(), r#""foobar""#)];
496496

497497
for (input, output) in cases {
498-
let mut serializer = CompactTSSerializer::new();
498+
let mut serializer = CompactTSSerializer::new(false);
499499
input.to_string().serialize(&mut serializer);
500500
let s = serializer.into_string();
501501
assert_eq!(&s, output);
@@ -507,7 +507,7 @@ mod tests {
507507
let cases = [("", r#""""#), ("a", r#""a""#), ("abc", r#""abc""#)];
508508

509509
for (input, output) in cases {
510-
let mut serializer = CompactTSSerializer::new();
510+
let mut serializer = CompactTSSerializer::new(false);
511511
JsonSafeString(input).serialize(&mut serializer);
512512
let s = serializer.into_string();
513513
assert_eq!(&s, output);
@@ -530,7 +530,7 @@ mod tests {
530530
];
531531

532532
for (input, output) in cases {
533-
let mut serializer = CompactTSSerializer::new();
533+
let mut serializer = CompactTSSerializer::new(false);
534534
LoneSurrogatesString(input).serialize(&mut serializer);
535535
let s = serializer.into_string();
536536
assert_eq!(&s, output);

0 commit comments

Comments
 (0)