From ceea5031fac70ec9a9fd174c0250b536992d14d2 Mon Sep 17 00:00:00 2001 From: Don Isaac Date: Sat, 24 Aug 2024 16:34:43 -0400 Subject: [PATCH] feat(parser): report errors on optional accessor properties --- crates/oxc_parser/src/diagnostics.rs | 5 +++++ crates/oxc_parser/src/js/class.rs | 11 ++++++++++- tasks/coverage/parser_babel.snap | 8 ++++++++ tasks/coverage/parser_misc.snap | 11 +++++++++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index 6d5157e186abbb..0a3a13487c38c7 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -249,6 +249,11 @@ pub fn constructor_async(span0: Span) -> OxcDiagnostic { OxcDiagnostic::error("Constructor can't be an async method").with_label(span0) } +#[cold] +pub fn optional_accessor_property(span: Span) -> OxcDiagnostic { + ts_error("1276", "An 'accessor' property cannot be declared optional.").with_label(span) +} + #[cold] pub fn identifier_async(x0: &str, span1: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("Cannot use `{x0}` as an identifier in an async context")) diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index 427cd51ef2f5fe..f32e457767628d 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -263,7 +263,13 @@ impl<'a> ParserImpl<'a> { let (key, computed) = if let Some(result) = key_name { result } else { self.parse_class_element_name()? }; - let optional = self.eat(Kind::Question); + let (optional, optional_span) = if self.at(Kind::Question) { + let span = self.start_span(); + self.bump_any(); + (true, self.end_span(span)) + } else { + (false, oxc_span::SPAN) + }; let definite = self.eat(Kind::Bang); if let PropertyKey::PrivateIdentifier(private_ident) = &key { @@ -281,6 +287,9 @@ impl<'a> ParserImpl<'a> { } if accessor { + if optional { + self.error(diagnostics::optional_accessor_property(optional_span)); + } self.parse_class_accessor_property(span, key, computed, r#static, r#abstract).map(Some) } else if self.at(Kind::LParen) || self.at(Kind::LAngle) || r#async || generator { // LAngle for start of type parameters `foo` diff --git a/tasks/coverage/parser_babel.snap b/tasks/coverage/parser_babel.snap index be2ffb6142be26..490c721250f17c 100644 --- a/tasks/coverage/parser_babel.snap +++ b/tasks/coverage/parser_babel.snap @@ -10067,6 +10067,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc 4 │ ╰──── + × TS(1276): An 'accessor' property cannot be declared optional. + ╭─[babel/packages/babel-parser/test/fixtures/typescript/class/accessor-invalid/input.ts:7:14] + 6 │ abstract accessor #s; + 7 │ accessor #d?; + · ─ + 8 │ abstract accessor f = 1; + ╰──── + × Expected a semicolon or an implicit semicolon after a statement, but found none ╭─[babel/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/input.ts:1:8] 1 │ declare abstract diff --git a/tasks/coverage/parser_misc.snap b/tasks/coverage/parser_misc.snap index 79f3a915d44c8c..6ee26030e24f6d 100644 --- a/tasks/coverage/parser_misc.snap +++ b/tasks/coverage/parser_misc.snap @@ -1,8 +1,7 @@ parser_misc Summary: AST Parsed : 27/27 (100.00%) Positive Passed: 27/27 (100.00%) -Negative Passed: 15/16 (93.75%) -Expect Syntax Error: tasks/coverage/misc/fail/oxc-5177.ts +Negative Passed: 16/16 (100.00%) × Unexpected token ╭─[misc/fail/oxc-169.js:2:1] @@ -231,6 +230,14 @@ Expect Syntax Error: tasks/coverage/misc/fail/oxc-5177.ts 3 │ } ╰──── + × TS(1276): An 'accessor' property cannot be declared optional. + ╭─[misc/fail/oxc-5177.ts:4:15] + 3 │ export class Bang { + 4 │ accessor x?: Foo + · ─ + 5 │ } + ╰──── + × The keyword 'let' is reserved ╭─[misc/fail/oxc.js:1:1] 1 │ let.a = 1;