fix(ast): parse rest parameter with the correct optional and type annotation syntax (#2686)

closes #2653
This commit is contained in:
Boshen 2024-03-12 15:47:22 +08:00 committed by GitHub
parent e86cd629c8
commit 6c6adb46d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 8 deletions

View file

@ -148,6 +148,11 @@ pub struct BindingRestElementTrailingComma(#[label] pub Span);
#[diagnostic(help("Expected identifier in rest element"))] #[diagnostic(help("Expected identifier in rest element"))]
pub struct InvalidBindingRestElement(#[label] pub Span); pub struct InvalidBindingRestElement(#[label] pub Span);
#[derive(Debug, Error, Diagnostic)]
#[error("A rest parameter cannot be optional")]
#[diagnostic()]
pub struct ARestParameterCannotBeOptional(#[label] pub Span);
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("Cannot assign to this expression")] #[error("Cannot assign to this expression")]
#[diagnostic()] #[diagnostic()]

View file

@ -61,7 +61,21 @@ impl<'a> ParserImpl<'a> {
pub(super) fn parse_rest_element(&mut self) -> Result<Box<'a, BindingRestElement<'a>>> { pub(super) fn parse_rest_element(&mut self) -> Result<Box<'a, BindingRestElement<'a>>> {
let span = self.start_span(); let span = self.start_span();
self.bump_any(); // advance `...` self.bump_any(); // advance `...`
let argument = self.parse_binding_pattern_with_initializer()?; let init_span = self.start_span();
let kind = self.parse_binding_pattern_kind()?;
// Rest element does not allow `?`, checked in checker/typescript.rs
if self.at(Kind::Question) && self.ts_enabled() {
let span = self.cur_token().span();
self.bump_any();
self.error(diagnostics::ARestParameterCannotBeOptional(span));
}
// The span is not extended to its type_annotation
let type_annotation = self.parse_ts_type_annotation()?;
let pattern = self.ast.binding_pattern(kind, type_annotation, false);
// Rest element does not allow `= initializer`, .
let argument =
self.with_context(Context::In, |p| p.parse_initializer(init_span, pattern))?;
let span = self.end_span(span); let span = self.end_span(span);
if self.at(Kind::Comma) { if self.at(Kind::Comma) {

View file

@ -1,7 +1,7 @@
parser_babel Summary: parser_babel Summary:
AST Parsed : 2090/2096 (99.71%) AST Parsed : 2090/2096 (99.71%)
Positive Passed: 2083/2096 (99.38%) Positive Passed: 2083/2096 (99.38%)
Negative Passed: 1361/1500 (90.73%) Negative Passed: 1362/1500 (90.80%)
Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js" Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js"
@ -36,7 +36,6 @@ Expect Syntax Error: "es2020/dynamic-import-createImportExpression-false/invalid
Expect Syntax Error: "esprima/es2015-arrow-function/invalid-param-strict-mode/input.js" Expect Syntax Error: "esprima/es2015-arrow-function/invalid-param-strict-mode/input.js"
Expect Syntax Error: "esprima/es2015-generator/generator-parameter-binding-property-reserved/input.js" Expect Syntax Error: "esprima/es2015-generator/generator-parameter-binding-property-reserved/input.js"
Expect Syntax Error: "esprima/invalid-syntax/migrated_0101/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0101/input.js"
Expect Syntax Error: "typescript/arrow-function/async-rest-optional-parameter/input.ts"
Expect Syntax Error: "typescript/cast/satisfies-const-error/input.ts" Expect Syntax Error: "typescript/cast/satisfies-const-error/input.ts"
Expect Syntax Error: "typescript/cast/unparenthesized-assert-and-assign/input.ts" Expect Syntax Error: "typescript/cast/unparenthesized-assert-and-assign/input.ts"
Expect Syntax Error: "typescript/cast/unparenthesized-type-assertion-and-assign/input.ts" Expect Syntax Error: "typescript/cast/unparenthesized-type-assertion-and-assign/input.ts"
@ -9720,6 +9719,12 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts"
╰──── ╰────
help: Try insert a semicolon here help: Try insert a semicolon here
× A rest parameter cannot be optional
╭─[typescript/arrow-function/async-rest-optional-parameter/input.ts:1:14]
1 │ async(...args?: any[]) : any => {}
· ─
╰────
× Unexpected token × Unexpected token
╭─[typescript/arrow-function/generic-tsx/input.ts:4:3] ╭─[typescript/arrow-function/generic-tsx/input.ts:4:3]
3 │ 3 │

View file

@ -1,7 +1,7 @@
parser_typescript Summary: parser_typescript Summary:
AST Parsed : 5240/5243 (99.94%) AST Parsed : 5240/5243 (99.94%)
Positive Passed: 5233/5243 (99.81%) Positive Passed: 5233/5243 (99.81%)
Negative Passed: 1060/4879 (21.73%) Negative Passed: 1062/4879 (21.77%)
Expect Syntax Error: "compiler/ClassDeclaration10.ts" Expect Syntax Error: "compiler/ClassDeclaration10.ts"
Expect Syntax Error: "compiler/ClassDeclaration11.ts" Expect Syntax Error: "compiler/ClassDeclaration11.ts"
Expect Syntax Error: "compiler/ClassDeclaration13.ts" Expect Syntax Error: "compiler/ClassDeclaration13.ts"
@ -3175,7 +3175,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserMo
Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration3.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration3.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration4.d.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration4.d.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration5.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration5.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList14.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList14.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList15.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList15.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList16.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList16.ts"
@ -3183,7 +3182,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParame
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList2.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList2.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList7.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList7.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList8.ts" Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList8.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected1.ts" Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected1.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected2.ts" Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected2.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected4.ts" Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected4.ts"
@ -6544,6 +6542,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
╰──── ╰────
help: Try insert a semicolon here help: Try insert a semicolon here
× A rest parameter cannot be optional
╭─[compiler/fatarrowfunctionsOptionalArgsErrors1.ts:2:8]
1 │ (arg1?, arg2) => 101;
2 │ (...arg?) => 102;
· ─
3 │ (...arg) => 103;
╰────
× A required parameter cannot follow an optional parameter. × A required parameter cannot follow an optional parameter.
╭─[compiler/fatarrowfunctionsOptionalArgsErrors1.ts:1:9] ╭─[compiler/fatarrowfunctionsOptionalArgsErrors1.ts:1:9]
1 │ (arg1?, arg2) => 101; 1 │ (arg1?, arg2) => 101;
@ -6630,8 +6636,8 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
× Identifier `b` has already been declared × Identifier `b` has already been declared
╭─[compiler/functionCall15.ts:1:25] ╭─[compiler/functionCall15.ts:1:25]
1 │ function foo(a?:string, b?:number, ...b:number[]){} 1 │ function foo(a?:string, b?:number, ...b:number[]){}
· ────┬──── ───────── · ────┬──── ┬
· │ ╰── It can not be redeclared here · │ ╰── It can not be redeclared here
· ╰── `b` has already been declared here · ╰── `b` has already been declared here
╰──── ╰────
@ -8610,6 +8616,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
· ─ · ─
╰──── ╰────
× A rest parameter cannot be optional
╭─[compiler/restParamAsOptional.ts:1:16]
1 │ function f(...x?) { }
· ─
2 │ function f2(...x = []) { }
╰────
× A rest parameter cannot have an initializer × A rest parameter cannot have an initializer
╭─[compiler/restParamAsOptional.ts:2:16] ╭─[compiler/restParamAsOptional.ts:2:16]
1 │ function f(...x?) { } 1 │ function f(...x?) { }
@ -12489,6 +12502,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
8 │ a0([1, 2, [["world"]], "string"]); // Error 8 │ a0([1, 2, [["world"]], "string"]); // Error
╰──── ╰────
× A rest parameter cannot be optional
╭─[conformance/es6/destructuring/destructuringParameterDeclaration4.ts:14:17]
13 │ function a2(...a: someArray) { } // Error, rest parameter must be array type
14 │ function a3(...b?) { } // Error, can't be optional
· ─
15 │ function a4(...b = [1,2,3]) { } // Error, can't have initializer
╰────
× A rest parameter cannot have an initializer × A rest parameter cannot have an initializer
╭─[conformance/es6/destructuring/destructuringParameterDeclaration4.ts:15:16] ╭─[conformance/es6/destructuring/destructuringParameterDeclaration4.ts:15:16]
14 │ function a3(...b?) { } // Error, can't be optional 14 │ function a3(...b?) { } // Error, can't be optional
@ -17267,6 +17288,12 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ } 3 │ }
╰──── ╰────
× A rest parameter cannot be optional
╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts:1:8]
1 │ (...arg?) => 102;
· ─
╰────
× A parameter property is only allowed in a constructor implementation. × A parameter property is only allowed in a constructor implementation.
╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList13.ts:2:10] ╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList13.ts:2:10]
1 │ interface I { 1 │ interface I {
@ -17307,6 +17334,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ } 3 │ }
╰──── ╰────
× A rest parameter cannot be optional
╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts:2:14]
1 │ class C {
2 │ foo(...bar?) { }
· ─
3 │ }
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none × Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[conformance/parser/ecmascript5/RealWorld/parserharness.ts:1431:16] ╭─[conformance/parser/ecmascript5/RealWorld/parserharness.ts:1431:16]
1430 │ // Regex for parsing options in the format "@Alpha: Value of any sort" 1430 │ // Regex for parsing options in the format "@Alpha: Value of any sort"