diff --git a/crates/oxc_semantic/src/checker/mod.rs b/crates/oxc_semantic/src/checker/mod.rs index 60f350c8e788fa..26fd69d7c23165 100644 --- a/crates/oxc_semantic/src/checker/mod.rs +++ b/crates/oxc_semantic/src/checker/mod.rs @@ -53,10 +53,12 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) { AstKind::ForInStatement(stmt) => { js::check_function_declaration(&stmt.body, false, ctx); js::check_for_statement_left(&stmt.left, true, node, ctx); + ts::check_for_statement_left(&stmt.left, true, ctx); } AstKind::ForOfStatement(stmt) => { js::check_function_declaration(&stmt.body, false, ctx); js::check_for_statement_left(&stmt.left, false, node, ctx); + ts::check_for_statement_left(&stmt.left, false, ctx); } AstKind::WhileStatement(WhileStatement { body, .. }) | AstKind::DoWhileStatement(DoWhileStatement { body, .. }) diff --git a/crates/oxc_semantic/src/checker/typescript.rs b/crates/oxc_semantic/src/checker/typescript.rs index 9e26b01d209958..4d4735212b7996 100644 --- a/crates/oxc_semantic/src/checker/typescript.rs +++ b/crates/oxc_semantic/src/checker/typescript.rs @@ -438,3 +438,27 @@ pub fn check_object_property(prop: &ObjectProperty, ctx: &SemanticBuilder<'_>) { } } } + +/// The left-hand side of a 'for...of' statement cannot use a type annotation. (2483) +fn type_annotation_in_for_left(span: Span, is_for_in: bool) -> OxcDiagnostic { + let for_of_or_in = if is_for_in { "for...in" } else { "for...of" }; + ts_error( + "2483", + format!( + "The left-hand side of a '{for_of_or_in}' statement cannot use a type annotation.", + ), + ).with_label(span).with_help("This iterator's type will be inferred from the iterable. You can safely remove the type annotation.") +} + +pub fn check_for_statement_left(left: &ForStatementLeft, is_for_in: bool, ctx: &SemanticBuilder) { + let ForStatementLeft::VariableDeclaration(decls) = left else { + return; + }; + + for decl in &decls.declarations { + if decl.id.type_annotation.is_some() { + let span = decl.id.span(); + ctx.error(type_annotation_in_for_left(span, is_for_in)); + } + } +} diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index 4212ec2e49b551..43da562aed6fb3 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -3,7 +3,7 @@ commit: a709f989 parser_typescript Summary: AST Parsed : 6469/6479 (99.85%) Positive Passed: 6458/6479 (99.68%) -Negative Passed: 1226/5715 (21.45%) +Negative Passed: 1232/5715 (21.56%) 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 @@ -854,10 +854,8 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/firstMatchRe Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/fixTypeParameterInSignatureWithRestParameters.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/fixingTypeParametersRepeatedly2.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/flatArrayNoExcessiveStackDepth.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forIn.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forIn2.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forInStatement2.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forInStatement4.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forInStatement7.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forInStrictNullChecksNoError.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/forwardDeclaredCommonTypes01.ts @@ -3852,14 +3850,12 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement15.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement16.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement20.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement5.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement8.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement9.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserEmptyStatement1.d.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserExpressionStatement1.d.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement1.d.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement4.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement5.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement8.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement1.d.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement2.ts @@ -3964,7 +3960,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement15.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement16.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement20.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts @@ -4073,7 +4068,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statement Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-inStatements/for-inStatementsInvalid.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-ofStatements/ES5For-of17.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-ofStatements/ES5For-of26.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-ofStatements/ES5For-of27.ts @@ -7903,6 +7897,24 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 30 │ } ╰──── + × TS(2483): The left-hand side of a 'for...in' statement cannot use a type annotation. + ╭─[typescript/tests/cases/compiler/forIn.ts:2:10] + 1 │ var arr = null; + 2 │ for (var i:number in arr) { // error + · ──────── + 3 │ var x1 = arr[i]; + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + + × TS(2483): The left-hand side of a 'for...in' statement cannot use a type annotation. + ╭─[typescript/tests/cases/compiler/forInStatement4.ts:2:10] + 1 │ var expr: any; + 2 │ for (var a: number in expr) { + · ───────── + 3 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Identifier `foo3` has already been declared ╭─[typescript/tests/cases/compiler/funClodule.ts:15:10] 14 │ @@ -21479,6 +21491,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 2 │ } ╰──── + × TS(2483): The left-hand side of a 'for...of' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement5.ts:1:10] + 1 │ for (var a: number of X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Only a single declaration is allowed in a `for...of` statement ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement6.ts:1:6] 1 │ for (var a = 1, b = 2 of X) { @@ -21493,6 +21513,22 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 2 │ } ╰──── + × TS(2483): The left-hand side of a 'for...of' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement7.ts:1:10] + 1 │ for (var a: number = 1, b: string = "" of X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + + × TS(2483): The left-hand side of a 'for...of' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement7.ts:1:25] + 1 │ for (var a: number = 1, b: string = "" of X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Unexpected token ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement2.ts:1:10] 1 │ for (var in X) { @@ -21507,6 +21543,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 2 │ } ╰──── + × TS(2483): The left-hand side of a 'for...in' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement5.ts:1:10] + 1 │ for (var a: number in X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Only a single declaration is allowed in a `for...in` statement ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement6.ts:1:6] 1 │ for (var a = 1, b = 2 in X) { @@ -21521,6 +21565,22 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 2 │ } ╰──── + × TS(2483): The left-hand side of a 'for...in' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts:1:10] + 1 │ for (var a: number = 1, b: string = "" in X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + + × TS(2483): The left-hand side of a 'for...in' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts:1:25] + 1 │ for (var a: number = 1, b: string = "" in X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Unexpected token ╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement4.ts:1:6] 1 │ for (a = 1 in b) { @@ -21986,6 +22046,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 2 │ } ╰──── + × TS(2483): The left-hand side of a 'for...of' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts:1:10] + 1 │ for (var a: number of X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Only a single declaration is allowed in a `for...of` statement ╭─[typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts:1:6] 1 │ for (var a = 1, b = 2 of X) { @@ -22000,6 +22068,22 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 2 │ } ╰──── + × TS(2483): The left-hand side of a 'for...of' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts:1:10] + 1 │ for (var a: number = 1, b: string = "" of X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + + × TS(2483): The left-hand side of a 'for...of' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts:1:25] + 1 │ for (var a: number = 1, b: string = "" of X) { + · ───────── + 2 │ } + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Expected `,` but found `?` ╭─[typescript/tests/cases/conformance/parser/ecmascript6/ShorthandPropertyAssignment/parserShorthandPropertyAssignment1.ts:3:11] 2 │ var name:any, id: any; @@ -22936,6 +23020,15 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 38 │ } ╰──── + × TS(2483): The left-hand side of a 'for...in' statement cannot use a type annotation. + ╭─[typescript/tests/cases/conformance/statements/for-inStatements/for-inStatementsInvalid.ts:10:10] + 9 │ + 10 │ for (var idx : number in {}) { } + · ──────────── + 11 │ + ╰──── + help: This iterator's type will be inferred from the iterable. You can safely remove the type annotation. + × Unexpected token ╭─[typescript/tests/cases/conformance/statements/for-ofStatements/ES5For-of12.ts:1:6] 1 │ for ([""] of [[""]]) { }