diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ae1e9a398a2..23aa8dc92c9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8806,6 +8806,11 @@ module ts { // VarDecl must be a variable declaration without a type annotation that declares a variable of type Any, // and Expr must be an expression of type Any, an object type, or a type parameter type. if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { + var variable = (node.initializer).declarations[0]; + if (variable && isBindingPattern(variable.name)) { + error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); + } + checkForInOrForOfVariableDeclaration(node); } else { @@ -8815,7 +8820,10 @@ module ts { // and Expr must be an expression of type Any, an object type, or a type parameter type. var varExpr = node.initializer; var leftType = checkExpression(varExpr); - if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike)) { + if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { + error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); + } + else if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike)) { error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any); } else { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 08de6681226..7d1e4bcf34d 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -332,6 +332,7 @@ module ts { The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: DiagnosticCategory.Error, key: "The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator." }, The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method: { code: 2489, category: DiagnosticCategory.Error, key: "The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method." }, The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The object returned by the next method of the iterator must have a 'value' property." }, + The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 45661c570c2..81e451ef02a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1320,6 +1320,10 @@ "category": "Error", "code": 2490 }, + "The left-hand side of a 'for...in' statement cannot be a destructuring pattern.": { + "category": "Error", + "code": 2491 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", @@ -1596,7 +1600,7 @@ "Exported type alias '{0}' has or is using private name '{1}'.": { "category": "Error", "code": 4081 - }, + }, "The current host does not support the '{0}' option.": { "category": "Error", "code": 5001 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b53c0007248..ddcd58fd2d6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -665,7 +665,7 @@ module ts { } export function isBindingPattern(node: Node) { - return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern; + return !!node && (node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern); } export function isInAmbientContext(node: Node): boolean { diff --git a/tests/baselines/reference/for-inStatementsDestructuring.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring.errors.txt new file mode 100644 index 00000000000..e540b182cf5 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. + + +==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts (1 errors) ==== + for (var [a, b] in []) {} + ~~~~~~ +!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring.js b/tests/baselines/reference/for-inStatementsDestructuring.js new file mode 100644 index 00000000000..e5e00d5b3ab --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring.js @@ -0,0 +1,5 @@ +//// [for-inStatementsDestructuring.ts] +for (var [a, b] in []) {} + +//// [for-inStatementsDestructuring.js] +for (var _a = void 0, a = _a[0], b = _a[1] in []) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt new file mode 100644 index 00000000000..56d2436d4c7 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring2.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts(1,10): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. + + +==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts (1 errors) ==== + for (var {a, b} in []) {} + ~~~~~~ +!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring2.js b/tests/baselines/reference/for-inStatementsDestructuring2.js new file mode 100644 index 00000000000..41a6d30919f --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring2.js @@ -0,0 +1,5 @@ +//// [for-inStatementsDestructuring2.ts] +for (var {a, b} in []) {} + +//// [for-inStatementsDestructuring2.js] +for (var _a = void 0, a = _a.a, b = _a.b in []) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt new file mode 100644 index 00000000000..e3ce65f872d --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring3.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts(2,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. + + +==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts (1 errors) ==== + var a, b; + for ([a, b] in []) { } + ~~~~~~ +!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring3.js b/tests/baselines/reference/for-inStatementsDestructuring3.js new file mode 100644 index 00000000000..0970740acab --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring3.js @@ -0,0 +1,7 @@ +//// [for-inStatementsDestructuring3.ts] +var a, b; +for ([a, b] in []) { } + +//// [for-inStatementsDestructuring3.js] +var a, b; +for ([a, b] in []) { } diff --git a/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt b/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt new file mode 100644 index 00000000000..8d3fe2d1b53 --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring4.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts(2,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. + + +==== tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts (1 errors) ==== + var a, b; + for ({a, b} in []) { } + ~~~~~~ +!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. \ No newline at end of file diff --git a/tests/baselines/reference/for-inStatementsDestructuring4.js b/tests/baselines/reference/for-inStatementsDestructuring4.js new file mode 100644 index 00000000000..0cce61ac96d --- /dev/null +++ b/tests/baselines/reference/for-inStatementsDestructuring4.js @@ -0,0 +1,7 @@ +//// [for-inStatementsDestructuring4.ts] +var a, b; +for ({a, b} in []) { } + +//// [for-inStatementsDestructuring4.js] +var a, b; +for ({ a: a, b: b } in []) { } diff --git a/tests/baselines/reference/parserForStatement5.errors.txt b/tests/baselines/reference/parserForStatement5.errors.txt index 72c9bffce4c..ae1e855b765 100644 --- a/tests/baselines/reference/parserForStatement5.errors.txt +++ b/tests/baselines/reference/parserForStatement5.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement5.ts(1,6): error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'. +tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement5.ts(1,6): error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement5.ts(1,12): error TS2304: Cannot find name 'b'. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserForStatement5.ts (2 errors) ==== for ({} in b) { ~~ -!!! error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'. +!!! error TS2491: The left-hand side of a 'for...in' statement cannot be a destructuring pattern. ~ !!! error TS2304: Cannot find name 'b'. } \ No newline at end of file diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts new file mode 100644 index 00000000000..94868ef3bd6 --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts @@ -0,0 +1 @@ +for (var [a, b] in []) {} \ No newline at end of file diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts new file mode 100644 index 00000000000..8671acc675b --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts @@ -0,0 +1 @@ +for (var {a, b} in []) {} \ No newline at end of file diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts new file mode 100644 index 00000000000..411261dee43 --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts @@ -0,0 +1,2 @@ +var a, b; +for ([a, b] in []) { } \ No newline at end of file diff --git a/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts new file mode 100644 index 00000000000..816dd564b6a --- /dev/null +++ b/tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts @@ -0,0 +1,2 @@ +var a, b; +for ({a, b} in []) { } \ No newline at end of file