From 840279a2715c59e620604d4010d1b02442597d04 Mon Sep 17 00:00:00 2001 From: zoomdong <1344492820@qq.com> Date: Tue, 9 Dec 2025 02:00:35 +0800 Subject: [PATCH 1/3] fix(parser): allow async as class member name --- crates/biome_js_parser/src/syntax/class.rs | 1 + .../ts_class_memeber_named_async_is_valid.ts | 3 + ...class_memeber_named_async_is_valid.ts.snap | 102 ++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts create mode 100644 crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts.snap diff --git a/crates/biome_js_parser/src/syntax/class.rs b/crates/biome_js_parser/src/syntax/class.rs index 2c337db6db53..6e29c8e1f405 100644 --- a/crates/biome_js_parser/src/syntax/class.rs +++ b/crates/biome_js_parser/src/syntax/class.rs @@ -662,6 +662,7 @@ fn parse_class_member_impl( && !p.nth_at(1, T![?]) && !p.nth_at(1, T![;]) && !p.nth_at(1, T![=]) + && !p.nth_at(1, T![:]) && !is_at_method_class_member(p, 1) && !p.has_nth_preceding_line_break(1) { diff --git a/crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts b/crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts new file mode 100644 index 000000000000..42c4aaab63ee --- /dev/null +++ b/crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts @@ -0,0 +1,3 @@ +class Connection { + public async: boolean = false; +} \ No newline at end of file diff --git a/crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts.snap b/crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts.snap new file mode 100644 index 000000000000..f8db5867433e --- /dev/null +++ b/crates/biome_js_parser/tests/js_test_suite/ok/ts_class_memeber_named_async_is_valid.ts.snap @@ -0,0 +1,102 @@ +--- +source: crates/biome_js_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```ts +class Connection { + public async: boolean = false; +} +``` + + +## AST + +``` +JsModule { + bom_token: missing (optional), + interpreter_token: missing (optional), + directives: JsDirectiveList [], + items: JsModuleItemList [ + JsClassDeclaration { + decorators: JsDecoratorList [], + abstract_token: missing (optional), + class_token: CLASS_KW@0..6 "class" [] [Whitespace(" ")], + id: JsIdentifierBinding { + name_token: IDENT@6..17 "Connection" [] [Whitespace(" ")], + }, + type_parameters: missing (optional), + extends_clause: missing (optional), + implements_clause: missing (optional), + l_curly_token: L_CURLY@17..18 "{" [] [], + members: JsClassMemberList [ + JsPropertyClassMember { + modifiers: JsPropertyModifierList [ + TsAccessibilityModifier { + modifier_token: PUBLIC_KW@18..30 "public" [Newline("\n"), Whitespace(" ")] [Whitespace(" ")], + }, + ], + name: JsLiteralMemberName { + value: IDENT@30..35 "async" [] [], + }, + property_annotation: TsTypeAnnotation { + colon_token: COLON@35..37 ":" [] [Whitespace(" ")], + ty: TsBooleanType { + boolean_token: BOOLEAN_KW@37..45 "boolean" [] [Whitespace(" ")], + }, + }, + value: JsInitializerClause { + eq_token: EQ@45..47 "=" [] [Whitespace(" ")], + expression: JsBooleanLiteralExpression { + value_token: FALSE_KW@47..52 "false" [] [], + }, + }, + semicolon_token: SEMICOLON@52..53 ";" [] [], + }, + ], + r_curly_token: R_CURLY@53..55 "}" [Newline("\n")] [], + }, + ], + eof_token: EOF@55..55 "" [] [], +} +``` + +## CST + +``` +0: JS_MODULE@0..55 + 0: (empty) + 1: (empty) + 2: JS_DIRECTIVE_LIST@0..0 + 3: JS_MODULE_ITEM_LIST@0..55 + 0: JS_CLASS_DECLARATION@0..55 + 0: JS_DECORATOR_LIST@0..0 + 1: (empty) + 2: CLASS_KW@0..6 "class" [] [Whitespace(" ")] + 3: JS_IDENTIFIER_BINDING@6..17 + 0: IDENT@6..17 "Connection" [] [Whitespace(" ")] + 4: (empty) + 5: (empty) + 6: (empty) + 7: L_CURLY@17..18 "{" [] [] + 8: JS_CLASS_MEMBER_LIST@18..53 + 0: JS_PROPERTY_CLASS_MEMBER@18..53 + 0: JS_PROPERTY_MODIFIER_LIST@18..30 + 0: TS_ACCESSIBILITY_MODIFIER@18..30 + 0: PUBLIC_KW@18..30 "public" [Newline("\n"), Whitespace(" ")] [Whitespace(" ")] + 1: JS_LITERAL_MEMBER_NAME@30..35 + 0: IDENT@30..35 "async" [] [] + 2: TS_TYPE_ANNOTATION@35..45 + 0: COLON@35..37 ":" [] [Whitespace(" ")] + 1: TS_BOOLEAN_TYPE@37..45 + 0: BOOLEAN_KW@37..45 "boolean" [] [Whitespace(" ")] + 3: JS_INITIALIZER_CLAUSE@45..52 + 0: EQ@45..47 "=" [] [Whitespace(" ")] + 1: JS_BOOLEAN_LITERAL_EXPRESSION@47..52 + 0: FALSE_KW@47..52 "false" [] [] + 4: SEMICOLON@52..53 ";" [] [] + 9: R_CURLY@53..55 "}" [Newline("\n")] [] + 4: EOF@55..55 "" [] [] + +``` From 0bd1297929c356263572d4ae07593e00a6374cfa Mon Sep 17 00:00:00 2001 From: zoomdong <1344492820@qq.com> Date: Tue, 9 Dec 2025 02:03:21 +0800 Subject: [PATCH 2/3] fix(parser): allow async as class member name --- .changeset/short-adults-join.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/short-adults-join.md diff --git a/.changeset/short-adults-join.md b/.changeset/short-adults-join.md new file mode 100644 index 000000000000..701f85d788d7 --- /dev/null +++ b/.changeset/short-adults-join.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#7826](https://github.com/biomejs/biome/issues/7826), when class memeber name is `async`, parser should not throw error. From ee43765a3de356b53c4e28b9c1be3298b0785879 Mon Sep 17 00:00:00 2001 From: zoomdong <1344492820@qq.com> Date: Tue, 9 Dec 2025 02:10:14 +0800 Subject: [PATCH 3/3] update md --- .changeset/short-adults-join.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/short-adults-join.md b/.changeset/short-adults-join.md index 701f85d788d7..65a56616b9ae 100644 --- a/.changeset/short-adults-join.md +++ b/.changeset/short-adults-join.md @@ -2,4 +2,4 @@ "@biomejs/biome": patch --- -Fixed [#7826](https://github.com/biomejs/biome/issues/7826), when class memeber name is `async`, parser should not throw error. +Fixed [#7826](https://github.com/biomejs/biome/issues/7826), where a class member named `async` will not cause the parse error.