mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(semantic): check optional parameters (#2263)
This commit is contained in:
parent
8d99a15ac9
commit
d71175e712
4 changed files with 98 additions and 8 deletions
|
|
@ -1602,6 +1602,10 @@ impl<'a> BindingPatternKind<'a> {
|
||||||
pub fn is_binding_identifier(&self) -> bool {
|
pub fn is_binding_identifier(&self) -> bool {
|
||||||
matches!(self, Self::BindingIdentifier(_))
|
matches!(self, Self::BindingIdentifier(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_assignment_pattern(&self) -> bool {
|
||||||
|
matches!(self, Self::AssignmentPattern(_))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,25 @@ fn check_variable_declarator(decl: &VariableDeclarator, ctx: &SemanticBuilder<'_
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_formal_parameters(params: &FormalParameters, ctx: &SemanticBuilder<'_>) {
|
fn check_formal_parameters(params: &FormalParameters, ctx: &SemanticBuilder<'_>) {
|
||||||
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
|
#[error("A required parameter cannot follow an optional parameter.")]
|
||||||
|
#[diagnostic()]
|
||||||
|
struct RequiredParameterAfterOptionalParameter(#[label] Span);
|
||||||
|
|
||||||
if !params.is_empty() && params.kind == FormalParameterKind::Signature {
|
if !params.is_empty() && params.kind == FormalParameterKind::Signature {
|
||||||
check_duplicate_bound_names(params, ctx);
|
check_duplicate_bound_names(params, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut has_optional = false;
|
||||||
|
for item in ¶ms.items {
|
||||||
|
// function a(optional?: number, required: number) { }
|
||||||
|
if has_optional && !item.pattern.optional && !item.pattern.kind.is_assignment_pattern() {
|
||||||
|
ctx.error(RequiredParameterAfterOptionalParameter(item.span));
|
||||||
|
}
|
||||||
|
if item.pattern.optional {
|
||||||
|
has_optional = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_duplicate_bound_names<T: BoundNames>(bound_names: &T, ctx: &SemanticBuilder<'_>) {
|
fn check_duplicate_bound_names<T: BoundNames>(bound_names: &T, ctx: &SemanticBuilder<'_>) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
parser_babel Summary:
|
parser_babel Summary:
|
||||||
AST Parsed : 2090/2096 (99.71%)
|
AST Parsed : 2090/2096 (99.71%)
|
||||||
Positive Passed: 2088/2096 (99.62%)
|
Positive Passed: 2086/2096 (99.52%)
|
||||||
Negative Passed: 1351/1500 (90.07%)
|
Negative Passed: 1355/1500 (90.33%)
|
||||||
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"
|
||||||
|
|
@ -71,7 +71,6 @@ Expect Syntax Error: "typescript/class/modifiers-index-signatures/input.ts"
|
||||||
Expect Syntax Error: "typescript/class/modifiers-invalid-order/input.ts"
|
Expect Syntax Error: "typescript/class/modifiers-invalid-order/input.ts"
|
||||||
Expect Syntax Error: "typescript/class/modifiers-override-errors/input.ts"
|
Expect Syntax Error: "typescript/class/modifiers-override-errors/input.ts"
|
||||||
Expect Syntax Error: "typescript/class/parameter-properties-binding-patterns/input.ts"
|
Expect Syntax Error: "typescript/class/parameter-properties-binding-patterns/input.ts"
|
||||||
Expect Syntax Error: "typescript/class/parameter-properties-not-constructor/input.ts"
|
|
||||||
Expect Syntax Error: "typescript/class/private-fields-modifier-abstract/input.ts"
|
Expect Syntax Error: "typescript/class/private-fields-modifier-abstract/input.ts"
|
||||||
Expect Syntax Error: "typescript/class/private-fields-modifier-private/input.ts"
|
Expect Syntax Error: "typescript/class/private-fields-modifier-private/input.ts"
|
||||||
Expect Syntax Error: "typescript/class/private-fields-modifier-protected/input.ts"
|
Expect Syntax Error: "typescript/class/private-fields-modifier-protected/input.ts"
|
||||||
|
|
@ -94,9 +93,6 @@ Expect Syntax Error: "typescript/expect-plugin/export-type-named/input.js"
|
||||||
Expect Syntax Error: "typescript/export/double-declare/input.ts"
|
Expect Syntax Error: "typescript/export/double-declare/input.ts"
|
||||||
Expect Syntax Error: "typescript/export/equals-in-script/input.ts"
|
Expect Syntax Error: "typescript/export/equals-in-script/input.ts"
|
||||||
Expect Syntax Error: "typescript/function/empty-type-parameters/input.ts"
|
Expect Syntax Error: "typescript/function/empty-type-parameters/input.ts"
|
||||||
Expect Syntax Error: "typescript/function/parameter-properties/input.ts"
|
|
||||||
Expect Syntax Error: "typescript/function/pattern-optional-parameters/input.ts"
|
|
||||||
Expect Syntax Error: "typescript/function/pattern-optional-parameters-arrow/input.ts"
|
|
||||||
Expect Syntax Error: "typescript/import/equals-in-script/input.ts"
|
Expect Syntax Error: "typescript/import/equals-in-script/input.ts"
|
||||||
Expect Syntax Error: "typescript/import/equals-require-in-script/input.ts"
|
Expect Syntax Error: "typescript/import/equals-require-in-script/input.ts"
|
||||||
Expect Syntax Error: "typescript/import/export-import-type/input.ts"
|
Expect Syntax Error: "typescript/import/export-import-type/input.ts"
|
||||||
|
|
@ -187,6 +183,22 @@ Expect to Parse: "typescript/class/constructor-with-modifier-names/input.ts"
|
||||||
4 │ }
|
4 │ }
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
|
Expect to Parse: "typescript/class/parameter-properties/input.ts"
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[typescript/class/parameter-properties/input.ts:6:1]
|
||||||
|
6 │ private pi?: number,
|
||||||
|
7 │ public readonly pur,
|
||||||
|
· ───────────────────
|
||||||
|
8 │ // Also works on AssignmentPattern
|
||||||
|
╰────
|
||||||
|
|
||||||
|
Expect to Parse: "typescript/function/declare-pattern-parameters/input.ts"
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[typescript/function/declare-pattern-parameters/input.ts:1:1]
|
||||||
|
1 │ declare function f([]?, {})
|
||||||
|
· ──
|
||||||
|
╰────
|
||||||
|
|
||||||
Expect to Parse: "typescript/interface/get-set-properties/input.ts"
|
Expect to Parse: "typescript/interface/get-set-properties/input.ts"
|
||||||
× Expected `(` but found `:`
|
× Expected `(` but found `:`
|
||||||
╭─[typescript/interface/get-set-properties/input.ts:1:1]
|
╭─[typescript/interface/get-set-properties/input.ts:1:1]
|
||||||
|
|
@ -9775,6 +9787,14 @@ 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 required parameter cannot follow an optional parameter.
|
||||||
|
╭─[typescript/class/parameter-properties-not-constructor/input.ts:6:1]
|
||||||
|
6 │ private pi?: number,
|
||||||
|
7 │ public readonly pur,
|
||||||
|
· ───────────────────
|
||||||
|
8 │ // Also works on AssignmentPattern
|
||||||
|
╰────
|
||||||
|
|
||||||
× Unexpected token
|
× Unexpected token
|
||||||
╭─[typescript/const/invalid-initializer-ambient-context/input.ts:1:1]
|
╭─[typescript/const/invalid-initializer-ambient-context/input.ts:1:1]
|
||||||
1 │ declare module N {
|
1 │ declare module N {
|
||||||
|
|
@ -9822,6 +9842,26 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts"
|
||||||
· ───
|
· ───
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[typescript/function/parameter-properties/input.ts:5:1]
|
||||||
|
5 │ private pi?: number,
|
||||||
|
6 │ public readonly pur,
|
||||||
|
· ───────────────────
|
||||||
|
7 │ readonly x = 0,
|
||||||
|
╰────
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[typescript/function/pattern-optional-parameters/input.ts:1:1]
|
||||||
|
1 │ function f([]?, {}) {}
|
||||||
|
· ──
|
||||||
|
╰────
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[typescript/function/pattern-optional-parameters-arrow/input.ts:1:1]
|
||||||
|
1 │ ([]?, {}) => {}
|
||||||
|
· ──
|
||||||
|
╰────
|
||||||
|
|
||||||
× 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
|
||||||
╭─[typescript/interface/declare-new-line/input.ts:1:1]
|
╭─[typescript/interface/declare-new-line/input.ts:1:1]
|
||||||
1 │ declare interface
|
1 │ declare interface
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
parser_typescript Summary:
|
parser_typescript Summary:
|
||||||
AST Parsed : 5239/5243 (99.92%)
|
AST Parsed : 5239/5243 (99.92%)
|
||||||
Positive Passed: 5232/5243 (99.79%)
|
Positive Passed: 5232/5243 (99.79%)
|
||||||
Negative Passed: 1024/4879 (20.99%)
|
Negative Passed: 1025/4879 (21.01%)
|
||||||
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"
|
||||||
|
|
@ -3210,7 +3210,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParame
|
||||||
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList16.ts"
|
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList16.ts"
|
||||||
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList17.ts"
|
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList17.ts"
|
||||||
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/parserParameterList3.ts"
|
|
||||||
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList4.ts"
|
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList4.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"
|
||||||
|
|
@ -6370,6 +6369,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
|
||||||
╰────
|
╰────
|
||||||
help: Try insert a semicolon here
|
help: Try insert a semicolon here
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[compiler/fatarrowfunctionsOptionalArgsErrors1.ts:1:1]
|
||||||
|
1 │ (arg1?, arg2) => 101;
|
||||||
|
· ────
|
||||||
|
2 │ (...arg?) => 102;
|
||||||
|
╰────
|
||||||
|
|
||||||
× A rest parameter cannot have an initializer
|
× A rest parameter cannot have an initializer
|
||||||
╭─[compiler/fatarrowfunctionsOptionalArgsErrors1.ts:3:1]
|
╭─[compiler/fatarrowfunctionsOptionalArgsErrors1.ts:3:1]
|
||||||
3 │ (...arg) => 103;
|
3 │ (...arg) => 103;
|
||||||
|
|
@ -15798,6 +15804,22 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
|
||||||
10 │ function fn5() { }
|
10 │ function fn5() { }
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[conformance/functions/functionOverloadErrorsSyntax.ts:1:1]
|
||||||
|
1 │ //Function overload signature with optional parameter followed by non-optional parameter
|
||||||
|
2 │ function fn4a(x?: number, y: string);
|
||||||
|
· ─────────
|
||||||
|
3 │ function fn4a() { }
|
||||||
|
╰────
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[conformance/functions/functionOverloadErrorsSyntax.ts:4:1]
|
||||||
|
4 │
|
||||||
|
5 │ function fn4b(n: string, x?: number, y: string);
|
||||||
|
· ─────────
|
||||||
|
6 │ function fn4b() { }
|
||||||
|
╰────
|
||||||
|
|
||||||
× Illegal 'use strict' directive in function with non-simple parameter list
|
× Illegal 'use strict' directive in function with non-simple parameter list
|
||||||
╭─[conformance/functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:3:1]
|
╭─[conformance/functions/functionWithUseStrictAndSimpleParameterList_es2016.ts:3:1]
|
||||||
3 │ function a(a = 10) {
|
3 │ function a(a = 10) {
|
||||||
|
|
@ -17062,6 +17084,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
|
||||||
3 │ }
|
3 │ }
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
|
× A required parameter cannot follow an optional parameter.
|
||||||
|
╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList3.ts:1:1]
|
||||||
|
1 │ class C {
|
||||||
|
2 │ F(A?, B) { }
|
||||||
|
· ─
|
||||||
|
3 │ }
|
||||||
|
╰────
|
||||||
|
|
||||||
× Expected `)` but found `Identifier`
|
× Expected `)` but found `Identifier`
|
||||||
╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts:1:1]
|
╭─[conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts:1:1]
|
||||||
1 │ function A(): (public B) => C {
|
1 │ function A(): (public B) => C {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue