Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 'for...of' loops in ES6 #2164

Merged
merged 30 commits into from
Mar 2, 2015
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b6a4987
Remove error disallowing for...of loops
JsonFreeman Feb 20, 2015
9e9dcde
Fix naming in checkForInStatement
JsonFreeman Feb 20, 2015
e0d7734
Basic for...of checking
JsonFreeman Feb 20, 2015
aa06622
Basic tests
JsonFreeman Feb 20, 2015
277c931
Basic iterator support in for..of statement
JsonFreeman Feb 21, 2015
ec9e563
Add tests and accept correct baselines
JsonFreeman Feb 21, 2015
a2c5573
Get type of 'for...of' variables
JsonFreeman Feb 24, 2015
1043d87
Tests and baselines for 'for...of' variables
JsonFreeman Feb 24, 2015
2858771
Check iterable structure of the right hand side of 'for...of' statement
JsonFreeman Feb 24, 2015
3d5c113
Iterator tests
JsonFreeman Feb 24, 2015
0571086
More tests
JsonFreeman Feb 24, 2015
732637d
Fix getIteratedType to work with 'any' at all levels
JsonFreeman Feb 24, 2015
0049b21
Check for assignability to the relevant iteratable type
JsonFreeman Feb 25, 2015
034bd09
Add tests for circular references in for...of loops
JsonFreeman Feb 25, 2015
c00a264
Move assert
JsonFreeman Feb 25, 2015
f3543b7
In ES6, an Iterable should contextually type an array literal
JsonFreeman Feb 26, 2015
00408a6
Add tests for for-of destructuring
JsonFreeman Feb 26, 2015
79b609b
Update comment
JsonFreeman Feb 26, 2015
9faa09b
Delete bad baseline
JsonFreeman Feb 26, 2015
f8150d3
Support assignment patterns in 'for...of' statements
JsonFreeman Feb 26, 2015
84a22be
Add a few more tests
JsonFreeman Feb 26, 2015
fd0fd36
Disallow destructuring in 'for...in'
JsonFreeman Feb 27, 2015
996b9d2
Respond to PR feedback
JsonFreeman Feb 27, 2015
14ba418
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
JsonFreeman Feb 27, 2015
bcb466e
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
JsonFreeman Feb 28, 2015
3de73e6
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
JsonFreeman Mar 1, 2015
8da49aa
Address feedback
JsonFreeman Mar 2, 2015
cb97686
Add tests for scoping
JsonFreeman Mar 2, 2015
7dd7b43
Add one more test
JsonFreeman Mar 2, 2015
e0227d1
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
JsonFreeman Mar 2, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
300 changes: 224 additions & 76 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,13 @@ module ts {
for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher: { code: 2482, category: DiagnosticCategory.Error, key: "'for...of' statements are only available when targeting ECMAScript 6 or higher." },
The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: { code: 2483, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot use a type annotation." },
Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2484, category: DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" },
The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: { code: 2486, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant." },
Invalid_left_hand_side_in_for_of_statement: { code: 2487, category: DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...of' statement." },
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}'." },
Expand Down Expand Up @@ -471,6 +478,5 @@ module ts {
yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." },
The_arguments_object_cannot_be_referenced_in_an_arrow_function_Consider_using_a_standard_function_expression: { code: 9002, category: DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression." },
for_of_statements_are_not_currently_supported: { code: 9003, category: DiagnosticCategory.Error, key: "'for...of' statements are not currently supported." },
};
}
34 changes: 29 additions & 5 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,34 @@
"category": "Error",
"code": 2484
},
"The left-hand side of a 'for...of' statement cannot be a previously defined constant.": {
"category": "Error",
"code": 2485
},
"The left-hand side of a 'for...in' statement cannot be a previously defined constant.": {
"category": "Error",
"code": 2486
},
"Invalid left-hand side in 'for...of' statement.": {
"category": "Error",
"code": 2487
},
"The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator.": {
"category": "Error",
"code": 2488
},
"The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method.": {
"category": "Error",
"code": 2489
},
"The object returned by the next method of the iterator must have a 'value' property.": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent with the last message - next should have parens and single-quotes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be "of an iterator"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're totally right about next. I will fix that.

I see your point. I guess unqualified noun phrases should be indefinite. So in a possessive chain of noun phrases, the tail should be indefinite, but all the preceding ones can be definite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be 'The object' or 'The type' in the beginning?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be 'The type', or if not, 'The value'.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make it type.

"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",
Expand Down Expand Up @@ -1572,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
Expand Down Expand Up @@ -1877,9 +1905,5 @@
"The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression.": {
"category": "Error",
"code": 9002
},
"'for...of' statements are not currently supported.": {
"category": "Error",
"code": 9003
}
}
2 changes: 1 addition & 1 deletion src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ tests/cases/compiler/constDeclarations-errors.ts(5,7): error TS1155: 'const' dec
tests/cases/compiler/constDeclarations-errors.ts(5,11): error TS1155: 'const' declarations must be initialized
tests/cases/compiler/constDeclarations-errors.ts(5,15): error TS1155: 'const' declarations must be initialized
tests/cases/compiler/constDeclarations-errors.ts(5,27): error TS1155: 'const' declarations must be initialized
tests/cases/compiler/constDeclarations-errors.ts(8,11): error TS1155: 'const' declarations must be initialized
tests/cases/compiler/constDeclarations-errors.ts(11,27): error TS2449: The operand of an increment or decrement operator cannot be a constant.
tests/cases/compiler/constDeclarations-errors.ts(14,11): error TS1155: 'const' declarations must be initialized
tests/cases/compiler/constDeclarations-errors.ts(17,20): error TS1155: 'const' declarations must be initialized


==== tests/cases/compiler/constDeclarations-errors.ts (10 errors) ====
==== tests/cases/compiler/constDeclarations-errors.ts (9 errors) ====

// error, missing intialicer
const c1;
Expand All @@ -31,8 +30,6 @@ tests/cases/compiler/constDeclarations-errors.ts(17,20): error TS1155: 'const' d

// error, can not be unintalized
for(const c in {}) { }
~
!!! error TS1155: 'const' declarations must be initialized

// error, assigning to a const
for(const c8 = 0; c8 < 1; c8++) { }
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 5 additions & 0 deletions tests/baselines/reference/for-inStatementsDestructuring.js
Original file line number Diff line number Diff line change
@@ -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 []) { }
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 5 additions & 0 deletions tests/baselines/reference/for-inStatementsDestructuring2.js
Original file line number Diff line number Diff line change
@@ -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 []) { }
Original file line number Diff line number Diff line change
@@ -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.
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-inStatementsDestructuring3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [for-inStatementsDestructuring3.ts]
var a, b;
for ([a, b] in []) { }

//// [for-inStatementsDestructuring3.js]
var a, b;
for ([a, b] in []) { }
Original file line number Diff line number Diff line change
@@ -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.
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-inStatementsDestructuring4.js
Original file line number Diff line number Diff line change
@@ -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 []) { }
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-of1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [for-of1.ts]
var v;
for (v of []) { }

//// [for-of1.js]
var v;
for (v of []) { }
8 changes: 8 additions & 0 deletions tests/baselines/reference/for-of1.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/for-ofStatements/for-of1.ts ===
var v;
>v : any

for (v of []) { }
>v : any
>[] : undefined[]

8 changes: 8 additions & 0 deletions tests/baselines/reference/for-of10.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
tests/cases/conformance/es6/for-ofStatements/for-of10.ts(2,6): error TS2322: Type 'number' is not assignable to type 'string'.


==== tests/cases/conformance/es6/for-ofStatements/for-of10.ts (1 errors) ====
var v: string;
for (v of [0]) { }
~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-of10.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [for-of10.ts]
var v: string;
for (v of [0]) { }

//// [for-of10.js]
var v;
for (v of [0]) { }
10 changes: 10 additions & 0 deletions tests/baselines/reference/for-of11.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
tests/cases/conformance/es6/for-ofStatements/for-of11.ts(2,6): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.


==== tests/cases/conformance/es6/for-ofStatements/for-of11.ts (1 errors) ====
var v: string;
for (v of [0, ""]) { }
~
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-of11.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [for-of11.ts]
var v: string;
for (v of [0, ""]) { }

//// [for-of11.js]
var v;
for (v of [0, ""]) { }
10 changes: 10 additions & 0 deletions tests/baselines/reference/for-of12.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
tests/cases/conformance/es6/for-ofStatements/for-of12.ts(2,6): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.


