Skip to content

Commit c919ce9

Browse files
committed
refactor(estree/tokens): make Context methods take AST nodes
1 parent ce89e1d commit c919ce9

File tree

4 files changed

+75
-51
lines changed

4 files changed

+75
-51
lines changed

crates/oxc_estree_tokens/src/context.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! [`Context`] trait.
22
3-
use oxc_ast::ast::{RegExpLiteral, TemplateElement};
3+
use oxc_ast::ast::{JSXText, PrivateIdentifier, RegExpLiteral, StringLiteral, TemplateElement};
44

5-
use crate::{jsx_state::JSXState, token_type::TokenType, visitor::Visitor};
5+
use crate::{jsx_state::JSXState, visitor::Visitor};
66

77
/// Trait abstracting over the two token processing modes:
88
/// JSON serialization ([`JsonContext`]) and raw transfer ([`RawContext`]).
@@ -51,29 +51,31 @@ pub trait Context: Sized {
5151
/// * Raw transfer mode: Set kind to `Kind::JSXIdentifier`.
5252
fn emit_jsx_identifier_at(&mut self, start: u32, name: &str);
5353

54-
/// Emit the token at `start` as `PrivateIdentifier`.
54+
/// Emit a `PrivateIdentifier` token.
5555
///
5656
/// * JSON mode: Serialize with appropriate encoding.
5757
/// * Raw transfer mode: No-op (token already has `Kind::PrivateIdentifier`).
58-
fn emit_private_identifier_at(&mut self, start: u32, name: &str);
58+
fn emit_private_identifier(&mut self, ident: &PrivateIdentifier<'_>);
59+
60+
/// Emit a `StringLiteral` token.
61+
///
62+
/// * JSON mode: Serialize with JSON encoding (`value` may not be JSON-safe).
63+
/// * Raw transfer mode: No-op (token already has the correct kind).
64+
fn emit_string_literal(&mut self, literal: &StringLiteral<'_>);
5965

6066
/// Emit a `StringLiteral` in a JSX attribute as `JSXText`.
6167
///
62-
/// Unlike [`emit_unsafe_token_at`], this changes the token's kind in raw transfer mode,
63-
/// because the token has `Kind::Str` but needs to become `Kind::JSXText`.
64-
/// Use [`emit_unsafe_token_at`] for actual `JSXText` tokens which already have the correct kind.
68+
/// The token has `Kind::Str` but needs to become `JSXText`.
6569
///
6670
/// * JSON mode: Serialize as `JSXText` with JSON encoding.
6771
/// * Raw transfer mode: Set kind to `Kind::JSXText`.
68-
///
69-
/// [`emit_unsafe_token_at`]: Context::emit_unsafe_token_at
70-
fn emit_jsx_text_at(&mut self, start: u32);
72+
fn emit_string_literal_as_jsx_text(&mut self, literal: &StringLiteral<'_>);
7173

72-
/// Emit a token whose value may not be JSON-safe (strings, templates, JSXText).
74+
/// Emit a `JSXText` token whose value may not be JSON-safe.
7375
///
7476
/// * JSON mode: Serialize with JSON encoding.
75-
/// * Raw transfer mode: No-op (token already has the correct kind).
76-
fn emit_unsafe_token_at(&mut self, start: u32, token_type: TokenType);
77+
/// * Raw transfer mode: No-op (token already has `Kind::JSXText`).
78+
fn emit_jsx_text(&mut self, jsx_text: &JSXText<'_>);
7779

7880
/// Emit a `RegularExpression` token.
7981
///

crates/oxc_estree_tokens/src/json.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
33
use std::slice::Iter;
44

5-
use oxc_ast::ast::{Program, RegExpLiteral, TemplateElement};
5+
use oxc_ast::ast::{
6+
JSXText, PrivateIdentifier, Program, RegExpLiteral, StringLiteral, TemplateElement,
7+
};
68
use oxc_ast_visit::utf8_to_utf16::Utf8ToUtf16;
79
use oxc_ast_visit::{Visit, utf8_to_utf16::Utf8ToUtf16Converter};
810
use oxc_estree::{
@@ -241,11 +243,18 @@ impl<'b, O: ESTreeTokenConfig, S: SequenceSerializer> JsonContext<'b, O, S> {
241243
self.serialize_safe_token(token, token_type, value);
242244
}
243245

246+
/// Advance to the token at `start` and serialize it using provided `value` without JSON encoding.
244247
fn emit_safe_token_at(&mut self, start: u32, token_type: TokenType, value: &str) {
245248
let token = self.advance_to(start);
246249
self.serialize_safe_token(token, token_type, value);
247250
}
248251

252+
/// Advance to the token at `start` and serialize it using raw source text with JSON encoding.
253+
fn emit_unsafe_token_at(&mut self, start: u32, token_type: TokenType) {
254+
let token = self.advance_to(start);
255+
self.emit_unsafe_token(token, token_type);
256+
}
257+
249258
/// Serialize a token using its raw source text, with JSON encoding.
250259
///
251260
/// Used for tokens whose values may contain backslashes, quotes, or control characters
@@ -365,19 +374,19 @@ impl<O: ESTreeTokenConfig, S: SequenceSerializer> Context for JsonContext<'_, O,
365374
self.emit_safe_token_at(start, TokenType::new("JSXIdentifier"), name);
366375
}
367376

368-
/// Emit the token at `start` as `PrivateIdentifier`.
369-
fn emit_private_identifier_at(&mut self, start: u32, name: &str) {
370-
let token = self.advance_to(start);
377+
/// Emit a `PrivateIdentifier` token.
378+
fn emit_private_identifier(&mut self, ident: &PrivateIdentifier<'_>) {
379+
let token = self.advance_to(ident.span.start);
371380

372-
// `identifier.name` has `#` stripped and escapes decoded by the parser, and is JSON-safe.
381+
// `ident.name` has `#` stripped and escapes decoded by the parser, and is JSON-safe.
373382
// Use it in most cases — if token is not marked as escaped, it's JSON-safe, so can skip JSON encoding.
374383
// When `self.is_js()` is `true`, token `value` should *always* be the unescaped version,
375384
// so can also use `name` from AST node and skip JSON encoding.
376385
// Only fall back to raw source text when the token contains escapes *and* decoding is disabled,
377386
// since escape sequences contain `\` which needs JSON escaping.
378387
// Escaped identifiers are extremely rare, so handle them in `#[cold]` branch.
379388
if self.is_js() || !token.escaped() {
380-
self.serialize_safe_token(token, TokenType::new("PrivateIdentifier"), name);
389+
self.serialize_safe_token(token, TokenType::new("PrivateIdentifier"), &ident.name);
381390
} else {
382391
#[cold]
383392
#[inline(never)]
@@ -393,17 +402,19 @@ impl<O: ESTreeTokenConfig, S: SequenceSerializer> Context for JsonContext<'_, O,
393402
}
394403
}
395404

396-
/// Emit the token at `start` as `JSXText`.
397-
fn emit_jsx_text_at(&mut self, start: u32) {
398-
let token = self.advance_to(start);
399-
self.emit_unsafe_token(token, TokenType::new("JSXText"));
405+
/// Emit a `StringLiteral` token.
406+
fn emit_string_literal(&mut self, literal: &StringLiteral<'_>) {
407+
self.emit_unsafe_token_at(literal.span.start, TokenType::new("String"));
400408
}
401409

402-
/// Emit the token at `start` as the specified token type,
403-
/// where the token's `value` may not be JSON-safe.
404-
fn emit_unsafe_token_at(&mut self, start: u32, token_type: TokenType) {
405-
let token = self.advance_to(start);
406-
self.emit_unsafe_token(token, token_type);
410+
/// Emit a `StringLiteral` in a JSX attribute as `JSXText`.
411+
fn emit_string_literal_as_jsx_text(&mut self, literal: &StringLiteral<'_>) {
412+
self.emit_unsafe_token_at(literal.span.start, TokenType::new("JSXText"));
413+
}
414+
415+
/// Emit a `JSXText` token.
416+
fn emit_jsx_text(&mut self, jsx_text: &JSXText<'_>) {
417+
self.emit_unsafe_token_at(jsx_text.span.start, TokenType::new("JSXText"));
407418
}
408419

409420
/// Emit token for `RegExpLiteral`.

crates/oxc_estree_tokens/src/raw_transfer.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
33
use std::slice::IterMut;
44

5-
use oxc_ast::ast::{Program, RegExpLiteral, TemplateElement};
5+
use oxc_ast::ast::{
6+
JSXText, PrivateIdentifier, Program, RegExpLiteral, StringLiteral, TemplateElement,
7+
};
68
use oxc_ast_visit::{
79
Visit,
810
utf8_to_utf16::{Utf8ToUtf16, Utf8ToUtf16Converter},
911
};
1012
use oxc_parser::{Kind, Token};
1113

12-
use crate::{
13-
context::Context, options::ESTreeTokenConfig, token_type::TokenType, visitor::Visitor,
14-
};
14+
use crate::{context::Context, options::ESTreeTokenConfig, visitor::Visitor};
1515

1616
/// Walk AST and set token kinds to match ESTree token types.
1717
/// Convert token spans from UTF-8 byte offsets to UTF-16 offsets.
@@ -147,26 +147,39 @@ impl<O: ESTreeTokenConfig> Context for RawContext<'_, O> {
147147
token.set_kind(Kind::JSXIdentifier);
148148
}
149149

150-
/// Handle `PrivateIdentifier` token at `start` (no-op).
150+
/// Handle `PrivateIdentifier` token (no-op).
151151
#[inline(always)]
152-
fn emit_private_identifier_at(&mut self, _start: u32, _name: &str) {
152+
fn emit_private_identifier(&mut self, _ident: &PrivateIdentifier<'_>) {
153153
// No-op: token already has `Kind::PrivateIdentifier`.
154154
// The iterator will skip past this token on the next `advance_to` call.
155155
}
156156

157-
/// Set `Kind` of the token at `start` to `JSXText`.
158-
fn emit_jsx_text_at(&mut self, start: u32) {
159-
let token = self.advance_to(start);
157+
/// Handle `StringLiteral` token (no-op).
158+
#[inline(always)]
159+
fn emit_string_literal(&mut self, _literal: &StringLiteral<'_>) {
160+
// No-op: token already has `Kind::Str`.
161+
// The iterator will skip past this token on the next `advance_to` call.
162+
}
163+
164+
/// Set `Kind` of the `StringLiteral` token to `JSXText`.
165+
fn emit_string_literal_as_jsx_text(&mut self, literal: &StringLiteral<'_>) {
166+
let token = self.advance_to(literal.span.start);
160167
token.set_kind(Kind::JSXText);
161168
}
162169

163-
/// Handle token at `start` (no-op).
170+
/// Handle `JSXText` token (no-op).
164171
#[inline(always)]
165-
fn emit_unsafe_token_at(&mut self, _start: u32, _token_type: TokenType) {}
172+
fn emit_jsx_text(&mut self, _jsx_text: &JSXText<'_>) {
173+
// No-op: token already has `Kind::JSXText`.
174+
// The iterator will skip past this token on the next `advance_to` call.
175+
}
166176

167177
/// Handle `RegExpLiteral` (no-op).
168178
#[inline(always)]
169-
fn emit_regexp(&mut self, _regexp: &RegExpLiteral<'_>) {}
179+
fn emit_regexp(&mut self, _regexp: &RegExpLiteral<'_>) {
180+
// No-op: token already has `Kind::RegExp`.
181+
// The iterator will skip past this token on the next `advance_to` call.
182+
}
170183

171184
/// Walk template interpolations (expressions or TS types).
172185
fn walk_template_quasis_interleaved<I>(

crates/oxc_estree_tokens/src/visitor.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use oxc_ast::ast::*;
66
use oxc_ast_visit::{Visit, walk};
77
use oxc_span::GetSpan;
88

9-
use crate::{context::Context, jsx_state::JSXState, token_type::TokenType};
9+
use crate::{context::Context, jsx_state::JSXState};
1010

1111
/// Visitor that walks the AST and delegates token processing to a [`Context`].
1212
///
@@ -121,7 +121,7 @@ impl<'a, C: Context> Visit<'a> for Visitor<C> {
121121
}
122122

123123
fn visit_private_identifier(&mut self, identifier: &PrivateIdentifier<'a>) {
124-
self.ctx.emit_private_identifier_at(identifier.span.start, &identifier.name);
124+
self.ctx.emit_private_identifier(identifier);
125125
}
126126

127127
fn visit_reg_exp_literal(&mut self, regexp: &RegExpLiteral<'a>) {
@@ -229,14 +229,13 @@ impl<'a, C: Context> Visit<'a> for Visitor<C> {
229229
}
230230

231231
fn visit_string_literal(&mut self, literal: &StringLiteral<'a>) {
232-
// No-op in raw transfer mode - token's `Kind` is already `String`
233-
self.ctx.emit_unsafe_token_at(literal.span.start, TokenType::new("String"));
232+
// No-op in raw transfer mode - token already has `Kind::Str`
233+
self.ctx.emit_string_literal(literal);
234234
}
235235

236-
fn visit_jsx_text(&mut self, text: &JSXText<'a>) {
237-
// Use `emit_unsafe_token_at` not `emit_jsx_text_at`, as the token's `Kind` is already `JSXText`,
238-
// so no-op in raw transfer mode
239-
self.ctx.emit_unsafe_token_at(text.span.start, TokenType::new("JSXText"));
236+
fn visit_jsx_text(&mut self, jsx_text: &JSXText<'a>) {
237+
// No-op in raw transfer mode - token's `Kind` is already `JSXText`
238+
self.ctx.emit_jsx_text(jsx_text);
240239
}
241240

242241
fn visit_jsx_attribute(&mut self, attribute: &JSXAttribute<'a>) {
@@ -246,9 +245,8 @@ impl<'a, C: Context> Visit<'a> for Visitor<C> {
246245
self.visit_jsx_attribute_name(&attribute.name);
247246
match &attribute.value {
248247
Some(JSXAttributeValue::StringLiteral(string_literal)) => {
249-
// Use `emit_jsx_text_at` not `emit_unsafe_token_at`, as the token `Kind`
250-
// needs to be set to `JSXText` in raw transfer mode
251-
self.ctx.emit_jsx_text_at(string_literal.span.start);
248+
// Token `Kind` needs to be set to `JSXText` in raw transfer mode
249+
self.ctx.emit_string_literal_as_jsx_text(string_literal);
252250
}
253251
Some(value) => self.visit_jsx_attribute_value(value),
254252
None => {}

0 commit comments

Comments
 (0)