Skip to content

Commit

Permalink
fix(parser): disallow type parameters on class constructors (#8071)
Browse files Browse the repository at this point in the history
TypeScript does not allow type parameters on constructors:

```ts
class A {
  constructor<T>(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>
  • Loading branch information
srijan-paul and autofix-ci[bot] authored Dec 23, 2024
1 parent 618b6aa commit 55d6eb9
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
5 changes: 5 additions & 0 deletions crates/oxc_parser/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_parser/src/js/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(param: T ) {} }
self.error(diagnostics::ts_constructor_type_parameter(type_sig.span));
}

if r#static {
self.error(diagnostics::static_constructor(key.span()));
}
Expand Down
20 changes: 17 additions & 3 deletions tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<T>(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<T>(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 {
Expand Down
83 changes: 81 additions & 2 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<T>() { }
· ───
3 │ }
╰────

× Unexpected token
╭─[typescript/tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnum4.ts:2:9]
1 │ export enum SignatureFlags {
Expand Down

0 comments on commit 55d6eb9

Please sign in to comment.