From 176d6f2c8e423cf61b4da44536a8044c34bfb096 Mon Sep 17 00:00:00 2001 From: zoomdong <1344492820@qq.com> Date: Mon, 20 Jan 2025 16:52:00 +0800 Subject: [PATCH] fix(parser): export_named_type should parse default as normal --- .changeset/export_named_type_parser.md | 14 +++++ .../tests/specs/ts/module/export_clause.ts | 2 + .../specs/ts/module/export_clause.ts.snap | 5 ++ crates/biome_js_parser/src/syntax/module.rs | 4 +- ...s_export_named_from_specifier_with_type.ts | 1 + ...ort_named_from_specifier_with_type.ts.snap | 59 +++++++++++++++++-- crates/biome_js_parser/tests/spec_test.rs | 8 +-- 7 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 .changeset/export_named_type_parser.md diff --git a/.changeset/export_named_type_parser.md b/.changeset/export_named_type_parser.md new file mode 100644 index 000000000000..62f70f9aa3bf --- /dev/null +++ b/.changeset/export_named_type_parser.md @@ -0,0 +1,14 @@ +--- +cli: patch +biome_js_parser: patch +--- + +# Export Named Type support `default` parser + +The following code: + +```ts +export { type A as default } from './b.ts'; +``` + +Should be parsed successfully. \ No newline at end of file diff --git a/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts b/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts index 6fcc164d2c25..b919fbaf7e1c 100644 --- a/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts +++ b/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts @@ -20,3 +20,5 @@ export declare class E { } export type * from "types"; export type * as types from "types"; + +export { type default as G } from './types.ts'; diff --git a/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts.snap b/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts.snap index e2638fe7fc61..65170a093503 100644 --- a/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts.snap +++ b/crates/biome_js_formatter/tests/specs/ts/module/export_clause.ts.snap @@ -1,6 +1,7 @@ --- source: crates/biome_formatter_test/src/snapshot_builder.rs info: ts/module/export_clause.ts +snapshot_kind: text --- # Input @@ -28,6 +29,8 @@ export type * from "types"; export type * as types from "types"; +export { type default as G } from './types.ts'; + ``` @@ -76,4 +79,6 @@ export declare class E {} export type * from "types"; export type * as types from "types"; + +export { type default as G } from "./types.ts"; ``` diff --git a/crates/biome_js_parser/src/syntax/module.rs b/crates/biome_js_parser/src/syntax/module.rs index 600d6cba930d..9641f6b9f6da 100644 --- a/crates/biome_js_parser/src/syntax/module.rs +++ b/crates/biome_js_parser/src/syntax/module.rs @@ -977,8 +977,8 @@ where metadata.is_type = true; } } else { - // `{ type x }` or `{ type "x" }` or `{ type x as }` - metadata.is_type = is_nth_name(p, 1); + // `{ type x }` or `{ type "x" }` or `{ type x as }` or `{ type default as }` + metadata.is_type = is_nth_name(p, 1) || p.nth_at(1, T![default]); metadata.has_alias = p.nth_at(2, T![as]); } } else if p.at(T![as]) && is_nth_alias(p, 1) { diff --git a/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts b/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts index 2a9ee434fbef..8d3075f893e1 100644 --- a/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts +++ b/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts @@ -1,2 +1,3 @@ export { type A } from "a" export { type } from "./type"; +export { type default as CrsMeta } from './crs-meta.js'; diff --git a/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts.snap b/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts.snap index 238669242e13..fb5f027a1913 100644 --- a/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts.snap +++ b/crates/biome_js_parser/tests/js_test_suite/ok/ts_export_named_from_specifier_with_type.ts.snap @@ -8,6 +8,7 @@ snapshot_kind: text ```ts export { type A } from "a" export { type } from "./type"; +export { type default as CrsMeta } from './crs-meta.js'; ``` @@ -68,19 +69,48 @@ JsModule { semicolon_token: SEMICOLON@56..57 ";" [] [], }, }, + JsExport { + decorators: JsDecoratorList [], + export_token: EXPORT_KW@57..65 "export" [Newline("\n")] [Whitespace(" ")], + export_clause: JsExportNamedFromClause { + type_token: missing (optional), + l_curly_token: L_CURLY@65..67 "{" [] [Whitespace(" ")], + specifiers: JsExportNamedFromSpecifierList [ + JsExportNamedFromSpecifier { + type_token: TYPE_KW@67..72 "type" [] [Whitespace(" ")], + source_name: JsLiteralExportName { + value: IDENT@72..80 "default" [] [Whitespace(" ")], + }, + export_as: JsExportAsClause { + as_token: AS_KW@80..83 "as" [] [Whitespace(" ")], + exported_name: JsLiteralExportName { + value: IDENT@83..91 "CrsMeta" [] [Whitespace(" ")], + }, + }, + }, + ], + r_curly_token: R_CURLY@91..93 "}" [] [Whitespace(" ")], + from_token: FROM_KW@93..98 "from" [] [Whitespace(" ")], + source: JsModuleSource { + value_token: JS_STRING_LITERAL@98..113 "'./crs-meta.js'" [] [], + }, + assertion: missing (optional), + semicolon_token: SEMICOLON@113..114 ";" [] [], + }, + }, ], - eof_token: EOF@57..58 "" [Newline("\n")] [], + eof_token: EOF@114..115 "" [Newline("\n")] [], } ``` ## CST ``` -0: JS_MODULE@0..58 +0: JS_MODULE@0..115 0: (empty) 1: (empty) 2: JS_DIRECTIVE_LIST@0..0 - 3: JS_MODULE_ITEM_LIST@0..57 + 3: JS_MODULE_ITEM_LIST@0..114 0: JS_EXPORT@0..26 0: JS_DECORATOR_LIST@0..0 1: EXPORT_KW@0..7 "export" [] [Whitespace(" ")] @@ -117,6 +147,27 @@ JsModule { 0: JS_STRING_LITERAL@48..56 "\"./type\"" [] [] 6: (empty) 7: SEMICOLON@56..57 ";" [] [] - 4: EOF@57..58 "" [Newline("\n")] [] + 2: JS_EXPORT@57..114 + 0: JS_DECORATOR_LIST@57..57 + 1: EXPORT_KW@57..65 "export" [Newline("\n")] [Whitespace(" ")] + 2: JS_EXPORT_NAMED_FROM_CLAUSE@65..114 + 0: (empty) + 1: L_CURLY@65..67 "{" [] [Whitespace(" ")] + 2: JS_EXPORT_NAMED_FROM_SPECIFIER_LIST@67..91 + 0: JS_EXPORT_NAMED_FROM_SPECIFIER@67..91 + 0: TYPE_KW@67..72 "type" [] [Whitespace(" ")] + 1: JS_LITERAL_EXPORT_NAME@72..80 + 0: IDENT@72..80 "default" [] [Whitespace(" ")] + 2: JS_EXPORT_AS_CLAUSE@80..91 + 0: AS_KW@80..83 "as" [] [Whitespace(" ")] + 1: JS_LITERAL_EXPORT_NAME@83..91 + 0: IDENT@83..91 "CrsMeta" [] [Whitespace(" ")] + 3: R_CURLY@91..93 "}" [] [Whitespace(" ")] + 4: FROM_KW@93..98 "from" [] [Whitespace(" ")] + 5: JS_MODULE_SOURCE@98..113 + 0: JS_STRING_LITERAL@98..113 "'./crs-meta.js'" [] [] + 6: (empty) + 7: SEMICOLON@113..114 ";" [] [] + 4: EOF@114..115 "" [Newline("\n")] [] ``` diff --git a/crates/biome_js_parser/tests/spec_test.rs b/crates/biome_js_parser/tests/spec_test.rs index 76c42085cbf7..f11bdfa1b84e 100644 --- a/crates/biome_js_parser/tests/spec_test.rs +++ b/crates/biome_js_parser/tests/spec_test.rs @@ -176,13 +176,7 @@ pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome_ #[test] pub fn quick_test() { let code = r#" -export let shim: typeof import("./foo2") = { - Bar: Bar2 -}; - -export interface Foo { - bar: import('immutable').Map; -} +export { type default as CrsMeta } from './crs-meta.js'; "#; let root = parse(code, JsFileSource::ts(), JsParserOptions::default());