Skip to content

Commit

Permalink
refactor(parser): provide better error messages for const modifiers…
Browse files Browse the repository at this point in the history
… on class elements (#6353)

Quality-of-life improvement for invalid `const` modifiers on class elements. Instead of panicking, the parser will eat `const` and report it as an error.

```ts
class C {
  static const H = 1;
}
```
  • Loading branch information
DonIsaac committed Oct 8, 2024
1 parent 6159560 commit 3b53dd4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 13 deletions.
8 changes: 8 additions & 0 deletions crates/oxc_parser/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion crates/oxc_parser/src/js/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down
11 changes: 9 additions & 2 deletions tasks/coverage/snapshots/parser_misc.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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]
1class a { const enum b(); }
· ▲
·
╰────
help: Try insert a semicolon here

Expand Down
29 changes: 19 additions & 10 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit 3b53dd4

Please sign in to comment.