fix(parser): add support for empty module declaration (#2834)

Should be merged after #2829, Tried a few times to get it done with
graphite stacking but found no success. I guess it either doesn't work
with forks or It is just a skill issue since I'm not familiar with it.

closes: #2829
closes: #2830

---------

Co-authored-by: Dmytro Maretskyi <maretskii@gmail.com>
This commit is contained in:
Ali Rezvani 2024-03-27 09:18:03 +03:30 committed by GitHub
parent f6391f9b43
commit b76b02d019
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 38 additions and 20 deletions

View file

@ -697,7 +697,7 @@ pub struct TSModuleDeclaration<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))] #[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span, pub span: Span,
pub id: TSModuleDeclarationName<'a>, pub id: TSModuleDeclarationName<'a>,
pub body: TSModuleDeclarationBody<'a>, pub body: Option<TSModuleDeclarationBody<'a>>,
/// The keyword used to define this module declaration /// The keyword used to define this module declaration
/// ```text /// ```text
/// namespace Foo {} /// namespace Foo {}

View file

@ -1273,7 +1273,7 @@ impl<'a> AstBuilder<'a> {
&self, &self,
span: Span, span: Span,
id: TSModuleDeclarationName<'a>, id: TSModuleDeclarationName<'a>,
body: TSModuleDeclarationBody<'a>, body: Option<TSModuleDeclarationBody<'a>>,
kind: TSModuleDeclarationKind, kind: TSModuleDeclarationKind,
modifiers: Modifiers<'a>, modifiers: Modifiers<'a>,
) -> Box<'a, TSModuleDeclaration<'a>> { ) -> Box<'a, TSModuleDeclaration<'a>> {

View file

@ -2493,10 +2493,13 @@ pub mod walk {
TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit), TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit),
} }
match &decl.body { match &decl.body {
TSModuleDeclarationBody::TSModuleDeclaration(decl) => { Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
visitor.visit_ts_module_declaration(decl); visitor.visit_ts_module_declaration(decl);
} }
TSModuleDeclarationBody::TSModuleBlock(block) => visitor.visit_ts_module_block(block), Some(TSModuleDeclarationBody::TSModuleBlock(block)) => {
visitor.visit_ts_module_block(block);
}
None => {}
} }
visitor.leave_node(kind); visitor.leave_node(kind);
} }

View file

@ -2694,10 +2694,13 @@ pub mod walk_mut {
TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit), TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit),
} }
match &mut decl.body { match &mut decl.body {
TSModuleDeclarationBody::TSModuleDeclaration(decl) => { Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
visitor.visit_ts_module_declaration(decl); visitor.visit_ts_module_declaration(decl);
} }
TSModuleDeclarationBody::TSModuleBlock(block) => visitor.visit_ts_module_block(block), Some(TSModuleDeclarationBody::TSModuleBlock(block)) => {
visitor.visit_ts_module_block(block);
}
None => {}
} }
visitor.leave_node(kind); visitor.leave_node(kind);
} }

View file

