From a1d1c91280fbd094f3766f9e5d79ac47611e31d6 Mon Sep 17 00:00:00 2001 From: zoomdong <1344492820@qq.com> Date: Tue, 15 Oct 2024 13:25:13 +0800 Subject: [PATCH] feat(biome_js_parser): support defer attribute in import statements --- CHANGELOG.md | 10 ++++ .../src/generated/node_factory.rs | 7 +++ .../src/generated/syntax_factory.rs | 9 +++- .../src/js/module/import_namespace_clause.rs | 4 ++ crates/biome_js_parser/src/lexer/mod.rs | 1 + crates/biome_js_parser/src/syntax/module.rs | 22 ++++++++ crates/biome_js_parser/src/tests.rs | 2 +- .../test_data/inline/err/import_err.rast | 12 +++-- .../test_data/inline/ok/import_decl.rast | 10 ++-- .../inline/ok/import_defer_clause.js | 1 + .../inline/ok/import_defer_clause.rast | 50 +++++++++++++++++++ .../inline/ok/ts_import_clause_types.rast | 10 ++-- crates/biome_js_syntax/src/generated/kind.rs | 5 +- crates/biome_js_syntax/src/generated/nodes.rs | 17 +++++-- .../src/generated/nodes_mut.rs | 14 ++++-- xtask/codegen/js.ungram | 1 + xtask/codegen/src/js_kinds_src.rs | 1 + 17 files changed, 153 insertions(+), 23 deletions(-) create mode 100644 crates/biome_js_parser/test_data/inline/ok/import_defer_clause.js create mode 100644 crates/biome_js_parser/test_data/inline/ok/import_defer_clause.rast diff --git a/CHANGELOG.md b/CHANGELOG.md index 0adcbc5d07f8..52a3f8660933 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -178,6 +178,16 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b ### Parser +#### New features + +- JS Parser support defer attribute in import statements ([#4215](https://github.com/biomejs/biome/issues/4215)). + + ```js + import defer * as myModule from "my-module"; + ``` + + Contributed by @fireairforce + #### Bug Fixes - The CSS parser now accepts more emoji in identifiers ([#3627](https://github.com/biomejs/biome/issues/3627#issuecomment-2392388022)). diff --git a/crates/biome_js_factory/src/generated/node_factory.rs b/crates/biome_js_factory/src/generated/node_factory.rs index 6e9666567949..f2afe8feb2a9 100644 --- a/crates/biome_js_factory/src/generated/node_factory.rs +++ b/crates/biome_js_factory/src/generated/node_factory.rs @@ -2209,6 +2209,7 @@ pub fn js_import_namespace_clause( from_token, source, type_token: None, + defer_token: None, assertion: None, } } @@ -2217,6 +2218,7 @@ pub struct JsImportNamespaceClauseBuilder { from_token: SyntaxToken, source: AnyJsModuleSource, type_token: Option, + defer_token: Option, assertion: Option, } impl JsImportNamespaceClauseBuilder { @@ -2224,6 +2226,10 @@ impl JsImportNamespaceClauseBuilder { self.type_token = Some(type_token); self } + pub fn with_defer_token(mut self, defer_token: SyntaxToken) -> Self { + self.defer_token = Some(defer_token); + self + } pub fn with_assertion(mut self, assertion: JsImportAssertion) -> Self { self.assertion = Some(assertion); self @@ -2233,6 +2239,7 @@ impl JsImportNamespaceClauseBuilder { JsSyntaxKind::JS_IMPORT_NAMESPACE_CLAUSE, [ self.type_token.map(|token| SyntaxElement::Token(token)), + self.defer_token.map(|token| SyntaxElement::Token(token)), Some(SyntaxElement::Node(self.namespace_specifier.into_syntax())), Some(SyntaxElement::Token(self.from_token)), Some(SyntaxElement::Node(self.source.into_syntax())), diff --git a/crates/biome_js_factory/src/generated/syntax_factory.rs b/crates/biome_js_factory/src/generated/syntax_factory.rs index 4e265b9ebd0a..f4927dc760de 100644 --- a/crates/biome_js_factory/src/generated/syntax_factory.rs +++ b/crates/biome_js_factory/src/generated/syntax_factory.rs @@ -3107,7 +3107,7 @@ impl SyntaxFactory for JsSyntaxFactory { } JS_IMPORT_NAMESPACE_CLAUSE => { let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<5usize> = RawNodeSlots::default(); + let mut slots: RawNodeSlots<6usize> = RawNodeSlots::default(); let mut current_element = elements.next(); if let Some(element) = ¤t_element { if element.kind() == T![type] { @@ -3116,6 +3116,13 @@ impl SyntaxFactory for JsSyntaxFactory { } } slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T![defer] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); if let Some(element) = ¤t_element { if JsNamespaceImportSpecifier::can_cast(element.kind()) { slots.mark_present(); diff --git a/crates/biome_js_formatter/src/js/module/import_namespace_clause.rs b/crates/biome_js_formatter/src/js/module/import_namespace_clause.rs index 0ddc63937025..8610daed6752 100644 --- a/crates/biome_js_formatter/src/js/module/import_namespace_clause.rs +++ b/crates/biome_js_formatter/src/js/module/import_namespace_clause.rs @@ -13,6 +13,7 @@ impl FormatNodeRule for FormatJsImportNamespaceClause { type_token, namespace_specifier, from_token, + defer_token, source, assertion, } = node.as_fields(); @@ -20,6 +21,9 @@ impl FormatNodeRule for FormatJsImportNamespaceClause { if let Some(type_token) = type_token { write!(f, [type_token.format(), space()])?; } + if let Some(defer_token) = defer_token { + write!(f, [defer_token.format(), space()])?; + } write![ f, diff --git a/crates/biome_js_parser/src/lexer/mod.rs b/crates/biome_js_parser/src/lexer/mod.rs index 500e1914fcff..a75cbf86b677 100644 --- a/crates/biome_js_parser/src/lexer/mod.rs +++ b/crates/biome_js_parser/src/lexer/mod.rs @@ -1034,6 +1034,7 @@ impl<'src> JsLexer<'src> { b"of" => OF_KW, b"out" => OUT_KW, b"using" => USING_KW, + b"defer" => DEFER_KW, _ => T![ident], } } diff --git a/crates/biome_js_parser/src/syntax/module.rs b/crates/biome_js_parser/src/syntax/module.rs index 8e85b8b1cb4e..2b90dbf34725 100644 --- a/crates/biome_js_parser/src/syntax/module.rs +++ b/crates/biome_js_parser/src/syntax/module.rs @@ -293,6 +293,28 @@ fn parse_import_clause(p: &mut JsParser) -> ParsedSyntax { if is_typed { p.eat(T![type]); } + + // test js import_defer_clause + // import defer * as yNamespace from "y"; + let is_defer = 'is_defer: { + if !p.at(T![defer]) { + break 'is_defer false; + } + + if matches!(p.nth(1), T![*] | T!['{']) { + break 'is_defer true; + } + + if !is_nth_at_identifier_binding(p, 1) { + break 'is_defer false; + } + + !p.nth_at(1, T![from]) || p.nth_at(2, T![from]) + }; + + if is_defer { + p.eat(T![defer]); + } let clause = match p.cur() { T![*] => parse_import_namespace_clause_rest(p, m), diff --git a/crates/biome_js_parser/src/tests.rs b/crates/biome_js_parser/src/tests.rs index 5df6860aef3b..8bb58ede06df 100644 --- a/crates/biome_js_parser/src/tests.rs +++ b/crates/biome_js_parser/src/tests.rs @@ -408,7 +408,7 @@ fn diagnostics_print_correctly() { #[test] pub fn quick_test() { let code = r#" - type Equals = A extends (x: B extends C ? D : E) => 0 ? F : G; + import defer * as yNamespace from "y"; "#; let root = parse( code, diff --git a/crates/biome_js_parser/test_data/inline/err/import_err.rast b/crates/biome_js_parser/test_data/inline/err/import_err.rast index 33550b72d731..eb0e675b4b18 100644 --- a/crates/biome_js_parser/test_data/inline/err/import_err.rast +++ b/crates/biome_js_parser/test_data/inline/err/import_err.rast @@ -12,6 +12,7 @@ JsModule { import_token: IMPORT_KW@7..15 "import" [Newline("\n")] [Whitespace(" ")], import_clause: JsImportNamespaceClause { type_token: missing (optional), + defer_token: missing (optional), namespace_specifier: JsNamespaceImportSpecifier { star_token: STAR@15..16 "*" [] [], as_token: missing (required), @@ -27,6 +28,7 @@ JsModule { import_token: IMPORT_KW@17..25 "import" [Newline("\n")] [Whitespace(" ")], import_clause: JsImportNamespaceClause { type_token: missing (optional), + defer_token: missing (optional), namespace_specifier: JsNamespaceImportSpecifier { star_token: STAR@25..27 "*" [] [Whitespace(" ")], as_token: AS_KW@27..30 "as" [] [Whitespace(" ")], @@ -291,26 +293,28 @@ JsModule { 0: IMPORT_KW@7..15 "import" [Newline("\n")] [Whitespace(" ")] 1: JS_IMPORT_NAMESPACE_CLAUSE@15..16 0: (empty) - 1: JS_NAMESPACE_IMPORT_SPECIFIER@15..16 + 1: (empty) + 2: JS_NAMESPACE_IMPORT_SPECIFIER@15..16 0: STAR@15..16 "*" [] [] 1: (empty) 2: (empty) - 2: (empty) 3: (empty) 4: (empty) + 5: (empty) 2: SEMICOLON@16..17 ";" [] [] 2: JS_IMPORT@17..31 0: IMPORT_KW@17..25 "import" [Newline("\n")] [Whitespace(" ")] 1: JS_IMPORT_NAMESPACE_CLAUSE@25..31 0: (empty) - 1: JS_NAMESPACE_IMPORT_SPECIFIER@25..31 + 1: (empty) + 2: JS_NAMESPACE_IMPORT_SPECIFIER@25..31 0: STAR@25..27 "*" [] [Whitespace(" ")] 1: AS_KW@27..30 "as" [] [Whitespace(" ")] 2: JS_IDENTIFIER_BINDING@30..31 0: IDENT@30..31 "c" [] [] - 2: (empty) 3: (empty) 4: (empty) + 5: (empty) 2: (empty) 3: JS_BOGUS_STATEMENT@31..33 0: COMMA@31..33 "," [] [Whitespace(" ")] diff --git a/crates/biome_js_parser/test_data/inline/ok/import_decl.rast b/crates/biome_js_parser/test_data/inline/ok/import_decl.rast index 7b59b6d531a6..5c15ee42e7c4 100644 --- a/crates/biome_js_parser/test_data/inline/ok/import_decl.rast +++ b/crates/biome_js_parser/test_data/inline/ok/import_decl.rast @@ -7,6 +7,7 @@ JsModule { import_token: IMPORT_KW@0..7 "import" [] [Whitespace(" ")], import_clause: JsImportNamespaceClause { type_token: missing (optional), + defer_token: missing (optional), namespace_specifier: JsNamespaceImportSpecifier { star_token: STAR@7..9 "*" [] [Whitespace(" ")], as_token: AS_KW@9..12 "as" [] [Whitespace(" ")], @@ -35,14 +36,15 @@ JsModule { 0: IMPORT_KW@0..7 "import" [] [Whitespace(" ")] 1: JS_IMPORT_NAMESPACE_CLAUSE@7..26 0: (empty) - 1: JS_NAMESPACE_IMPORT_SPECIFIER@7..16 + 1: (empty) + 2: JS_NAMESPACE_IMPORT_SPECIFIER@7..16 0: STAR@7..9 "*" [] [Whitespace(" ")] 1: AS_KW@9..12 "as" [] [Whitespace(" ")] 2: JS_IDENTIFIER_BINDING@12..16 0: IDENT@12..16 "foo" [] [Whitespace(" ")] - 2: FROM_KW@16..21 "from" [] [Whitespace(" ")] - 3: JS_MODULE_SOURCE@21..26 + 3: FROM_KW@16..21 "from" [] [Whitespace(" ")] + 4: JS_MODULE_SOURCE@21..26 0: JS_STRING_LITERAL@21..26 "\"bla\"" [] [] - 4: (empty) + 5: (empty) 2: SEMICOLON@26..27 ";" [] [] 4: EOF@27..28 "" [Newline("\n")] [] diff --git a/crates/biome_js_parser/test_data/inline/ok/import_defer_clause.js b/crates/biome_js_parser/test_data/inline/ok/import_defer_clause.js new file mode 100644 index 000000000000..c83d0dfdd36e --- /dev/null +++ b/crates/biome_js_parser/test_data/inline/ok/import_defer_clause.js @@ -0,0 +1 @@ +import defer * as yNamespace from "y"; diff --git a/crates/biome_js_parser/test_data/inline/ok/import_defer_clause.rast b/crates/biome_js_parser/test_data/inline/ok/import_defer_clause.rast new file mode 100644 index 000000000000..7069a6ebaaf3 --- /dev/null +++ b/crates/biome_js_parser/test_data/inline/ok/import_defer_clause.rast @@ -0,0 +1,50 @@ +JsModule { + bom_token: missing (optional), + interpreter_token: missing (optional), + directives: JsDirectiveList [], + items: JsModuleItemList [ + JsImport { + import_token: IMPORT_KW@0..7 "import" [] [Whitespace(" ")], + import_clause: JsImportNamespaceClause { + type_token: missing (optional), + defer_token: DEFER_KW@7..13 "defer" [] [Whitespace(" ")], + namespace_specifier: JsNamespaceImportSpecifier { + star_token: STAR@13..15 "*" [] [Whitespace(" ")], + as_token: AS_KW@15..18 "as" [] [Whitespace(" ")], + local_name: JsIdentifierBinding { + name_token: IDENT@18..29 "yNamespace" [] [Whitespace(" ")], + }, + }, + from_token: FROM_KW@29..34 "from" [] [Whitespace(" ")], + source: JsModuleSource { + value_token: JS_STRING_LITERAL@34..37 "\"y\"" [] [], + }, + assertion: missing (optional), + }, + semicolon_token: SEMICOLON@37..38 ";" [] [], + }, + ], + eof_token: EOF@38..39 "" [Newline("\n")] [], +} + +0: JS_MODULE@0..39 + 0: (empty) + 1: (empty) + 2: JS_DIRECTIVE_LIST@0..0 + 3: JS_MODULE_ITEM_LIST@0..38 + 0: JS_IMPORT@0..38 + 0: IMPORT_KW@0..7 "import" [] [Whitespace(" ")] + 1: JS_IMPORT_NAMESPACE_CLAUSE@7..37 + 0: (empty) + 1: DEFER_KW@7..13 "defer" [] [Whitespace(" ")] + 2: JS_NAMESPACE_IMPORT_SPECIFIER@13..29 + 0: STAR@13..15 "*" [] [Whitespace(" ")] + 1: AS_KW@15..18 "as" [] [Whitespace(" ")] + 2: JS_IDENTIFIER_BINDING@18..29 + 0: IDENT@18..29 "yNamespace" [] [Whitespace(" ")] + 3: FROM_KW@29..34 "from" [] [Whitespace(" ")] + 4: JS_MODULE_SOURCE@34..37 + 0: JS_STRING_LITERAL@34..37 "\"y\"" [] [] + 5: (empty) + 2: SEMICOLON@37..38 ";" [] [] + 4: EOF@38..39 "" [Newline("\n")] [] diff --git a/crates/biome_js_parser/test_data/inline/ok/ts_import_clause_types.rast b/crates/biome_js_parser/test_data/inline/ok/ts_import_clause_types.rast index 379f48b097a6..30949b8643dc 100644 --- a/crates/biome_js_parser/test_data/inline/ok/ts_import_clause_types.rast +++ b/crates/biome_js_parser/test_data/inline/ok/ts_import_clause_types.rast @@ -41,6 +41,7 @@ JsModule { import_token: IMPORT_KW@69..77 "import" [Newline("\n")] [Whitespace(" ")], import_clause: JsImportNamespaceClause { type_token: TYPE_KW@77..82 "type" [] [Whitespace(" ")], + defer_token: missing (optional), namespace_specifier: JsNamespaceImportSpecifier { star_token: STAR@82..84 "*" [] [Whitespace(" ")], as_token: AS_KW@84..87 "as" [] [Whitespace(" ")], @@ -134,15 +135,16 @@ JsModule { 0: IMPORT_KW@69..77 "import" [Newline("\n")] [Whitespace(" ")] 1: JS_IMPORT_NAMESPACE_CLAUSE@77..104 0: TYPE_KW@77..82 "type" [] [Whitespace(" ")] - 1: JS_NAMESPACE_IMPORT_SPECIFIER@82..92 + 1: (empty) + 2: JS_NAMESPACE_IMPORT_SPECIFIER@82..92 0: STAR@82..84 "*" [] [Whitespace(" ")] 1: AS_KW@84..87 "as" [] [Whitespace(" ")] 2: JS_IDENTIFIER_BINDING@87..92 0: IDENT@87..92 "foo2" [] [Whitespace(" ")] - 2: FROM_KW@92..97 "from" [] [Whitespace(" ")] - 3: JS_MODULE_SOURCE@97..104 + 3: FROM_KW@92..97 "from" [] [Whitespace(" ")] + 4: JS_MODULE_SOURCE@97..104 0: JS_STRING_LITERAL@97..104 "\"./mod\"" [] [] - 4: (empty) + 5: (empty) 2: SEMICOLON@104..105 ";" [] [] 3: JS_IMPORT@105..138 0: IMPORT_KW@105..113 "import" [Newline("\n")] [Whitespace(" ")] diff --git a/crates/biome_js_syntax/src/generated/kind.rs b/crates/biome_js_syntax/src/generated/kind.rs index febf32803792..e2a38ce8c517 100644 --- a/crates/biome_js_syntax/src/generated/kind.rs +++ b/crates/biome_js_syntax/src/generated/kind.rs @@ -154,6 +154,7 @@ pub enum JsSyntaxKind { OF_KW, OUT_KW, USING_KW, + DEFER_KW, JS_NUMBER_LITERAL, JS_BIGINT_LITERAL, JS_STRING_LITERAL, @@ -665,6 +666,7 @@ impl JsSyntaxKind { "of" => OF_KW, "out" => OUT_KW, "using" => USING_KW, + "defer" => DEFER_KW, _ => return None, }; Some(kw) @@ -812,6 +814,7 @@ impl JsSyntaxKind { OF_KW => "of", OUT_KW => "out", USING_KW => "using", + DEFER_KW => "defer", JS_STRING_LITERAL => "string literal", _ => return None, }; @@ -820,4 +823,4 @@ impl JsSyntaxKind { } #[doc = r" Utility macro for creating a SyntaxKind through simple macro syntax"] #[macro_export] -macro_rules ! T { [;] => { $ crate :: JsSyntaxKind :: SEMICOLON } ; [,] => { $ crate :: JsSyntaxKind :: COMMA } ; ['('] => { $ crate :: JsSyntaxKind :: L_PAREN } ; [')'] => { $ crate :: JsSyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: JsSyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: JsSyntaxKind :: R_CURLY } ; ['['] => { $ crate :: JsSyntaxKind :: L_BRACK } ; [']'] => { $ crate :: JsSyntaxKind :: R_BRACK } ; [<] => { $ crate :: JsSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: JsSyntaxKind :: R_ANGLE } ; [~] => { $ crate :: JsSyntaxKind :: TILDE } ; [?] => { $ crate :: JsSyntaxKind :: QUESTION } ; [??] => { $ crate :: JsSyntaxKind :: QUESTION2 } ; [?.] => { $ crate :: JsSyntaxKind :: QUESTIONDOT } ; [&] => { $ crate :: JsSyntaxKind :: AMP } ; [|] => { $ crate :: JsSyntaxKind :: PIPE } ; [+] => { $ crate :: JsSyntaxKind :: PLUS } ; [++] => { $ crate :: JsSyntaxKind :: PLUS2 } ; [*] => { $ crate :: JsSyntaxKind :: STAR } ; [**] => { $ crate :: JsSyntaxKind :: STAR2 } ; [/] => { $ crate :: JsSyntaxKind :: SLASH } ; [^] => { $ crate :: JsSyntaxKind :: CARET } ; [%] => { $ crate :: JsSyntaxKind :: PERCENT } ; [.] => { $ crate :: JsSyntaxKind :: DOT } ; [...] => { $ crate :: JsSyntaxKind :: DOT3 } ; [:] => { $ crate :: JsSyntaxKind :: COLON } ; [=] => { $ crate :: JsSyntaxKind :: EQ } ; [==] => { $ crate :: JsSyntaxKind :: EQ2 } ; [===] => { $ crate :: JsSyntaxKind :: EQ3 } ; [=>] => { $ crate :: JsSyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: JsSyntaxKind :: BANG } ; [!=] => { $ crate :: JsSyntaxKind :: NEQ } ; [!==] => { $ crate :: JsSyntaxKind :: NEQ2 } ; [-] => { $ crate :: JsSyntaxKind :: MINUS } ; [--] => { $ crate :: JsSyntaxKind :: MINUS2 } ; [<=] => { $ crate :: JsSyntaxKind :: LTEQ } ; [>=] => { $ crate :: JsSyntaxKind :: GTEQ } ; [+=] => { $ crate :: JsSyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: JsSyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: JsSyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: JsSyntaxKind :: AMPEQ } ; [^=] => { $ crate :: JsSyntaxKind :: CARETEQ } ; [/=] => { $ crate :: JsSyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: JsSyntaxKind :: STAREQ } ; [%=] => { $ crate :: JsSyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: JsSyntaxKind :: AMP2 } ; [||] => { $ crate :: JsSyntaxKind :: PIPE2 } ; [<<] => { $ crate :: JsSyntaxKind :: SHL } ; [>>] => { $ crate :: JsSyntaxKind :: SHR } ; [>>>] => { $ crate :: JsSyntaxKind :: USHR } ; [<<=] => { $ crate :: JsSyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: JsSyntaxKind :: SHREQ } ; [>>>=] => { $ crate :: JsSyntaxKind :: USHREQ } ; [&&=] => { $ crate :: JsSyntaxKind :: AMP2EQ } ; [||=] => { $ crate :: JsSyntaxKind :: PIPE2EQ } ; [**=] => { $ crate :: JsSyntaxKind :: STAR2EQ } ; [??=] => { $ crate :: JsSyntaxKind :: QUESTION2EQ } ; [@] => { $ crate :: JsSyntaxKind :: AT } ; ['`'] => { $ crate :: JsSyntaxKind :: BACKTICK } ; [break] => { $ crate :: JsSyntaxKind :: BREAK_KW } ; [case] => { $ crate :: JsSyntaxKind :: CASE_KW } ; [catch] => { $ crate :: JsSyntaxKind :: CATCH_KW } ; [class] => { $ crate :: JsSyntaxKind :: CLASS_KW } ; [const] => { $ crate :: JsSyntaxKind :: CONST_KW } ; [continue] => { $ crate :: JsSyntaxKind :: CONTINUE_KW } ; [debugger] => { $ crate :: JsSyntaxKind :: DEBUGGER_KW } ; [default] => { $ crate :: JsSyntaxKind :: DEFAULT_KW } ; [delete] => { $ crate :: JsSyntaxKind :: DELETE_KW } ; [do] => { $ crate :: JsSyntaxKind :: DO_KW } ; [else] => { $ crate :: JsSyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: JsSyntaxKind :: ENUM_KW } ; [export] => { $ crate :: JsSyntaxKind :: EXPORT_KW } ; [extends] => { $ crate :: JsSyntaxKind :: EXTENDS_KW } ; [false] => { $ crate :: JsSyntaxKind :: FALSE_KW } ; [finally] => { $ crate :: JsSyntaxKind :: FINALLY_KW } ; [for] => { $ crate :: JsSyntaxKind :: FOR_KW } ; [function] => { $ crate :: JsSyntaxKind :: FUNCTION_KW } ; [if] => { $ crate :: JsSyntaxKind :: IF_KW } ; [in] => { $ crate :: JsSyntaxKind :: IN_KW } ; [instanceof] => { $ crate :: JsSyntaxKind :: INSTANCEOF_KW } ; [import] => { $ crate :: JsSyntaxKind :: IMPORT_KW } ; [new] => { $ crate :: JsSyntaxKind :: NEW_KW } ; [null] => { $ crate :: JsSyntaxKind :: NULL_KW } ; [return] => { $ crate :: JsSyntaxKind :: RETURN_KW } ; [super] => { $ crate :: JsSyntaxKind :: SUPER_KW } ; [switch] => { $ crate :: JsSyntaxKind :: SWITCH_KW } ; [this] => { $ crate :: JsSyntaxKind :: THIS_KW } ; [throw] => { $ crate :: JsSyntaxKind :: THROW_KW } ; [try] => { $ crate :: JsSyntaxKind :: TRY_KW } ; [true] => { $ crate :: JsSyntaxKind :: TRUE_KW } ; [typeof] => { $ crate :: JsSyntaxKind :: TYPEOF_KW } ; [var] => { $ crate :: JsSyntaxKind :: VAR_KW } ; [void] => { $ crate :: JsSyntaxKind :: VOID_KW } ; [while] => { $ crate :: JsSyntaxKind :: WHILE_KW } ; [with] => { $ crate :: JsSyntaxKind :: WITH_KW } ; [implements] => { $ crate :: JsSyntaxKind :: IMPLEMENTS_KW } ; [interface] => { $ crate :: JsSyntaxKind :: INTERFACE_KW } ; [let] => { $ crate :: JsSyntaxKind :: LET_KW } ; [package] => { $ crate :: JsSyntaxKind :: PACKAGE_KW } ; [private] => { $ crate :: JsSyntaxKind :: PRIVATE_KW } ; [protected] => { $ crate :: JsSyntaxKind :: PROTECTED_KW } ; [public] => { $ crate :: JsSyntaxKind :: PUBLIC_KW } ; [static] => { $ crate :: JsSyntaxKind :: STATIC_KW } ; [yield] => { $ crate :: JsSyntaxKind :: YIELD_KW } ; [abstract] => { $ crate :: JsSyntaxKind :: ABSTRACT_KW } ; [accessor] => { $ crate :: JsSyntaxKind :: ACCESSOR_KW } ; [as] => { $ crate :: JsSyntaxKind :: AS_KW } ; [satisfies] => { $ crate :: JsSyntaxKind :: SATISFIES_KW } ; [asserts] => { $ crate :: JsSyntaxKind :: ASSERTS_KW } ; [assert] => { $ crate :: JsSyntaxKind :: ASSERT_KW } ; [any] => { $ crate :: JsSyntaxKind :: ANY_KW } ; [async] => { $ crate :: JsSyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: JsSyntaxKind :: AWAIT_KW } ; [boolean] => { $ crate :: JsSyntaxKind :: BOOLEAN_KW } ; [constructor] => { $ crate :: JsSyntaxKind :: CONSTRUCTOR_KW } ; [declare] => { $ crate :: JsSyntaxKind :: DECLARE_KW } ; [get] => { $ crate :: JsSyntaxKind :: GET_KW } ; [infer] => { $ crate :: JsSyntaxKind :: INFER_KW } ; [is] => { $ crate :: JsSyntaxKind :: IS_KW } ; [keyof] => { $ crate :: JsSyntaxKind :: KEYOF_KW } ; [module] => { $ crate :: JsSyntaxKind :: MODULE_KW } ; [namespace] => { $ crate :: JsSyntaxKind :: NAMESPACE_KW } ; [never] => { $ crate :: JsSyntaxKind :: NEVER_KW } ; [readonly] => { $ crate :: JsSyntaxKind :: READONLY_KW } ; [require] => { $ crate :: JsSyntaxKind :: REQUIRE_KW } ; [number] => { $ crate :: JsSyntaxKind :: NUMBER_KW } ; [object] => { $ crate :: JsSyntaxKind :: OBJECT_KW } ; [set] => { $ crate :: JsSyntaxKind :: SET_KW } ; [string] => { $ crate :: JsSyntaxKind :: STRING_KW } ; [symbol] => { $ crate :: JsSyntaxKind :: SYMBOL_KW } ; [type] => { $ crate :: JsSyntaxKind :: TYPE_KW } ; [undefined] => { $ crate :: JsSyntaxKind :: UNDEFINED_KW } ; [unique] => { $ crate :: JsSyntaxKind :: UNIQUE_KW } ; [unknown] => { $ crate :: JsSyntaxKind :: UNKNOWN_KW } ; [from] => { $ crate :: JsSyntaxKind :: FROM_KW } ; [global] => { $ crate :: JsSyntaxKind :: GLOBAL_KW } ; [bigint] => { $ crate :: JsSyntaxKind :: BIGINT_KW } ; [override] => { $ crate :: JsSyntaxKind :: OVERRIDE_KW } ; [of] => { $ crate :: JsSyntaxKind :: OF_KW } ; [out] => { $ crate :: JsSyntaxKind :: OUT_KW } ; [using] => { $ crate :: JsSyntaxKind :: USING_KW } ; [ident] => { $ crate :: JsSyntaxKind :: IDENT } ; [EOF] => { $ crate :: JsSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: JsSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: JsSyntaxKind :: HASH } ; } +macro_rules ! T { [;] => { $ crate :: JsSyntaxKind :: SEMICOLON } ; [,] => { $ crate :: JsSyntaxKind :: COMMA } ; ['('] => { $ crate :: JsSyntaxKind :: L_PAREN } ; [')'] => { $ crate :: JsSyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: JsSyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: JsSyntaxKind :: R_CURLY } ; ['['] => { $ crate :: JsSyntaxKind :: L_BRACK } ; [']'] => { $ crate :: JsSyntaxKind :: R_BRACK } ; [<] => { $ crate :: JsSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: JsSyntaxKind :: R_ANGLE } ; [~] => { $ crate :: JsSyntaxKind :: TILDE } ; [?] => { $ crate :: JsSyntaxKind :: QUESTION } ; [??] => { $ crate :: JsSyntaxKind :: QUESTION2 } ; [?.] => { $ crate :: JsSyntaxKind :: QUESTIONDOT } ; [&] => { $ crate :: JsSyntaxKind :: AMP } ; [|] => { $ crate :: JsSyntaxKind :: PIPE } ; [+] => { $ crate :: JsSyntaxKind :: PLUS } ; [++] => { $ crate :: JsSyntaxKind :: PLUS2 } ; [*] => { $ crate :: JsSyntaxKind :: STAR } ; [**] => { $ crate :: JsSyntaxKind :: STAR2 } ; [/] => { $ crate :: JsSyntaxKind :: SLASH } ; [^] => { $ crate :: JsSyntaxKind :: CARET } ; [%] => { $ crate :: JsSyntaxKind :: PERCENT } ; [.] => { $ crate :: JsSyntaxKind :: DOT } ; [...] => { $ crate :: JsSyntaxKind :: DOT3 } ; [:] => { $ crate :: JsSyntaxKind :: COLON } ; [=] => { $ crate :: JsSyntaxKind :: EQ } ; [==] => { $ crate :: JsSyntaxKind :: EQ2 } ; [===] => { $ crate :: JsSyntaxKind :: EQ3 } ; [=>] => { $ crate :: JsSyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: JsSyntaxKind :: BANG } ; [!=] => { $ crate :: JsSyntaxKind :: NEQ } ; [!==] => { $ crate :: JsSyntaxKind :: NEQ2 } ; [-] => { $ crate :: JsSyntaxKind :: MINUS } ; [--] => { $ crate :: JsSyntaxKind :: MINUS2 } ; [<=] => { $ crate :: JsSyntaxKind :: LTEQ } ; [>=] => { $ crate :: JsSyntaxKind :: GTEQ } ; [+=] => { $ crate :: JsSyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: JsSyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: JsSyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: JsSyntaxKind :: AMPEQ } ; [^=] => { $ crate :: JsSyntaxKind :: CARETEQ } ; [/=] => { $ crate :: JsSyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: JsSyntaxKind :: STAREQ } ; [%=] => { $ crate :: JsSyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: JsSyntaxKind :: AMP2 } ; [||] => { $ crate :: JsSyntaxKind :: PIPE2 } ; [<<] => { $ crate :: JsSyntaxKind :: SHL } ; [>>] => { $ crate :: JsSyntaxKind :: SHR } ; [>>>] => { $ crate :: JsSyntaxKind :: USHR } ; [<<=] => { $ crate :: JsSyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: JsSyntaxKind :: SHREQ } ; [>>>=] => { $ crate :: JsSyntaxKind :: USHREQ } ; [&&=] => { $ crate :: JsSyntaxKind :: AMP2EQ } ; [||=] => { $ crate :: JsSyntaxKind :: PIPE2EQ } ; [**=] => { $ crate :: JsSyntaxKind :: STAR2EQ } ; [??=] => { $ crate :: JsSyntaxKind :: QUESTION2EQ } ; [@] => { $ crate :: JsSyntaxKind :: AT } ; ['`'] => { $ crate :: JsSyntaxKind :: BACKTICK } ; [break] => { $ crate :: JsSyntaxKind :: BREAK_KW } ; [case] => { $ crate :: JsSyntaxKind :: CASE_KW } ; [catch] => { $ crate :: JsSyntaxKind :: CATCH_KW } ; [class] => { $ crate :: JsSyntaxKind :: CLASS_KW } ; [const] => { $ crate :: JsSyntaxKind :: CONST_KW } ; [continue] => { $ crate :: JsSyntaxKind :: CONTINUE_KW } ; [debugger] => { $ crate :: JsSyntaxKind :: DEBUGGER_KW } ; [default] => { $ crate :: JsSyntaxKind :: DEFAULT_KW } ; [delete] => { $ crate :: JsSyntaxKind :: DELETE_KW } ; [do] => { $ crate :: JsSyntaxKind :: DO_KW } ; [else] => { $ crate :: JsSyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: JsSyntaxKind :: ENUM_KW } ; [export] => { $ crate :: JsSyntaxKind :: EXPORT_KW } ; [extends] => { $ crate :: JsSyntaxKind :: EXTENDS_KW } ; [false] => { $ crate :: JsSyntaxKind :: FALSE_KW } ; [finally] => { $ crate :: JsSyntaxKind :: FINALLY_KW } ; [for] => { $ crate :: JsSyntaxKind :: FOR_KW } ; [function] => { $ crate :: JsSyntaxKind :: FUNCTION_KW } ; [if] => { $ crate :: JsSyntaxKind :: IF_KW } ; [in] => { $ crate :: JsSyntaxKind :: IN_KW } ; [instanceof] => { $ crate :: JsSyntaxKind :: INSTANCEOF_KW } ; [import] => { $ crate :: JsSyntaxKind :: IMPORT_KW } ; [new] => { $ crate :: JsSyntaxKind :: NEW_KW } ; [null] => { $ crate :: JsSyntaxKind :: NULL_KW } ; [return] => { $ crate :: JsSyntaxKind :: RETURN_KW } ; [super] => { $ crate :: JsSyntaxKind :: SUPER_KW } ; [switch] => { $ crate :: JsSyntaxKind :: SWITCH_KW } ; [this] => { $ crate :: JsSyntaxKind :: THIS_KW } ; [throw] => { $ crate :: JsSyntaxKind :: THROW_KW } ; [try] => { $ crate :: JsSyntaxKind :: TRY_KW } ; [true] => { $ crate :: JsSyntaxKind :: TRUE_KW } ; [typeof] => { $ crate :: JsSyntaxKind :: TYPEOF_KW } ; [var] => { $ crate :: JsSyntaxKind :: VAR_KW } ; [void] => { $ crate :: JsSyntaxKind :: VOID_KW } ; [while] => { $ crate :: JsSyntaxKind :: WHILE_KW } ; [with] => { $ crate :: JsSyntaxKind :: WITH_KW } ; [implements] => { $ crate :: JsSyntaxKind :: IMPLEMENTS_KW } ; [interface] => { $ crate :: JsSyntaxKind :: INTERFACE_KW } ; [let] => { $ crate :: JsSyntaxKind :: LET_KW } ; [package] => { $ crate :: JsSyntaxKind :: PACKAGE_KW } ; [private] => { $ crate :: JsSyntaxKind :: PRIVATE_KW } ; [protected] => { $ crate :: JsSyntaxKind :: PROTECTED_KW } ; [public] => { $ crate :: JsSyntaxKind :: PUBLIC_KW } ; [static] => { $ crate :: JsSyntaxKind :: STATIC_KW } ; [yield] => { $ crate :: JsSyntaxKind :: YIELD_KW } ; [abstract] => { $ crate :: JsSyntaxKind :: ABSTRACT_KW } ; [accessor] => { $ crate :: JsSyntaxKind :: ACCESSOR_KW } ; [as] => { $ crate :: JsSyntaxKind :: AS_KW } ; [satisfies] => { $ crate :: JsSyntaxKind :: SATISFIES_KW } ; [asserts] => { $ crate :: JsSyntaxKind :: ASSERTS_KW } ; [assert] => { $ crate :: JsSyntaxKind :: ASSERT_KW } ; [any] => { $ crate :: JsSyntaxKind :: ANY_KW } ; [async] => { $ crate :: JsSyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: JsSyntaxKind :: AWAIT_KW } ; [boolean] => { $ crate :: JsSyntaxKind :: BOOLEAN_KW } ; [constructor] => { $ crate :: JsSyntaxKind :: CONSTRUCTOR_KW } ; [declare] => { $ crate :: JsSyntaxKind :: DECLARE_KW } ; [get] => { $ crate :: JsSyntaxKind :: GET_KW } ; [infer] => { $ crate :: JsSyntaxKind :: INFER_KW } ; [is] => { $ crate :: JsSyntaxKind :: IS_KW } ; [keyof] => { $ crate :: JsSyntaxKind :: KEYOF_KW } ; [module] => { $ crate :: JsSyntaxKind :: MODULE_KW } ; [namespace] => { $ crate :: JsSyntaxKind :: NAMESPACE_KW } ; [never] => { $ crate :: JsSyntaxKind :: NEVER_KW } ; [readonly] => { $ crate :: JsSyntaxKind :: READONLY_KW } ; [require] => { $ crate :: JsSyntaxKind :: REQUIRE_KW } ; [number] => { $ crate :: JsSyntaxKind :: NUMBER_KW } ; [object] => { $ crate :: JsSyntaxKind :: OBJECT_KW } ; [set] => { $ crate :: JsSyntaxKind :: SET_KW } ; [string] => { $ crate :: JsSyntaxKind :: STRING_KW } ; [symbol] => { $ crate :: JsSyntaxKind :: SYMBOL_KW } ; [type] => { $ crate :: JsSyntaxKind :: TYPE_KW } ; [undefined] => { $ crate :: JsSyntaxKind :: UNDEFINED_KW } ; [unique] => { $ crate :: JsSyntaxKind :: UNIQUE_KW } ; [unknown] => { $ crate :: JsSyntaxKind :: UNKNOWN_KW } ; [from] => { $ crate :: JsSyntaxKind :: FROM_KW } ; [global] => { $ crate :: JsSyntaxKind :: GLOBAL_KW } ; [bigint] => { $ crate :: JsSyntaxKind :: BIGINT_KW } ; [override] => { $ crate :: JsSyntaxKind :: OVERRIDE_KW } ; [of] => { $ crate :: JsSyntaxKind :: OF_KW } ; [out] => { $ crate :: JsSyntaxKind :: OUT_KW } ; [using] => { $ crate :: JsSyntaxKind :: USING_KW } ; [defer] => { $ crate :: JsSyntaxKind :: DEFER_KW } ; [ident] => { $ crate :: JsSyntaxKind :: IDENT } ; [EOF] => { $ crate :: JsSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: JsSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: JsSyntaxKind :: HASH } ; } diff --git a/crates/biome_js_syntax/src/generated/nodes.rs b/crates/biome_js_syntax/src/generated/nodes.rs index 7486a3b58eb5..1472a013c63b 100644 --- a/crates/biome_js_syntax/src/generated/nodes.rs +++ b/crates/biome_js_syntax/src/generated/nodes.rs @@ -3900,6 +3900,7 @@ impl JsImportNamespaceClause { pub fn as_fields(&self) -> JsImportNamespaceClauseFields { JsImportNamespaceClauseFields { type_token: self.type_token(), + defer_token: self.defer_token(), namespace_specifier: self.namespace_specifier(), from_token: self.from_token(), source: self.source(), @@ -3909,17 +3910,20 @@ impl JsImportNamespaceClause { pub fn type_token(&self) -> Option { support::token(&self.syntax, 0usize) } + pub fn defer_token(&self) -> Option { + support::token(&self.syntax, 1usize) + } pub fn namespace_specifier(&self) -> SyntaxResult { - support::required_node(&self.syntax, 1usize) + support::required_node(&self.syntax, 2usize) } pub fn from_token(&self) -> SyntaxResult { - support::required_token(&self.syntax, 2usize) + support::required_token(&self.syntax, 3usize) } pub fn source(&self) -> SyntaxResult { - support::required_node(&self.syntax, 3usize) + support::required_node(&self.syntax, 4usize) } pub fn assertion(&self) -> Option { - support::node(&self.syntax, 4usize) + support::node(&self.syntax, 5usize) } } impl Serialize for JsImportNamespaceClause { @@ -3933,6 +3937,7 @@ impl Serialize for JsImportNamespaceClause { #[derive(Serialize)] pub struct JsImportNamespaceClauseFields { pub type_token: Option, + pub defer_token: Option, pub namespace_specifier: SyntaxResult, pub from_token: SyntaxResult, pub source: SyntaxResult, @@ -19954,6 +19959,10 @@ impl std::fmt::Debug for JsImportNamespaceClause { "type_token", &support::DebugOptionalElement(self.type_token()), ) + .field( + "defer_token", + &support::DebugOptionalElement(self.defer_token()), + ) .field( "namespace_specifier", &support::DebugSyntaxResult(self.namespace_specifier()), diff --git a/crates/biome_js_syntax/src/generated/nodes_mut.rs b/crates/biome_js_syntax/src/generated/nodes_mut.rs index 3416d6adc2b5..434826ab35ae 100644 --- a/crates/biome_js_syntax/src/generated/nodes_mut.rs +++ b/crates/biome_js_syntax/src/generated/nodes_mut.rs @@ -1961,27 +1961,33 @@ impl JsImportNamespaceClause { .splice_slots(0usize..=0usize, once(element.map(|element| element.into()))), ) } + pub fn with_defer_token(self, element: Option) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(element.map(|element| element.into()))), + ) + } pub fn with_namespace_specifier(self, element: JsNamespaceImportSpecifier) -> Self { Self::unwrap_cast( self.syntax - .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), ) } pub fn with_from_token(self, element: SyntaxToken) -> Self { Self::unwrap_cast( self.syntax - .splice_slots(2usize..=2usize, once(Some(element.into()))), + .splice_slots(3usize..=3usize, once(Some(element.into()))), ) } pub fn with_source(self, element: AnyJsModuleSource) -> Self { Self::unwrap_cast( self.syntax - .splice_slots(3usize..=3usize, once(Some(element.into_syntax().into()))), + .splice_slots(4usize..=4usize, once(Some(element.into_syntax().into()))), ) } pub fn with_assertion(self, element: Option) -> Self { Self::unwrap_cast(self.syntax.splice_slots( - 4usize..=4usize, + 5usize..=5usize, once(element.map(|element| element.into_syntax().into())), )) } diff --git a/xtask/codegen/js.ungram b/xtask/codegen/js.ungram index d91649f3b712..219e6bddb010 100644 --- a/xtask/codegen/js.ungram +++ b/xtask/codegen/js.ungram @@ -1252,6 +1252,7 @@ JsImportDefaultClause = // import type * as foo from "mod"; JsImportNamespaceClause = 'type'? + 'defer'? namespace_specifier: JsNamespaceImportSpecifier 'from' source: AnyJsModuleSource diff --git a/xtask/codegen/src/js_kinds_src.rs b/xtask/codegen/src/js_kinds_src.rs index 09f05a304392..362eb4889a6d 100644 --- a/xtask/codegen/src/js_kinds_src.rs +++ b/xtask/codegen/src/js_kinds_src.rs @@ -155,6 +155,7 @@ pub const JS_KINDS_SRC: KindsSrc = KindsSrc { "of", "out", "using", + "defer", ], literals: &[ "JS_NUMBER_LITERAL",