From c4132fb3b5242454c056723d7978b92b653c869b Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 22 Jan 2026 08:44:50 +0000 Subject: [PATCH] fix(parser): validate accessor parameters in interface method signatures (#18391) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Add validation for getter/setter accessor parameters in TypeScript interface method signatures: - A 'get' accessor cannot have parameters (TS1054) - A 'set' accessor must have exactly one parameter (TS1049) - A 'set' accessor cannot have an optional parameter (TS1051) - A 'set' accessor cannot have rest parameter (TS1053) - 'get' and 'set' accessors cannot declare 'this' parameters (TS2784) This fixes 5 failing Babel conformance tests: - `interface/get-set-invalid-optional-parameter` - `interface/get-set-invalid-parameters` - `interface/get-set-invalid-reset-parameter` - `interface/get-set-invalid-reset-parameter-babel-7` - `interface/get-set-invalid-this-parameters` ๐Ÿค– Generated with [Claude Code](https://claude.ai/code) --- crates/oxc_parser/src/diagnostics.rs | 10 +++ crates/oxc_parser/src/ts/types.rs | 39 +++++++-- tasks/coverage/snapshots/parser_babel.snap | 97 +++++++++++++++++++--- 3 files changed, 129 insertions(+), 17 deletions(-) diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index 323f42e078f37..08e8f352ce860 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -1144,6 +1144,16 @@ pub fn getter_parameters(span: Span) -> OxcDiagnostic { .with_help("Remove these parameters here") } +#[cold] +pub fn setter_with_optional_parameter(span: Span) -> OxcDiagnostic { + ts_error("1051", "A 'set' accessor cannot have an optional parameter.").with_label(span) +} + +#[cold] +pub fn accessor_cannot_have_this_parameter(span: Span) -> OxcDiagnostic { + ts_error("2784", "'get' and 'set' accessors cannot declare 'this' parameters.").with_label(span) +} + #[cold] pub fn variable_declarator_definite(span: Span) -> OxcDiagnostic { ts_error( diff --git a/crates/oxc_parser/src/ts/types.rs b/crates/oxc_parser/src/ts/types.rs index 8dbea2c9fe66e..5879d829392e2 100644 --- a/crates/oxc_parser/src/ts/types.rs +++ b/crates/oxc_parser/src/ts/types.rs @@ -1213,13 +1213,40 @@ impl<'a> ParserImpl<'a> { self.parse_formal_parameters(FunctionKind::Declaration, FormalParameterKind::Signature); let return_type = self.parse_ts_return_type_annotation(); self.parse_type_member_semicolon(); - if kind == TSMethodSignatureKind::Set - && let Some(return_type) = return_type.as_ref() - { - self.error(diagnostics::a_set_accessor_cannot_have_a_return_type_annotation( - return_type.span, - )); + + if let Some(this_param) = &this_param { + self.error(diagnostics::accessor_cannot_have_this_parameter(this_param.span)); + } + + match kind { + TSMethodSignatureKind::Get => { + if !params.items.is_empty() { + self.error(diagnostics::getter_parameters(params.span)); + } + } + TSMethodSignatureKind::Set => { + if let Some(return_type) = return_type.as_ref() { + self.error(diagnostics::a_set_accessor_cannot_have_a_return_type_annotation( + return_type.span, + )); + } + if let Some(rest) = ¶ms.rest { + self.error(diagnostics::setter_with_rest_parameter(rest.span)); + } + if params.items.len() != 1 { + self.error(diagnostics::setter_with_parameters( + params.span, + params.items.len(), + )); + } else if let Some(param) = params.items.first() + && param.optional + { + self.error(diagnostics::setter_with_optional_parameter(param.span)); + } + } + TSMethodSignatureKind::Method => {} } + self.ast.ts_signature_method_signature( self.end_span(span), key, diff --git a/tasks/coverage/snapshots/parser_babel.snap b/tasks/coverage/snapshots/parser_babel.snap index a56000c1eed28..9c4fc6ab7ceeb 100644 --- a/tasks/coverage/snapshots/parser_babel.snap +++ b/tasks/coverage/snapshots/parser_babel.snap @@ -3,7 +3,7 @@ commit: fc58af40 parser_babel Summary: AST Parsed : 2217/2223 (99.73%) Positive Passed: 2204/2223 (99.15%) -Negative Passed: 1649/1689 (97.63%) +Negative Passed: 1654/1689 (97.93%) Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/invalid-for-using-of-no-initializer/input.js Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts @@ -56,16 +56,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/ty Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/input.ts -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-optional-parameter/input.ts - -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-parameters/input.ts - -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-reset-parameter/input.ts - -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-reset-parameter-babel-7/input.ts - -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-this-parameters/input.ts - Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/module-namespace/module-identifier-invalid/input.ts Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/regression/keyword-qualified-type-2/input.ts @@ -13323,6 +13313,66 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ยท โ”€ โ•ฐโ”€โ”€โ”€โ”€ + ร— TS(1051): A 'set' accessor cannot have an optional parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-optional-parameter/input.ts:2:11] + 1 โ”‚ interface Foo { + 2 โ”‚ set bar(foo?: string); + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + 3 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + + ร— A 'get' accessor must not have any formal parameters. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-parameters/input.ts:2:10] + 1 โ”‚ interface Foo { + 2 โ”‚ get foo(param): string; + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + 3 โ”‚ set foo(); + โ•ฐโ”€โ”€โ”€โ”€ + help: Remove these parameters here + + ร— A 'set' accessor must have exactly one parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-parameters/input.ts:3:10] + 2 โ”‚ get foo(param): string; + 3 โ”‚ set foo(); + ยท โ”€โ”€ + 4 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + help: Add a parameter here + + ร— A 'set' accessor cannot have rest parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-reset-parameter/input.ts:2:11] + 1 โ”‚ interface Foo { + 2 โ”‚ set bar(...v); + ยท โ”€โ”€โ”€โ”€ + 3 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + + ร— A 'set' accessor must have exactly one parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-reset-parameter/input.ts:2:10] + 1 โ”‚ interface Foo { + 2 โ”‚ set bar(...v); + ยท โ”€โ”€โ”€โ”€โ”€โ”€ + 3 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + help: Add a parameter here + + ร— A 'set' accessor cannot have rest parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-reset-parameter-babel-7/input.ts:2:11] + 1 โ”‚ interface Foo { + 2 โ”‚ set bar(...v); + ยท โ”€โ”€โ”€โ”€ + 3 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + + ร— A 'set' accessor must have exactly one parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-reset-parameter-babel-7/input.ts:2:10] + 1 โ”‚ interface Foo { + 2 โ”‚ set bar(...v); + ยท โ”€โ”€โ”€โ”€โ”€โ”€ + 3 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + help: Add a parameter here + ร— TS(1095): A 'set' accessor cannot have a return type annotation. โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-return-types/input.ts:2:17] 1 โ”‚ interface Foo { @@ -13331,6 +13381,31 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc 3 โ”‚ } โ•ฐโ”€โ”€โ”€โ”€ + ร— TS(2784): 'get' and 'set' accessors cannot declare 'this' parameters. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-this-parameters/input.ts:2:11] + 1 โ”‚ interface Foo { + 2 โ”‚ get bar(this: Foo); + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + 3 โ”‚ set bar(this: Foo); + โ•ฐโ”€โ”€โ”€โ”€ + + ร— TS(2784): 'get' and 'set' accessors cannot declare 'this' parameters. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-this-parameters/input.ts:3:11] + 2 โ”‚ get bar(this: Foo); + 3 โ”‚ set bar(this: Foo); + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + 4 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + + ร— A 'set' accessor must have exactly one parameter. + โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-this-parameters/input.ts:3:10] + 2 โ”‚ get bar(this: Foo); + 3 โ”‚ set bar(this: Foo); + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + 4 โ”‚ } + โ•ฐโ”€โ”€โ”€โ”€ + help: Add a parameter here + ร— Expected `(` but found `<` โ•ญโ”€[babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-type-parameters/input.ts:2:10] 1 โ”‚ interface Foo {