diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index 0f758cd1e2204..305473097396a 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -327,6 +327,14 @@ pub fn extends_clause_must_precede_implements(span: Span, implements_span: Span) .with_help("Move the 'extends' clause before the 'implements' clause") } +// Classes can only extend a single class. ts(1174) +#[cold] +pub fn classes_can_only_extend_single_class(span: Span) -> OxcDiagnostic { + ts_error("1174", "Classes can only extend a single class.") + .with_label(span) + .with_help("Remove the extra base class or use interfaces for multiple inheritance") +} + // 'implements' clause already seen. ts(1175) #[cold] pub fn implements_clause_already_seen(span: Span, seen_span: Span) -> OxcDiagnostic { diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index 587492925d04d..49e0e4b082534 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -90,6 +90,9 @@ impl<'a> ParserImpl<'a> { let first_extends = extends.remove(0); super_class = Some(first_extends.0); super_type_parameters = first_extends.1; + for (_, _, span) in extends { + self.error(diagnostics::classes_can_only_extend_single_class(span)); + } } let body = self.parse_class_body(); diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index aea4b8efc1b36..5a5b9bdc49f69 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -3,7 +3,7 @@ commit: 669c25c0 parser_typescript Summary: AST Parsed : 9821/9822 (99.99%) Positive Passed: 9812/9822 (99.90%) -Negative Passed: 1482/2547 (58.19%) +Negative Passed: 1485/2547 (58.30%) Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts @@ -120,8 +120,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/classExtendi Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/classExtendsInterface_not.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/classExtendsMultipleBaseClasses.ts - Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/classExtendsNull.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/classExtendsNull2.ts @@ -686,8 +684,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/multipleExpo Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/multipleExports.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/multipleInheritance.ts - Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/multivar.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/namespaceMergedWithImportAliasNoCrash.ts @@ -1758,8 +1754,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ClassDeclarations/parserClassDeclaration18.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ClassDeclarations/parserClassDeclaration6.ts - Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ClassDeclarations/parserClassDeclaration7.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName4.ts @@ -3628,6 +3622,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc 4 │ } ╰──── + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/compiler/classExtendsMultipleBaseClasses.ts:3:19] + 2 │ class B { } + 3 │ class C extends A,B { } + · ─ + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + × Expected `(` but found `}` ╭─[typescript/tests/cases/compiler/classFieldsBrokenConstructorEmitNoCrash1.ts:4:1] 3 │ constructor @@ -3636,6 +3638,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc · ╰── `(` expected ╰──── + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/compiler/classHeritageWithTrailingSeparator.ts:2:20] + 1 │ class C { foo: number } + 2 │ ╭─▶ class D extends C, { + 3 │ ╰─▶ } + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + × Expected `{` but found `EOF` ╭─[typescript/tests/cases/compiler/classHeritageWithTrailingSeparator.ts:3:2] 2 │ class D extends C, { @@ -8415,6 +8425,24 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc 5 │ public private p4; ╰──── + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/compiler/multipleInheritance.ts:9:21] + 8 │ + 9 │ class C extends B1, B2 { // duplicate member + · ── + 10 │ } + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/compiler/multipleInheritance.ts:18:21] + 17 │ + 18 │ class E extends D1, D2 { // nope, duplicate member + · ── + 19 │ } + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + × Identifier `x` has already been declared ╭─[typescript/tests/cases/compiler/nameCollisions.ts:2:9] 1 │ namespace T { @@ -21142,6 +21170,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc ╰──── help: Merge the two 'implements' clauses into one by a ',' + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ClassDeclarations/parserClassDeclaration6.ts:1:20] + 1 │ class C extends A, B { + · ─ + 2 │ } + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + × Constructor implementation is missing. ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ClassDeclarations/parserClassDeclaration8.ts:2:3] 1 │ class C { @@ -21439,6 +21475,13 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc 2 │ } ╰──── + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ExtendsOrImplementsClauses/parserErrorRecovery_ExtendsOrImplementsClause2.ts:1:20] + 1 │ ╭─▶ class C extends A, { + 2 │ ╰─▶ } + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + × Expected `{` but found `EOF` ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ExtendsOrImplementsClauses/parserErrorRecovery_ExtendsOrImplementsClause2.ts:2:2] 1 │ class C extends A, { @@ -21460,6 +21503,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc 2 │ } ╰──── + × TS(1174): Classes can only extend a single class. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ExtendsOrImplementsClauses/parserErrorRecovery_ExtendsOrImplementsClause5.ts:1:20] + 1 │ class C extends A, implements B, { + · ────────── + 2 │ } + ╰──── + help: Remove the extra base class or use interfaces for multiple inheritance + × Expected `{` but found `Identifier` ╭─[typescript/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ExtendsOrImplementsClauses/parserErrorRecovery_ExtendsOrImplementsClause5.ts:1:31] 1 │ class C extends A, implements B, {