@ -539,12 +539,12 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleDeclaration<'a> {
p.wrap_quote(name, |p, _| p.print_str(name.as_bytes())); p.wrap_quote(name, |p, _| p.print_str(name.as_bytes()));
p.print_hard_space(); p.print_hard_space();
match &self.body { match &self.body {
TSModuleDeclarationBody::TSModuleDeclaration(body) => { Some(TSModuleDeclarationBody::TSModuleDeclaration(body)) => {
p.print_block_start(body.span.start); p.print_block_start(body.span.start);
body.gen(p, ctx); body.gen(p, ctx);
p.print_block_end(body.span.end); p.print_block_end(body.span.end);
} }
TSModuleDeclarationBody::TSModuleBlock(body) => { Some(TSModuleDeclarationBody::TSModuleBlock(body)) => {
p.print_block_start(body.span.start); p.print_block_start(body.span.start);
for item in &body.body { for item in &body.body {
p.print_semicolon_if_needed(); p.print_semicolon_if_needed();
@ -553,6 +553,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleDeclaration<'a> {
p.print_semicolon_if_needed(); p.print_semicolon_if_needed();
p.print_block_end(body.span.end); p.print_block_end(body.span.end);
} }
None => {}
} }
if MINIFY { if MINIFY {
p.print_semicolon(); p.print_semicolon();

View file

@ -406,8 +406,8 @@ impl<'a> ParserImpl<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use oxc_ast::CommentKind; use oxc_ast::CommentKind;
use std::path::Path;
use super::*; use super::*;
@ -436,6 +436,15 @@ mod test {
assert_eq!(ret.errors.first().unwrap().to_string(), "Flow is not supported"); assert_eq!(ret.errors.first().unwrap().to_string(), "Flow is not supported");
} }
#[test]
fn ts_module_declaration() {
let allocator = Allocator::default();
let source_type = SourceType::from_path(Path::new("module.ts")).unwrap();
let source = "declare module 'test'\n";
let ret = Parser::new(&allocator, source, source_type).parse();
assert_eq!(ret.errors.len(), 0);
}
#[test] #[test]
fn directives() { fn directives() {
let allocator = Allocator::default(); let allocator = Allocator::default();

View file

@ -212,14 +212,12 @@ impl<'a> ParserImpl<'a> {
let mut statements = self.ast.new_vec(); let mut statements = self.ast.new_vec();
if self.at(Kind::LCurly) {
self.expect(Kind::LCurly)?; self.expect(Kind::LCurly)?;
while !self.eat(Kind::RCurly) && !self.at(Kind::Eof) { while !self.eat(Kind::RCurly) && !self.at(Kind::Eof) {
let stmt = self.parse_ts_module_item()?; let stmt = self.parse_ts_module_item()?;
statements.push(stmt); statements.push(stmt);
} }
}
Ok(self.ast.ts_module_block(self.end_span(span), statements)) Ok(self.ast.ts_module_block(self.end_span(span), statements))
} }
@ -243,11 +241,14 @@ impl<'a> ParserImpl<'a> {
let span = self.start_span(); let span = self.start_span();
let decl = let decl =
self.parse_ts_namespace_or_module_declaration_body(span, kind, Modifiers::empty())?; self.parse_ts_namespace_or_module_declaration_body(span, kind, Modifiers::empty())?;
TSModuleDeclarationBody::TSModuleDeclaration(decl) Some(TSModuleDeclarationBody::TSModuleDeclaration(decl))
} else { } else if self.at(Kind::LCurly) {
let block = self.parse_ts_module_block()?; let block = self.parse_ts_module_block()?;
self.asi()?; self.asi()?;
TSModuleDeclarationBody::TSModuleBlock(block) Some(TSModuleDeclarationBody::TSModuleBlock(block))
} else {
self.asi()?;
None
}; };
Ok(self.ast.ts_module_declaration(self.end_span(span), id, body, kind, modifiers)) Ok(self.ast.ts_module_declaration(self.end_span(span), id, body, kind, modifiers))

View file

@ -661,13 +661,14 @@ impl<'a> TypeScript<'a> {
block: &mut Box<'a, TSModuleDeclaration<'a>>, block: &mut Box<'a, TSModuleDeclaration<'a>>,
) -> Statement<'a> { ) -> Statement<'a> {
let body_statements = match &mut block.body { let body_statements = match &mut block.body {
TSModuleDeclarationBody::TSModuleDeclaration(decl) => { Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
let transformed_module_block = self.transform_ts_module_block(decl); let transformed_module_block = self.transform_ts_module_block(decl);
self.ctx.ast.new_vec_single(transformed_module_block) self.ctx.ast.new_vec_single(transformed_module_block)
} }
TSModuleDeclarationBody::TSModuleBlock(ts_module_block) => { Some(TSModuleDeclarationBody::TSModuleBlock(ts_module_block)) => {
self.ctx.ast.move_statement_vec(&mut ts_module_block.body) self.ctx.ast.move_statement_vec(&mut ts_module_block.body)
} }
None => self.ctx.ast.new_vec(),
}; };
let name = block.id.name(); let name = block.id.name();