fix(rome_js_formatter, rome_js_parser): Empty external module declaration formatting
MODIFY
crates/rome_js_formatter/src/ts/declarations/external_module_declaration.rs
crates/rome_js_formatter/src/ts/declarations/external_module_declaration.rs
use crate::prelude::*;
use rome_formatter::write;
-use rome_js_syntax::TsExternalModuleDeclaration;
use rome_js_syntax::TsExternalModuleDeclarationFields;
+use rome_js_syntax::{TsAnyExternalModuleDeclarationBody, TsExternalModuleDeclaration};
#[derive(Debug, Clone, Default)]
pub struct FormatTsExternalModuleDeclaration;
@@ -19,15 +19,22 @@ impl FormatNodeRule<TsExternalModuleDeclaration> for FormatTsExternalModuleDecla
source,
} = node.as_fields();
- write![
- f,
- [
- module_token.format(),
- space(),
- source.format(),
- space(),
- body.format()
- ]
- ]
+ write!(f, [module_token.format(), space(), source.format(),])?;
+
+ match body {
+ Some(TsAnyExternalModuleDeclarationBody::TsEmptyExternalModuleDeclarationBody(
+ body,
+ )) => {
+ body.format().fmt(f)?;
+ }
+ Some(TsAnyExternalModuleDeclarationBody::TsModuleBlock(body)) => {
+ write!(f, [space(), body.format()])?;
+ }
+ None => {
+ text(";").fmt(f)?;
+ }
+ }
+
+ Ok(())
}
}

DELETE
crates/rome_js_formatter/tests/specs/prettier/typescript/module/empty.ts.snap
----
-source: crates/rome_js_formatter/tests/prettier_tests.rs
----
-
-# Input
-
-```js
-declare module 'autoprefixer';
-```
-
-
-# Prettier differences
-
-```diff
---- Prettier
-+++ Rome
-@@ -1 +1 @@
--declare module "autoprefixer";
-+declare module "autoprefixer" ;
-```
-
-# Output
-
-```js
-declare module "autoprefixer" ;
-```
-
-
-

ADD
crates/rome_js_formatter/tests/specs/ts/declare.ts
+declare module 'remark-html' ;
+declare module 'other'
+
+declare module 'remark-html' {
+
+}

ADD
crates/rome_js_formatter/tests/specs/ts/declare.ts.snap
+---
+source: crates/rome_js_formatter/tests/spec_test.rs
+expression: declare.ts
+---
+
+# Input
+
+```js
+declare module 'remark-html' ;
+declare module 'other'
+
+declare module 'remark-html' {
+
+}
+
+```
+
+
+=============================
+
+# Outputs
+
+## Output 1
+
+-----
+Indent style: Tab
+Line width: 80
+Quote style: Double Quotes
+Quote properties: As needed
+Trailing comma: All
+-----
+
+```js
+declare module "remark-html";
+declare module "other";
+
+declare module "remark-html" {}
+```
+
+

