diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index cda7501507f24..2721f640cefb1 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -169,6 +169,14 @@ pub fn class_declaration(span: Span) -> OxcDiagnostic { .with_label(span) } +/// A class member cannot have the 'const' keyword. ts(1248) +#[cold] +pub fn const_class_member(span: Span) -> OxcDiagnostic { + ts_error("1248", "A class member cannot have the 'const' keyword.") + .with_help("Did you mean `readonly`?") + .with_label(span) +} + #[cold] pub fn binding_rest_element_last(span: Span) -> OxcDiagnostic { OxcDiagnostic::error("A rest element must be last in a destructuring pattern").with_label(span) diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index e44f0e44a26cc..d8ed536cf7bb4 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -185,7 +185,7 @@ impl<'a> ParserImpl<'a> { let span = self.start_span(); - let modifiers = self.parse_modifiers(true, false, true); + let modifiers = self.parse_modifiers(true, true, true); let mut kind = MethodDefinitionKind::Method; let mut generator = false; @@ -277,6 +277,10 @@ impl<'a> ParserImpl<'a> { self.error(diagnostics::optional_definite_property(optional_span.expand_right(1))); } + if modifiers.contains(ModifierKind::Const) { + self.error(diagnostics::const_class_member(key.span())); + } + if let PropertyKey::PrivateIdentifier(private_ident) = &key { // `private #foo`, etc. is illegal if self.ts_enabled() { diff --git a/tasks/coverage/snapshots/parser_misc.snap b/tasks/coverage/snapshots/parser_misc.snap index 8a34c3d7cc708..8944a566e3b05 100644 --- a/tasks/coverage/snapshots/parser_misc.snap +++ b/tasks/coverage/snapshots/parser_misc.snap @@ -165,10 +165,17 @@ Negative Passed: 20/20 (100.00%) ╰──── help: Try insert a semicolon here + × TS(1248): A class member cannot have the 'const' keyword. + ╭─[misc/fail/oxc-4212-1.ts:1:17] + 1 │ class a { const enum b(); } + · ──── + ╰──── + help: Did you mean `readonly`? + × Expected a semicolon or an implicit semicolon after a statement, but found none - ╭─[misc/fail/oxc-4212-1.ts:1:16] + ╭─[misc/fail/oxc-4212-1.ts:1:21] 1 │ class a { const enum b(); } - · ▲ + · ▲ ╰──── help: Try insert a semicolon here diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index 83ae2767f35f0..dc5ed72ff1b9f 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -4730,23 +4730,32 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private · ──────────────── ╰──── + × TS(1248): A class member cannot have the 'const' keyword. + ╭─[typescript/tests/cases/compiler/ClassDeclaration26.ts:2:18] + 1 │ class C { + 2 │ public const var export foo = 10; + · ─── + 3 │ + ╰──── + help: Did you mean `readonly`? + × Expected a semicolon or an implicit semicolon after a statement, but found none - ╭─[typescript/tests/cases/compiler/ClassDeclaration26.ts:2:17] + ╭─[typescript/tests/cases/compiler/ClassDeclaration26.ts:2:21] 1 │ class C { 2 │ public const var export foo = 10; - · ▲ + · ▲ 3 │ ╰──── help: Try insert a semicolon here - × Expected a semicolon or an implicit semicolon after a statement, but found none - ╭─[typescript/tests/cases/compiler/ClassDeclarationWithInvalidConstOnPropertyDeclaration.ts:2:15] + × TS(1248): A class member cannot have the 'const' keyword. + ╭─[typescript/tests/cases/compiler/ClassDeclarationWithInvalidConstOnPropertyDeclaration.ts:2:16] 1 │ class AtomicNumbers { 2 │ static const H = 1; - · ▲ + · ─ 3 │ } ╰──── - help: Try insert a semicolon here + help: Did you mean `readonly`? × A parameter property is only allowed in a constructor implementation. ╭─[typescript/tests/cases/compiler/MemberAccessorDeclaration15.ts:2:12] @@ -6597,14 +6606,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 19 │ const c5 = 0; ╰──── - × Expected a semicolon or an implicit semicolon after a statement, but found none - ╭─[typescript/tests/cases/compiler/constInClassExpression.ts:2:10] + × TS(1248): A class member cannot have the 'const' keyword. + ╭─[typescript/tests/cases/compiler/constInClassExpression.ts:2:11] 1 │ let C = class { 2 │ const a = 4; - · ▲ + · ─ 3 │ }; ╰──── - help: Try insert a semicolon here + help: Did you mean `readonly`? × TS(1090): 'static' modifier cannot appear on a parameter. ╭─[typescript/tests/cases/compiler/constructorArgsErrors1.ts:2:18]