From 55d6eb9507d293fd846e52e019addf85e67dd8b9 Mon Sep 17 00:00:00 2001 From: injuly <50487716+srijan-paul@users.noreply.github.com> Date: Tue, 24 Dec 2024 05:08:39 +0530 Subject: [PATCH] fix(parser): disallow type parameters on class constructors (#8071) TypeScript does not allow type parameters on constructors: ```ts class A { constructor(t: T) {} // <- should be an error } ``` Here's a comparison snippet on: 1. [TypeScript playground](https://www.typescriptlang.org/play/?#code/MYGwhgzhAECC0G8BQ1XWAewHYQC4CcBXYXDfAHlgD4AKASkSRTQF8kWg) (syntax error). 2. [SWC playground](https://play.swc.rs/?version=1.10.1&code=H4sIAAAAAAAAA0vOSSwuVnBWqOZSUEjOzysuKSpNLskvsgmx09BUqFao5aoFAOf92%2FAiAAAA&config=H4sIAAAAAAAAA1WPSw7DIAwF9zkF8rrbdtE79BCIOhERP9mOVBTl7oUE0maH3xszsA5KwcwGnmotxzIkTYx0ziXhHER%2FSgKSE7IhmwRuvRWu1agd4x5tRwOiaUKpW8j3hoOLkbHjLfM22DH%2FC030iZD5ClZUh8nhVTc0Jfj4XvayfaQ%2B9tA%2F4Ad12XkxWH71TaEFh%2B0LYuVI0xQBAAA%3D) (syntax error) 3. [OXC playground](https://playground.oxc.rs/#eNo9T8EKwjAM/ZWSk8IOKngpInjxCzx66Wo2Cl0zkk4do/9u6+guyXshL+9lAQsarDci6qaWZ1DKUpDIk43El8d1t1+nSpWaniFBAwR6AZ5CaTKHaL6gswQb8C7EisXSiBuZh5Z8ZZFNkI54AN0ZL5gaGA0Lcr6YcblS8bb6H0A03GO2AJTT4XiGvGHphT2WMJkMLrjOVXH+JTL5u6dPEb+RW5KcaTVN6QerbleM) (parses as valid syntax) This PR makes OXC behave exactly like `tsc`, with a little test case. Happy holidays! --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- crates/oxc_parser/src/diagnostics.rs | 5 ++ crates/oxc_parser/src/js/class.rs | 5 ++ tasks/coverage/snapshots/parser_babel.snap | 20 ++++- .../coverage/snapshots/parser_typescript.snap | 83 ++++++++++++++++++- 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index 1f0dac1e8ff16..ec17389f55867 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -348,6 +348,11 @@ pub fn ts_constructor_this_parameter(span: Span) -> OxcDiagnostic { ts_error("2681", "A constructor cannot have a `this` parameter.").with_label(span) } +#[cold] +pub fn ts_constructor_type_parameter(span: Span) -> OxcDiagnostic { + ts_error("1092", "Type parameters cannot appear on a constructor declaration").with_label(span) +} + #[cold] pub fn ts_arrow_function_this_parameter(span: Span) -> OxcDiagnostic { ts_error("2730", "An arrow function cannot have a `this` parameter.").with_label(span) diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index 913fccc7ab4dd..cdc33ce60954c 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -419,6 +419,11 @@ impl<'a> ParserImpl<'a> { self.error(diagnostics::ts_constructor_this_parameter(this_param.span)); } + if let Some(type_sig) = &value.type_parameters { + // class Foo { constructor(param: T ) {} } + self.error(diagnostics::ts_constructor_type_parameter(type_sig.span)); + } + if r#static { self.error(diagnostics::static_constructor(key.span())); } diff --git a/tasks/coverage/snapshots/parser_babel.snap b/tasks/coverage/snapshots/parser_babel.snap index f94da9ccdb9d7..433ecf0c73e2e 100644 --- a/tasks/coverage/snapshots/parser_babel.snap +++ b/tasks/coverage/snapshots/parser_babel.snap @@ -3,7 +3,7 @@ commit: 54a8389f parser_babel Summary: AST Parsed : 2205/2218 (99.41%) Positive Passed: 2190/2218 (98.74%) -Negative Passed: 1520/1634 (93.02%) +Negative Passed: 1522/1634 (93.15%) Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.1-sloppy-labeled-functions-if-body/input.js Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-if/input.js Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js @@ -44,8 +44,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/class/constructor-with-invalid-order-modifiers-1/input.ts Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-2/input.ts Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-invalid-order-modifiers-3/input.ts -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-type-parameters/input.ts -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-type-parameters-babel-7/input.ts Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/declare-field-initializer/input.ts Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/declare-initializer/input.ts Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/declare-method/input.ts @@ -11575,6 +11573,22 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc 8 │ abstract accessor f = 1; ╰──── + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-type-parameters/input.ts:2:14] + 1 │ class C { + 2 │ constructor(foo: T) {} + · ─── + 3 │ } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-type-parameters-babel-7/input.ts:2:14] + 1 │ class C { + 2 │ constructor(foo: T) {} + · ─── + 3 │ } + ╰──── + × Getters and setters must have an implementation. ╭─[babel/packages/babel-parser/test/fixtures/typescript/class/declare-accessor/input.ts:2:15] 1 │ class Foo { diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index 50e1d61e74026..c0fde9d6f4c20 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -3,7 +3,7 @@ commit: d85767ab parser_typescript Summary: AST Parsed : 6494/6503 (99.86%) Positive Passed: 6483/6503 (99.69%) -Negative Passed: 1240/5747 (21.58%) +Negative Passed: 1241/5747 (21.59%) Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration10.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration11.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration13.ts @@ -3756,7 +3756,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration2.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration4.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration7.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration9.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnumDeclaration2.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnumDeclaration3.d.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/AccessibilityAfterStatic/parserAccessibilityAfterStatic1.ts @@ -10602,6 +10601,70 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private · ─ ╰──── + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:2:14] + 1 │ class C { + 2 │ constructor<>() { } + · ── + 3 │ constructor<> () { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:3:14] + 2 │ constructor<>() { } + 3 │ constructor<> () { } + · ── + 4 │ constructor <>() { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:4:15] + 3 │ constructor<> () { } + 4 │ constructor <>() { } + · ── + 5 │ constructor <> () { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:5:15] + 4 │ constructor <>() { } + 5 │ constructor <> () { } + · ── + 6 │ constructor< >() { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:6:14] + 5 │ constructor <> () { } + 6 │ constructor< >() { } + · ─── + 7 │ constructor< > () { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:7:14] + 6 │ constructor< >() { } + 7 │ constructor< > () { } + · ─── + 8 │ constructor < >() { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:8:15] + 7 │ constructor< > () { } + 8 │ constructor < >() { } + · ─── + 9 │ constructor < > () { } + ╰──── + + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:9:15] + 8 │ constructor < >() { } + 9 │ constructor < > () { } + · ─── + 10 │ } + ╰──── + × Type parameter list cannot be empty. ╭─[typescript/tests/cases/compiler/parserConstructorDeclaration12.ts:2:14] 1 │ class C { @@ -20194,6 +20257,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 3 │ } ╰──── + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration11.ts:2:14] + 1 │ class C { + 2 │ constructor<>() { } + · ── + 3 │ } + ╰──── + × Type parameter list cannot be empty. ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration11.ts:2:14] 1 │ class C { @@ -20228,6 +20299,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 4 │ } ╰──── + × TS(1092): Type parameters cannot appear on a constructor declaration + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ConstructorDeclarations/parserConstructorDeclaration9.ts:2:14] + 1 │ class C { + 2 │ constructor() { } + · ─── + 3 │ } + ╰──── + × Unexpected token ╭─[typescript/tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnum4.ts:2:9] 1 │ export enum SignatureFlags {