MODIFY
crates/rome_js_parser/src/syntax/typescript/statement.rs
crates/rome_js_parser/src/syntax/typescript/statement.rs
@@ -427,7 +427,8 @@ pub(crate) fn parse_any_ts_namespace_declaration_statement(p: &mut Parser) -> Pa
//
// test ts ts_external_module_declaration
// declare module "a";
-// declare module "./import" {}
+// declare module "b"
+// declare module "import" {}
//
// test_err ts ts_module_err
// declare module a; // missing body
@@ -451,9 +452,13 @@ fn parse_ts_namespace_or_module_declaration_clause(
let body = parse_ts_module_block(p);
if body.is_absent() {
+ if p.at(T![;]) {
let body = p.start();
- semi(p, TextRange::new(stmt_start_pos, p.cur_range().end()));
+ p.bump(T![;]);
body.complete(p, TS_EMPTY_EXTERNAL_MODULE_DECLARATION_BODY);
+ } else {
+ semi(p, TextRange::new(stmt_start_pos, p.cur_range().end()));
+ }
}
return Present(m.complete(p, TS_EXTERNAL_MODULE_DECLARATION));

MODIFY
crates/rome_js_parser/test_data/inline/err/ts_module_err.rast
crates/rome_js_parser/test_data/inline/err/ts_module_err.rast
@@ -22,9 +22,7 @@ JsModule {
source: JsModuleSource {
value_token: JS_STRING_LITERAL@49..53 "\"a\"" [] [Whitespace(" ")],
},
- body: TsEmptyExternalModuleDeclarationBody {
- semicolon_token: missing (required),
- },
+ body: missing (optional),
},
},
TsDeclareStatement {
@@ -62,8 +60,7 @@ JsModule {
0: MODULE_KW@42..49 "module" [] [Whitespace(" ")]
1: JS_MODULE_SOURCE@49..53
0: JS_STRING_LITERAL@49..53 "\"a\"" [] [Whitespace(" ")]
- 2: TS_EMPTY_EXTERNAL_MODULE_DECLARATION_BODY@53..53
- 0: (empty)
+ 2: (empty)
3: TS_DECLARE_STATEMENT@53..88
0: DECLARE_KW@53..61 "declare" [] [Whitespace(" ")]
1: TS_EXTERNAL_MODULE_DECLARATION@61..88

MODIFY
crates/rome_js_parser/test_data/inline/ok/ts_external_module_declaration.rast
crates/rome_js_parser/test_data/inline/ok/ts_external_module_declaration.rast
@@ -19,23 +19,33 @@ JsModule {
declaration: TsExternalModuleDeclaration {
module_token: MODULE_KW@28..35 "module" [] [Whitespace(" ")],
source: JsModuleSource {
- value_token: JS_STRING_LITERAL@35..46 "\"./import\"" [] [Whitespace(" ")],
+ value_token: JS_STRING_LITERAL@35..38 "\"b\"" [] [],
+ },
+ body: missing (optional),
+ },
+ },
+ TsDeclareStatement {
+ declare_token: DECLARE_KW@38..47 "declare" [Newline("\n")] [Whitespace(" ")],
+ declaration: TsExternalModuleDeclaration {
+ module_token: MODULE_KW@47..54 "module" [] [Whitespace(" ")],
+ source: JsModuleSource {
+ value_token: JS_STRING_LITERAL@54..63 "\"import\"" [] [Whitespace(" ")],
},
body: TsModuleBlock {
- l_curly_token: L_CURLY@46..47 "{" [] [],
+ l_curly_token: L_CURLY@63..64 "{" [] [],
items: JsModuleItemList [],
- r_curly_token: R_CURLY@47..48 "}" [] [],
+ r_curly_token: R_CURLY@64..65 "}" [] [],
},
},
},
],
- eof_token: EOF@48..49 "" [Newline("\n")] [],
+ eof_token: EOF@65..66 "" [Newline("\n")] [],
}
-0: JS_MODULE@0..49
+0: JS_MODULE@0..66
0: (empty)
1: JS_DIRECTIVE_LIST@0..0
- 2: JS_MODULE_ITEM_LIST@0..48
+ 2: JS_MODULE_ITEM_LIST@0..65
0: TS_DECLARE_STATEMENT@0..19
0: DECLARE_KW@0..8 "declare" [] [Whitespace(" ")]
1: TS_EXTERNAL_MODULE_DECLARATION@8..19
@@ -44,14 +54,21 @@ JsModule {
0: JS_STRING_LITERAL@15..18 "\"a\"" [] []
2: TS_EMPTY_EXTERNAL_MODULE_DECLARATION_BODY@18..19
0: SEMICOLON@18..19 ";" [] []
- 1: TS_DECLARE_STATEMENT@19..48
+ 1: TS_DECLARE_STATEMENT@19..38
0: DECLARE_KW@19..28 "declare" [Newline("\n")] [Whitespace(" ")]
- 1: TS_EXTERNAL_MODULE_DECLARATION@28..48
+ 1: TS_EXTERNAL_MODULE_DECLARATION@28..38
0: MODULE_KW@28..35 "module" [] [Whitespace(" ")]
- 1: JS_MODULE_SOURCE@35..46
- 0: JS_STRING_LITERAL@35..46 "\"./import\"" [] [Whitespace(" ")]
- 2: TS_MODULE_BLOCK@46..48
- 0: L_CURLY@46..47 "{" [] []
- 1: JS_MODULE_ITEM_LIST@47..47
- 2: R_CURLY@47..48 "}" [] []
- 3: EOF@48..49 "" [Newline("\n")] []
+ 1: JS_MODULE_SOURCE@35..38
+ 0: JS_STRING_LITERAL@35..38 "\"b\"" [] []
+ 2: (empty)
+ 2: TS_DECLARE_STATEMENT@38..65
+ 0: DECLARE_KW@38..47 "declare" [Newline("\n")] [Whitespace(" ")]
+ 1: TS_EXTERNAL_MODULE_DECLARATION@47..65
+ 0: MODULE_KW@47..54 "module" [] [Whitespace(" ")]
+ 1: JS_MODULE_SOURCE@54..63
+ 0: JS_STRING_LITERAL@54..63 "\"import\"" [] [Whitespace(" ")]
+ 2: TS_MODULE_BLOCK@63..65
+ 0: L_CURLY@63..64 "{" [] []
+ 1: JS_MODULE_ITEM_LIST@64..64
+ 2: R_CURLY@64..65 "}" [] []
+ 3: EOF@65..66 "" [Newline("\n")] []

MODIFY
crates/rome_js_parser/test_data/inline/ok/ts_external_module_declaration.ts
crates/rome_js_parser/test_data/inline/ok/ts_external_module_declaration.ts
declare module "a";
-declare module "./import" {}
+declare module "b"
+declare module "import" {}

fix(rome_js_formatter, rome_js_parser): Empty external module declaration formatting (#3472)