mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(semantic): check for invalid interface heritage clauses (#4928)
This commit is contained in:
parent
9c64b12963
commit
80d0d1f0c4
4 changed files with 45 additions and 3 deletions
|
|
@ -99,6 +99,7 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
|
|||
AstKind::YieldExpression(expr) => js::check_yield_expression(expr, node, ctx),
|
||||
AstKind::VariableDeclarator(decl) => ts::check_variable_declarator(decl, ctx),
|
||||
AstKind::SimpleAssignmentTarget(target) => ts::check_simple_assignment_target(target, ctx),
|
||||
AstKind::TSInterfaceDeclaration(decl) => ts::check_ts_interface_declaration(decl, ctx),
|
||||
AstKind::TSTypeParameterDeclaration(declaration) => {
|
||||
ts::check_ts_type_parameter_declaration(declaration, ctx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,31 @@ pub fn check_array_pattern<'a>(pattern: &ArrayPattern<'a>, ctx: &SemanticBuilder
|
|||
}
|
||||
}
|
||||
|
||||
/// An interface can only extend an identifier/qualified-name with optional type arguments.(2499)
|
||||
fn invalid_interface_extend(span0: Span) -> OxcDiagnostic {
|
||||
ts_error(
|
||||
"2499",
|
||||
"An interface can only extend an identifier/qualified-name with optional type arguments.",
|
||||
)
|
||||
.with_label(span0)
|
||||
}
|
||||
|
||||
pub fn check_ts_interface_declaration<'a>(
|
||||
decl: &TSInterfaceDeclaration<'a>,
|
||||
ctx: &SemanticBuilder<'a>,
|
||||
) {
|
||||
if let Some(extends) = &decl.extends {
|
||||
for extend in extends {
|
||||
if !matches!(
|
||||
&extend.expression,
|
||||
Expression::Identifier(_) | Expression::StaticMemberExpression(_),
|
||||
) {
|
||||
ctx.error(invalid_interface_extend(extend.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn not_allowed_namespace_declaration(span0: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::error(
|
||||
"A namespace declaration is only allowed at the top level of a namespace or module.",
|
||||
|
|
|
|||
|
|
@ -342,12 +342,15 @@ fn test_type_query() {
|
|||
|
||||
#[test]
|
||||
fn test_ts_interface_heritage() {
|
||||
// NOTE: interface heritage clauses can only be identifiers or qualified
|
||||
// names, but we handle references on invalid heritage clauses anyways.
|
||||
SemanticTester::ts(
|
||||
"
|
||||
type Heritage = { x: number; y: string; };
|
||||
interface A extends (Heritage.x) {}
|
||||
",
|
||||
)
|
||||
.expect_errors(true)
|
||||
.has_some_symbol("Heritage")
|
||||
.has_number_of_references(1)
|
||||
.test();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ commit: d8086f14
|
|||
parser_typescript Summary:
|
||||
AST Parsed : 6446/6456 (99.85%)
|
||||
Positive Passed: 6423/6456 (99.49%)
|
||||
Negative Passed: 1167/5653 (20.64%)
|
||||
Negative Passed: 1169/5653 (20.68%)
|
||||
Expect Syntax Error: "compiler/ClassDeclaration10.ts"
|
||||
Expect Syntax Error: "compiler/ClassDeclaration11.ts"
|
||||
Expect Syntax Error: "compiler/ClassDeclaration13.ts"
|
||||
|
|
@ -1158,7 +1158,6 @@ Expect Syntax Error: "compiler/interfaceImplementation6.ts"
|
|||
Expect Syntax Error: "compiler/interfaceImplementation7.ts"
|
||||
Expect Syntax Error: "compiler/interfaceImplementation8.ts"
|
||||
Expect Syntax Error: "compiler/interfaceInheritance.ts"
|
||||
Expect Syntax Error: "compiler/interfaceMayNotBeExtendedWitACall.ts"
|
||||
Expect Syntax Error: "compiler/interfaceMemberValidation.ts"
|
||||
Expect Syntax Error: "compiler/interfaceNameAsIdentifier.ts"
|
||||
Expect Syntax Error: "compiler/interfacePropertiesWithSameName2.ts"
|
||||
|
|
@ -3317,7 +3316,6 @@ Expect Syntax Error: "conformance/interfaces/declarationMerging/twoGenericInterf
|
|||
Expect Syntax Error: "conformance/interfaces/declarationMerging/twoInterfacesDifferentRootModule.ts"
|
||||
Expect Syntax Error: "conformance/interfaces/declarationMerging/twoInterfacesDifferentRootModule2.ts"
|
||||
Expect Syntax Error: "conformance/interfaces/interfaceDeclarations/derivedInterfaceIncompatibleWithBaseIndexer.ts"
|
||||
Expect Syntax Error: "conformance/interfaces/interfaceDeclarations/interfaceExtendingOptionalChain.ts"
|
||||
Expect Syntax Error: "conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts"
|
||||
Expect Syntax Error: "conformance/interfaces/interfaceDeclarations/interfaceThatHidesBaseProperty2.ts"
|
||||
Expect Syntax Error: "conformance/interfaces/interfaceDeclarations/interfaceThatIndirectlyInheritsFromItself.ts"
|
||||
|
|
@ -8119,6 +8117,14 @@ Expect to Parse: "conformance/salsa/typeFromPropertyAssignmentWithExport.ts"
|
|||
· ╰── `{` expected
|
||||
╰────
|
||||
|
||||
× TS(2499): An interface can only extend an identifier/qualified-name with optional type arguments.
|
||||
╭─[compiler/interfaceMayNotBeExtendedWitACall.ts:3:24]
|
||||
2 │
|
||||
3 │ interface blue extends color() { // error
|
||||
· ───────
|
||||
4 │
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[compiler/interfaceNaming1.ts:1:10]
|
||||
1 │ interface { }
|
||||
|
|
@ -17990,6 +17996,13 @@ Expect to Parse: "conformance/salsa/typeFromPropertyAssignmentWithExport.ts"
|
|||
11 │ I // This should be the identifier 'I'
|
||||
╰────
|
||||
|
||||
× TS(2499): An interface can only extend an identifier/qualified-name with optional type arguments.
|
||||
╭─[conformance/interfaces/interfaceDeclarations/interfaceExtendingOptionalChain.ts:5:22]
|
||||
4 │
|
||||
5 │ interface C1 extends Foo?.Bar {}
|
||||
· ────────
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[conformance/interfaces/interfaceDeclarations/interfacesWithPredefinedTypesAsNames.ts:5:10]
|
||||
4 │ interface boolean { }
|
||||
|
|
|
|||
Loading…
Reference in a new issue