From 393e5eb34bc5c4b78dd0e271a41b14b4efc92660 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Mon, 5 Feb 2024 15:41:49 +0800 Subject: [PATCH] feat(semantic): report parameter related errors for set accessor --- crates/oxc_ast/src/ast/js.rs | 3 ++ crates/oxc_semantic/src/checker/typescript.rs | 28 ++++++++++ tasks/coverage/parser_babel.snap | 12 +++++ tasks/coverage/parser_typescript.snap | 52 +++++++++++++++++-- 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 3642b91336069b..21cc87440bb597 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -2084,6 +2084,9 @@ impl MethodDefinitionKind { pub fn is_method(&self) -> bool { matches!(self, Self::Method) } + pub fn is_set(&self) -> bool { + matches!(self, Self::Set) + } } #[derive(Debug, Clone, Hash)] diff --git a/crates/oxc_semantic/src/checker/typescript.rs b/crates/oxc_semantic/src/checker/typescript.rs index 4b38d582f8e6cd..780aa703af9158 100644 --- a/crates/oxc_semantic/src/checker/typescript.rs +++ b/crates/oxc_semantic/src/checker/typescript.rs @@ -24,11 +24,39 @@ impl EarlyErrorTypeScript { AstKind::TSTypeParameterDeclaration(declaration) => { check_ts_type_parameter_declaration(declaration, ctx); } + AstKind::MethodDefinition(method) => { + check_method_definition(method, ctx); + } _ => {} } } } +fn check_method_definition(method: &MethodDefinition<'_>, ctx: &SemanticBuilder<'_>) { + #[derive(Debug, Error, Diagnostic)] + #[error("A 'set' accessor must have exactly one parameter.")] + #[diagnostic()] + struct SetAccessorWithParameters(#[label] Span); + + #[derive(Debug, Error, Diagnostic)] + #[error("A 'set' accessor cannot have rest parameter.")] + #[diagnostic()] + struct SetAccessorWithRestParameter(#[label] Span); + + if method.kind.is_set() { + method.value.params.rest.as_ref().map_or_else( + || { + if method.value.params.items.len() != 1 { + ctx.error(SetAccessorWithParameters(method.value.params.span)); + } + }, + |rest| { + ctx.error(SetAccessorWithRestParameter(rest.span)); + }, + ); + } +} + fn check_ts_type_parameter_declaration( declaration: &TSTypeParameterDeclaration<'_>, ctx: &SemanticBuilder<'_>, diff --git a/tasks/coverage/parser_babel.snap b/tasks/coverage/parser_babel.snap index 0f83d32ad256e3..1c69561e76d843 100644 --- a/tasks/coverage/parser_babel.snap +++ b/tasks/coverage/parser_babel.snap @@ -4015,6 +4015,18 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts" · ── ╰──── + × A 'set' accessor must have exactly one parameter. + ╭─[es2015/uncategorised/346/input.js:1:19] + 1 │ class A { set prop() {} } + · ── + ╰──── + + × A 'set' accessor must have exactly one parameter. + ╭─[es2015/uncategorised/347/input.js:1:19] + 1 │ class A { set prop(x, y) {} } + · ────── + ╰──── + × A 'set' accessor must have exactly one parameter. ╭─[es2015/uncategorised/347/input.js:1:19] 1 │ class A { set prop(x, y) {} } diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index 2247fc96c77724..e8de19b096290e 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -1,7 +1,7 @@ parser_typescript Summary: AST Parsed : 5239/5243 (99.92%) Positive Passed: 5232/5243 (99.79%) -Negative Passed: 1038/4879 (21.27%) +Negative Passed: 1040/4879 (21.32%) Expect Syntax Error: "compiler/ClassDeclaration10.ts" Expect Syntax Error: "compiler/ClassDeclaration11.ts" Expect Syntax Error: "compiler/ClassDeclaration13.ts" @@ -33,7 +33,6 @@ Expect Syntax Error: "compiler/accessorAccidentalCallDiagnostic.ts" Expect Syntax Error: "compiler/accessorDeclarationEmitVisibilityErrors.ts" Expect Syntax Error: "compiler/accessorInferredReturnTypeErrorInReturnStatement.ts" Expect Syntax Error: "compiler/accessorWithInitializer.ts" -Expect Syntax Error: "compiler/accessorWithRestParam.ts" Expect Syntax Error: "compiler/accessorWithoutBody1.ts" Expect Syntax Error: "compiler/accessorWithoutBody2.ts" Expect Syntax Error: "compiler/accessorsInAmbientContext.ts" @@ -3173,7 +3172,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/ Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts" Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration16.ts" Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts" -Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts" Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration2.ts" Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration3.ts" Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration7.ts" @@ -4099,6 +4097,22 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 6 │ } ╰──── + × A 'set' accessor cannot have rest parameter. + ╭─[compiler/accessorWithRestParam.ts:4:11] + 3 │ class C { + 4 │ set X(...v) { } + · ──── + 5 │ static set X(...v2) { } + ╰──── + + × A 'set' accessor cannot have rest parameter. + ╭─[compiler/accessorWithRestParam.ts:5:18] + 4 │ set X(...v) { } + 5 │ static set X(...v2) { } + · ───── + 6 │ } + ╰──── + × Unexpected token ╭─[compiler/aliasErrors.ts:13:12] 12 │ import m2 = no.mod; @@ -16774,6 +16788,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" × A 'set' accessor must have exactly one parameter. ╭─[conformance/parser/ecmascript5/ErrorRecovery/parserErrantSemicolonInClass1.ts:15:17] 14 │ } + 15 │ public set d() { + · ── + 16 │ } + ╰──── + + × A 'set' accessor must have exactly one parameter. + ╭─[conformance/parser/ecmascript5/ErrorRecovery/parserErrantSemicolonInClass1.ts:15:17] + 14 │ } 15 │ public set d() { · ── 16 │ } @@ -17135,6 +17157,22 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 4 │ } ╰──── + × A 'set' accessor must have exactly one parameter. + ╭─[conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration13.ts:3:11] + 2 │ class C { + 3 │ set Foo() { } + · ── + 4 │ } + ╰──── + + × A 'set' accessor must have exactly one parameter. + ╭─[conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration14.ts:3:11] + 2 │ class C { + 3 │ set Foo(a: number, b: number) { } + · ────────────────────── + 4 │ } + ╰──── + × A 'set' accessor must have exactly one parameter. ╭─[conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration14.ts:3:11] 2 │ class C { @@ -17151,6 +17189,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 4 │ } ╰──── + × A 'set' accessor cannot have rest parameter. + ╭─[conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts:3:12] + 2 │ class C { + 3 │ set Foo(...a) { } + · ──── + 4 │ } + ╰──── + × Expected a semicolon or an implicit semicolon after a statement, but found none ╭─[conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration4.ts:2:11] 1 │ class C {