==== tests/cases/conformance/es6/for-ofStatements/for-of12.ts (1 errors) ====
var v: string;
for (v of [0, ""].values()) { }
~
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-of12.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [for-of12.ts]
var v: string;
for (v of [0, ""].values()) { }

//// [for-of12.js]
var v;
for (v of [0, ""].values()) { }
7 changes: 7 additions & 0 deletions tests/baselines/reference/for-of13.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [for-of13.ts]
var v: string;
for (v of [""].values()) { }

//// [for-of13.js]
var v;
for (v of [""].values()) { }
11 changes: 11 additions & 0 deletions tests/baselines/reference/for-of13.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=== tests/cases/conformance/es6/for-ofStatements/for-of13.ts ===
var v: string;
>v : string

for (v of [""].values()) { }
>v : string
>[""].values() : IterableIterator<string>
>[""].values : () => IterableIterator<string>
>[""] : string[]
>values : () => IterableIterator<string>

14 changes: 14 additions & 0 deletions tests/baselines/reference/for-of14.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tests/cases/conformance/es6/for-ofStatements/for-of14.ts(2,11): error TS2488: The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator.


==== tests/cases/conformance/es6/for-ofStatements/for-of14.ts (1 errors) ====
var v: string;
for (v of new StringIterator) { } // Should fail because the iterator is not iterable
~~~~~~~~~~~~~~~~~~
!!! error TS2488: The right-hand side of a 'for...of' statement must have a '[Symbol.iterator]()' method that returns an iterator.

class StringIterator {
next() {
return "";
}
}
21 changes: 21 additions & 0 deletions tests/baselines/reference/for-of14.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [for-of14.ts]
var v: string;
for (v of new StringIterator) { } // Should fail because the iterator is not iterable

class StringIterator {
next() {
return "";
}
}

//// [for-of14.js]
var v;
for (v of new StringIterator) { } // Should fail because the iterator is not iterable
var StringIterator = (function () {
function StringIterator() {
}
StringIterator.prototype.next = function () {
return "";
};
return StringIterator;
})();
17 changes: 17 additions & 0 deletions tests/baselines/reference/for-of15.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
tests/cases/conformance/es6/for-ofStatements/for-of15.ts(2,11): error TS2490: The object returned by the next method of the iterator must have a 'value' property.


==== tests/cases/conformance/es6/for-ofStatements/for-of15.ts (1 errors) ====
var v: string;
for (v of new StringIterator) { } // Should fail
~~~~~~~~~~~~~~~~~~
!!! error TS2490: The object returned by the next method of the iterator must have a 'value' property.

class StringIterator {
next() {
return "";
}
[Symbol.iterator]() {
return this;
}
}
27 changes: 27 additions & 0 deletions tests/baselines/reference/for-of15.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//// [for-of15.ts]
var v: string;
for (v of new StringIterator) { } // Should fail

class StringIterator {
next() {
return "";
}
[Symbol.iterator]() {
return this;
}
}

//// [for-of15.js]
var v;
for (v of new StringIterator) { } // Should fail
var StringIterator = (function () {
function StringIterator() {
}
StringIterator.prototype.next = function () {
return "";
};
StringIterator.prototype[Symbol.iterator] = function () {
return this;
};
return StringIterator;
})();
14 changes: 14 additions & 0 deletions tests/baselines/reference/for-of16.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tests/cases/conformance/es6/for-ofStatements/for-of16.ts(2,11): error TS2489: The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method.


==== tests/cases/conformance/es6/for-ofStatements/for-of16.ts (1 errors) ====
var v: string;
for (v of new StringIterator) { } // Should fail
~~~~~~~~~~~~~~~~~~
!!! error TS2489: The iterator returned by the right-hand side of a 'for...of' statement must have a 'next()' method.

class StringIterator {
[Symbol.iterator]() {
return this;
}
}
21 changes: 21 additions & 0 deletions tests/baselines/reference/for-of16.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [for-of16.ts]
var v: string;
for (v of new StringIterator) { } // Should fail

class StringIterator {
[Symbol.iterator]() {
return this;
}
}

//// [for-of16.js]
var v;
for (v of new StringIterator) { } // Should fail
var StringIterator = (function () {
function StringIterator() {
}
StringIterator.prototype[Symbol.iterator] = function () {
return this;
};
return StringIterator;
})();
Loading