Skip to content

Commit

Permalink
feat(semantic): check for type annotations on left side of for..in
Browse files Browse the repository at this point in the history
…and `for..of` iterators (#6043)
  • Loading branch information
DonIsaac committed Sep 25, 2024
1 parent 8b2e9aa commit f866781
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 7 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_semantic/src/checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, .. })
Expand Down
24 changes: 24 additions & 0 deletions crates/oxc_semantic/src/checker/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,3 +479,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));
}
}
}
107 changes: 100 additions & 7 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: a709f989
parser_typescript Summary:
AST Parsed : 6469/6479 (99.85%)
Positive Passed: 6458/6479 (99.68%)
Negative Passed: 1228/5715 (21.49%)
Negative Passed: 1234/5715 (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 @@ -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
Expand Down Expand Up @@ -3850,14 +3848,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
Expand Down Expand Up @@ -3962,7 +3958,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
Expand Down Expand Up @@ -4071,7 +4066,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
Expand Down Expand Up @@ -7901,6 +7895,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 │
Expand Down Expand Up @@ -21644,6 +21656,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) {
Expand All @@ -21658,6 +21678,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) {
Expand All @@ -21672,6 +21708,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) {
Expand All @@ -21686,6 +21730,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) {
Expand Down Expand Up @@ -22151,6 +22211,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) {
Expand All @@ -22165,6 +22233,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;
Expand Down Expand Up @@ -23101,6 +23185,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 [[""]]) { }
Expand Down

0 comments on commit f866781

Please sign in to comment.