Skip to content

Commit

Permalink
fix(ast): correct JSON serialization of TSModuleBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Jun 23, 2024
1 parent bef7f2b commit e7bf211
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
4 changes: 3 additions & 1 deletion crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,13 +832,15 @@ pub enum TSModuleDeclarationBody<'a> {
TSModuleBlock(Box<'a, TSModuleBlock<'a>>),
}

// See serializer in serialize.rs
#[visited_node]
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", derive(Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSModuleBlock<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
#[cfg_attr(feature = "serialize", serde(skip))]
pub directives: Vec<'a, Directive<'a>>,
pub body: Vec<'a, Statement<'a>>,
}
Expand Down
54 changes: 52 additions & 2 deletions crates/oxc_ast/src/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use serde::{
use crate::ast::{
ArrayAssignmentTarget, ArrayPattern, AssignmentTargetMaybeDefault, AssignmentTargetProperty,
AssignmentTargetRest, BindingPattern, BindingPatternKind, BindingProperty, BindingRestElement,
Elision, FormalParameter, FormalParameterKind, FormalParameters, ObjectAssignmentTarget,
ObjectPattern, Program, RegExpFlags, TSTypeAnnotation,
Directive, Elision, FormalParameter, FormalParameterKind, FormalParameters,
ObjectAssignmentTarget, ObjectPattern, Program, RegExpFlags, Statement, StringLiteral,
TSModuleBlock, TSTypeAnnotation,
};

pub struct EcmaFormatter;
Expand Down Expand Up @@ -199,3 +200,52 @@ impl<'a, 'b, E: Serialize, R: Serialize> Serialize for ElementsAndRest<'a, 'b, E
}
}
}

/// Serialize `TSModuleBlock` to be ESTree compatible, with `body` and `directives` fields combined,
/// and directives output as `StringLiteral` expression statements
impl<'a> Serialize for TSModuleBlock<'a> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let converted = SerTSModuleBlock {
span: self.span,
body: DirectivesAndStatements { directives: &self.directives, body: &self.body },
};
converted.serialize(serializer)
}
}

#[derive(Serialize)]
#[serde(tag = "type", rename = "TSModuleBlock")]
struct SerTSModuleBlock<'a, 'b> {
#[serde(flatten)]
span: Span,
body: DirectivesAndStatements<'a, 'b>,
}

struct DirectivesAndStatements<'a, 'b> {
directives: &'b [Directive<'a>],
body: &'b [Statement<'a>],
}

impl<'a, 'b> Serialize for DirectivesAndStatements<'a, 'b> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_seq(Some(self.directives.len() + self.body.len()))?;
for directive in self.directives {
seq.serialize_element(&DirectiveAsStatement {
span: directive.span,
expression: &directive.expression,
})?;
}
for stmt in self.body {
seq.serialize_element(stmt)?;
}
seq.end()
}
}

#[derive(Serialize)]
#[serde(tag = "type", rename = "ExpressionStatement")]
struct DirectiveAsStatement<'a, 'b> {
#[serde(flatten)]
span: Span,
expression: &'b StringLiteral<'a>,
}

0 comments on commit e7bf211

Please sign in to comment.