Skip to content

Commit

Permalink
feat(biome_js_parser): support defer attribute in import statements
Browse files Browse the repository at this point in the history
  • Loading branch information
fireairforce committed Oct 15, 2024
1 parent 561b54c commit a1d1c91
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 23 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down
7 changes: 7 additions & 0 deletions crates/biome_js_factory/src/generated/node_factory.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion crates/biome_js_factory/src/generated/syntax_factory.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ impl FormatNodeRule<JsImportNamespaceClause> for FormatJsImportNamespaceClause {
type_token,
namespace_specifier,
from_token,
defer_token,
source,
assertion,
} = node.as_fields();

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,
Expand Down
1 change: 1 addition & 0 deletions crates/biome_js_parser/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
}
}
Expand Down
22 changes: 22 additions & 0 deletions crates/biome_js_parser/src/syntax/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_js_parser/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 8 additions & 4 deletions crates/biome_js_parser/test_data/inline/err/import_err.rast
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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(" ")],
Expand Down Expand Up @@ -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(" ")]
Expand Down
10 changes: 6 additions & 4 deletions crates/biome_js_parser/test_data/inline/ok/import_decl.rast
Original file line number Diff line number Diff line change
Expand Up @@ -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(" ")],
Expand Down Expand Up @@ -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")] []
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import defer * as yNamespace from "y";
Original file line number Diff line number Diff line change
@@ -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")] []
Original file line number Diff line number Diff line change
Expand Up @@ -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(" ")],
Expand Down Expand Up @@ -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(" ")]
Expand Down
Loading

0 comments on commit a1d1c91

Please sign in to comment.