From b6a4987103becb4e9cf16673ab4af8ea56fa7cd2 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 19 Feb 2015 16:36:48 -0800 Subject: [PATCH 01/26] Remove error disallowing for...of loops --- src/compiler/checker.ts | 2 -- src/compiler/diagnosticInformationMap.generated.ts | 1 - src/compiler/diagnosticMessages.json | 4 ---- .../reference/parserES5ForOfStatement1.d.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement10.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement11.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement12.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement13.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement14.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement15.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement16.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement18.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement2.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement21.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement3.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement4.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement5.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement6.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement7.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement8.errors.txt | 4 ++-- .../reference/parserES5ForOfStatement9.errors.txt | 4 ++-- .../reference/parserForOfStatement1.d.errors.txt | 4 ++-- .../baselines/reference/parserForOfStatement10.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement11.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement12.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement13.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement14.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement15.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement16.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement18.errors.txt | 7 ------- .../baselines/reference/parserForOfStatement2.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement21.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement3.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement4.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement5.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement6.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement7.errors.txt | 6 +++--- .../baselines/reference/parserForOfStatement8.errors.txt | 8 -------- .../baselines/reference/parserForOfStatement9.errors.txt | 8 -------- 39 files changed, 59 insertions(+), 145 deletions(-) delete mode 100644 tests/baselines/reference/parserForOfStatement10.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement11.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement12.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement13.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement14.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement15.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement16.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement18.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement8.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement9.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d666da91fe0..a92e77f6978 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11246,8 +11246,6 @@ module ts { } function checkGrammarForOfStatement(forOfStatement: ForOfStatement): boolean { - // Temporarily disallow for-of statements until type check work is complete. - return grammarErrorOnFirstToken(forOfStatement, Diagnostics.for_of_statements_are_not_currently_supported); if (languageVersion < ScriptTarget.ES6) { return grammarErrorOnFirstToken(forOfStatement, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher); } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 7c53d70f591..5f8be858627 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -471,6 +471,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." }, }; } \ No newline at end of file diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7a7efe4e43c..b7102337ef6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1877,9 +1877,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 } } diff --git a/tests/baselines/reference/parserES5ForOfStatement1.d.errors.txt b/tests/baselines/reference/parserES5ForOfStatement1.d.errors.txt index 9c1a39b1f4a..c280b597b2c 100644 --- a/tests/baselines/reference/parserES5ForOfStatement1.d.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement1.d.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement1.d.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement1.d.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement1.d.ts (1 errors) ==== for (var i of e) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement10.errors.txt b/tests/baselines/reference/parserES5ForOfStatement10.errors.txt index d7f411b1879..5cee7472d24 100644 --- a/tests/baselines/reference/parserES5ForOfStatement10.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement10.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement10.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement10.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement10.ts (1 errors) ==== for (const v of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement11.errors.txt b/tests/baselines/reference/parserES5ForOfStatement11.errors.txt index 48805a336c7..79b16ed1ad6 100644 --- a/tests/baselines/reference/parserES5ForOfStatement11.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement11.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement11.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement11.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement11.ts (1 errors) ==== for (const [a, b] of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement12.errors.txt b/tests/baselines/reference/parserES5ForOfStatement12.errors.txt index 3b9f242b975..cdb6db690cf 100644 --- a/tests/baselines/reference/parserES5ForOfStatement12.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement12.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement12.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement12.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement12.ts (1 errors) ==== for (const {a, b} of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement13.errors.txt b/tests/baselines/reference/parserES5ForOfStatement13.errors.txt index 8b8c8ce0868..9d97fd9e249 100644 --- a/tests/baselines/reference/parserES5ForOfStatement13.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement13.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement13.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement13.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement13.ts (1 errors) ==== for (let {a, b} of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement14.errors.txt b/tests/baselines/reference/parserES5ForOfStatement14.errors.txt index dc4db95270a..303439ec447 100644 --- a/tests/baselines/reference/parserES5ForOfStatement14.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement14.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement14.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement14.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement14.ts (1 errors) ==== for (let [a, b] of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement15.errors.txt b/tests/baselines/reference/parserES5ForOfStatement15.errors.txt index 07aa6dd5b37..f0eab288fa7 100644 --- a/tests/baselines/reference/parserES5ForOfStatement15.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement15.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement15.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement15.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement15.ts (1 errors) ==== for (var [a, b] of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement16.errors.txt b/tests/baselines/reference/parserES5ForOfStatement16.errors.txt index 15a3e4f7f0b..b9248140f33 100644 --- a/tests/baselines/reference/parserES5ForOfStatement16.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement16.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement16.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement16.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement16.ts (1 errors) ==== for (var {a, b} of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement18.errors.txt b/tests/baselines/reference/parserES5ForOfStatement18.errors.txt index fc314e51012..e123be9c4f7 100644 --- a/tests/baselines/reference/parserES5ForOfStatement18.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement18.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement18.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement18.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement18.ts (1 errors) ==== for (var of of of) { } ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. \ No newline at end of file +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement2.errors.txt b/tests/baselines/reference/parserES5ForOfStatement2.errors.txt index 347ae29ddb8..618e2f3f0ae 100644 --- a/tests/baselines/reference/parserES5ForOfStatement2.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement2.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement2.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement2.ts (1 errors) ==== for (var of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement21.errors.txt b/tests/baselines/reference/parserES5ForOfStatement21.errors.txt index 2ddbf4b5666..14d97f49faf 100644 --- a/tests/baselines/reference/parserES5ForOfStatement21.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement21.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement21.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement21.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement21.ts (1 errors) ==== for (var of of) { } ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. \ No newline at end of file +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement3.errors.txt b/tests/baselines/reference/parserES5ForOfStatement3.errors.txt index 553ca40aee0..dd888a3120a 100644 --- a/tests/baselines/reference/parserES5ForOfStatement3.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement3.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement3.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement3.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement3.ts (1 errors) ==== for (var a, b of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement4.errors.txt b/tests/baselines/reference/parserES5ForOfStatement4.errors.txt index 6a08c8942ed..b94de56b17c 100644 --- a/tests/baselines/reference/parserES5ForOfStatement4.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement4.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement4.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement4.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement4.ts (1 errors) ==== for (var a = 1 of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement5.errors.txt b/tests/baselines/reference/parserES5ForOfStatement5.errors.txt index 212eae8ac10..0b8dafc0b90 100644 --- a/tests/baselines/reference/parserES5ForOfStatement5.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement5.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement5.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement5.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement5.ts (1 errors) ==== for (var a: number of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement6.errors.txt b/tests/baselines/reference/parserES5ForOfStatement6.errors.txt index e331b66eb85..04ac84fbd73 100644 --- a/tests/baselines/reference/parserES5ForOfStatement6.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement6.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement6.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement6.ts (1 errors) ==== for (var a = 1, b = 2 of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement7.errors.txt b/tests/baselines/reference/parserES5ForOfStatement7.errors.txt index 5ba60c264eb..1def5279f65 100644 --- a/tests/baselines/reference/parserES5ForOfStatement7.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement7.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement7.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement7.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement7.ts (1 errors) ==== for (var a: number = 1, b: string = "" of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement8.errors.txt b/tests/baselines/reference/parserES5ForOfStatement8.errors.txt index 3696bf11f8c..829fea57e6e 100644 --- a/tests/baselines/reference/parserES5ForOfStatement8.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement8.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement8.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement8.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement8.ts (1 errors) ==== for (var v of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ForOfStatement9.errors.txt b/tests/baselines/reference/parserES5ForOfStatement9.errors.txt index 6e2e9d05705..4cf082b4f15 100644 --- a/tests/baselines/reference/parserES5ForOfStatement9.errors.txt +++ b/tests/baselines/reference/parserES5ForOfStatement9.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement9.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement9.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement9.ts (1 errors) ==== for (let v of X) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement1.d.errors.txt b/tests/baselines/reference/parserForOfStatement1.d.errors.txt index 05af0a6f775..3b1b2a65922 100644 --- a/tests/baselines/reference/parserForOfStatement1.d.errors.txt +++ b/tests/baselines/reference/parserForOfStatement1.d.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts(1,1): error TS1036: Statements are not allowed in ambient contexts. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts (1 errors) ==== for (var i of e) { ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. +!!! error TS1036: Statements are not allowed in ambient contexts. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement10.errors.txt b/tests/baselines/reference/parserForOfStatement10.errors.txt deleted file mode 100644 index 570c319b51f..00000000000 --- a/tests/baselines/reference/parserForOfStatement10.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement10.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement10.ts (1 errors) ==== - for (const v of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement11.errors.txt b/tests/baselines/reference/parserForOfStatement11.errors.txt deleted file mode 100644 index f253a2d4295..00000000000 --- a/tests/baselines/reference/parserForOfStatement11.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement11.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement11.ts (1 errors) ==== - for (const [a, b] of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement12.errors.txt b/tests/baselines/reference/parserForOfStatement12.errors.txt deleted file mode 100644 index 07ef4498984..00000000000 --- a/tests/baselines/reference/parserForOfStatement12.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement12.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement12.ts (1 errors) ==== - for (const {a, b} of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement13.errors.txt b/tests/baselines/reference/parserForOfStatement13.errors.txt deleted file mode 100644 index 6c10a7b0582..00000000000 --- a/tests/baselines/reference/parserForOfStatement13.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement13.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement13.ts (1 errors) ==== - for (let {a, b} of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement14.errors.txt b/tests/baselines/reference/parserForOfStatement14.errors.txt deleted file mode 100644 index 209a39c0513..00000000000 --- a/tests/baselines/reference/parserForOfStatement14.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement14.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement14.ts (1 errors) ==== - for (let [a, b] of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement15.errors.txt b/tests/baselines/reference/parserForOfStatement15.errors.txt deleted file mode 100644 index c5fd77af299..00000000000 --- a/tests/baselines/reference/parserForOfStatement15.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement15.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement15.ts (1 errors) ==== - for (var [a, b] of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement16.errors.txt b/tests/baselines/reference/parserForOfStatement16.errors.txt deleted file mode 100644 index d169eef1256..00000000000 --- a/tests/baselines/reference/parserForOfStatement16.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement16.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement16.ts (1 errors) ==== - for (var {a, b} of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement18.errors.txt b/tests/baselines/reference/parserForOfStatement18.errors.txt deleted file mode 100644 index 9312af76fc1..00000000000 --- a/tests/baselines/reference/parserForOfStatement18.errors.txt +++ /dev/null @@ -1,7 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement18.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement18.ts (1 errors) ==== - for (var of of of) { } - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement2.errors.txt b/tests/baselines/reference/parserForOfStatement2.errors.txt index 8e7da497308..7229fe4196d 100644 --- a/tests/baselines/reference/parserForOfStatement2.errors.txt +++ b/tests/baselines/reference/parserForOfStatement2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement2.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement2.ts(1,9): error TS1123: Variable declaration list cannot be empty. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement2.ts (1 errors) ==== for (var of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. + +!!! error TS1123: Variable declaration list cannot be empty. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement21.errors.txt b/tests/baselines/reference/parserForOfStatement21.errors.txt index dad48f415cd..9103e2fedee 100644 --- a/tests/baselines/reference/parserForOfStatement21.errors.txt +++ b/tests/baselines/reference/parserForOfStatement21.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement21.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement21.ts(1,9): error TS1123: Variable declaration list cannot be empty. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement21.ts (1 errors) ==== for (var of of) { } - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. \ No newline at end of file + +!!! error TS1123: Variable declaration list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement3.errors.txt b/tests/baselines/reference/parserForOfStatement3.errors.txt index 83985f1a710..995ef4637c2 100644 --- a/tests/baselines/reference/parserForOfStatement3.errors.txt +++ b/tests/baselines/reference/parserForOfStatement3.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts(1,13): error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts (1 errors) ==== for (var a, b of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. + ~ +!!! error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement4.errors.txt b/tests/baselines/reference/parserForOfStatement4.errors.txt index 94dd08ed597..65b4bf342f2 100644 --- a/tests/baselines/reference/parserForOfStatement4.errors.txt +++ b/tests/baselines/reference/parserForOfStatement4.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts(1,10): error TS1190: The variable declaration of a 'for...of' statement cannot have an initializer. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts (1 errors) ==== for (var a = 1 of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. + ~ +!!! error TS1190: The variable declaration of a 'for...of' statement cannot have an initializer. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement5.errors.txt b/tests/baselines/reference/parserForOfStatement5.errors.txt index 6570f4a0755..13fd8739866 100644 --- a/tests/baselines/reference/parserForOfStatement5.errors.txt +++ b/tests/baselines/reference/parserForOfStatement5.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts(1,10): error TS2483: The left-hand side of a 'for...of' statement cannot use a type annotation. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts (1 errors) ==== for (var a: number of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. + ~ +!!! error TS2483: The left-hand side of a 'for...of' statement cannot use a type annotation. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement6.errors.txt b/tests/baselines/reference/parserForOfStatement6.errors.txt index 6208749911f..57d95361b65 100644 --- a/tests/baselines/reference/parserForOfStatement6.errors.txt +++ b/tests/baselines/reference/parserForOfStatement6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts(1,17): error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts (1 errors) ==== for (var a = 1, b = 2 of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. + ~ +!!! error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement7.errors.txt b/tests/baselines/reference/parserForOfStatement7.errors.txt index 1810daad5ee..07f93c263ec 100644 --- a/tests/baselines/reference/parserForOfStatement7.errors.txt +++ b/tests/baselines/reference/parserForOfStatement7.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts(1,1): error TS9003: 'for...of' statements are not currently supported. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts(1,25): error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. ==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts (1 errors) ==== for (var a: number = 1, b: string = "" of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. + ~ +!!! error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement8.errors.txt b/tests/baselines/reference/parserForOfStatement8.errors.txt deleted file mode 100644 index 8e2c41d0cef..00000000000 --- a/tests/baselines/reference/parserForOfStatement8.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts (1 errors) ==== - for (var v of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement9.errors.txt b/tests/baselines/reference/parserForOfStatement9.errors.txt deleted file mode 100644 index 01fd729e9cd..00000000000 --- a/tests/baselines/reference/parserForOfStatement9.errors.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts(1,1): error TS9003: 'for...of' statements are not currently supported. - - -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts (1 errors) ==== - for (let v of X) { - ~~~ -!!! error TS9003: 'for...of' statements are not currently supported. - } \ No newline at end of file From 9e9dcdeca2da3a4e30907610a16412210968d4b1 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 19 Feb 2015 18:19:19 -0800 Subject: [PATCH 02/26] Fix naming in checkForInStatement --- src/compiler/checker.ts | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a92e77f6978..39d963712b0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8747,8 +8747,13 @@ module ts { } function checkForOfStatement(node: ForOfStatement) { - // TODO: not yet implemented - checkGrammarForOfStatement(node); + if (languageVersion < ScriptTarget.ES6) { + return grammarErrorOnFirstToken(node, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher); + } + + checkGrammarForInOrForOfStatement(node); + + // Check the expr } function checkForInStatement(node: ForInStatement) { @@ -8773,8 +8778,8 @@ module ts { // Var must be an expression classified as a reference of type Any or the String primitive type, // and Expr must be an expression of type Any, an object type, or a type parameter type. var varExpr = node.initializer; - var exprType = checkExpression(varExpr); - if (!allConstituentTypesHaveKind(exprType, TypeFlags.Any | TypeFlags.StringLike)) { + var leftType = checkExpression(varExpr); + 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 { @@ -8783,10 +8788,10 @@ module ts { } } - var exprType = checkExpression(node.expression); + var rightType = checkExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!allConstituentTypesHaveKind(exprType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) { + if (!allConstituentTypesHaveKind(rightType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } @@ -11245,14 +11250,6 @@ module ts { return false; } - function checkGrammarForOfStatement(forOfStatement: ForOfStatement): boolean { - if (languageVersion < ScriptTarget.ES6) { - return grammarErrorOnFirstToken(forOfStatement, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher); - } - - return checkGrammarForInOrForOfStatement(forOfStatement); - } - function checkGrammarAccessor(accessor: MethodDeclaration): boolean { var kind = accessor.kind; if (languageVersion < ScriptTarget.ES5) { From e0d77346996e08d615850b34d104532de9eb0f44 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 19 Feb 2015 19:24:54 -0800 Subject: [PATCH 03/26] Basic for...of checking --- src/compiler/checker.ts | 106 ++++++++++-------- .../diagnosticInformationMap.generated.ts | 3 + src/compiler/diagnosticMessages.json | 12 ++ 3 files changed, 77 insertions(+), 44 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 39d963712b0..cfe7134c741 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -595,13 +595,13 @@ module ts { } if (name.kind === SyntaxKind.Identifier) { - var symbol = resolveName(location,(name).text, meaning, Diagnostics.Cannot_find_name_0, name); + var symbol = resolveName(location, (name).text, meaning, Diagnostics.Cannot_find_name_0, name); if (!symbol) { return; } } else if (name.kind === SyntaxKind.QualifiedName) { - var namespace = resolveEntityName(location,(name).left, SymbolFlags.Namespace); + var namespace = resolveEntityName(location, (name).left, SymbolFlags.Namespace); if (!namespace || namespace === unknownSymbol || getFullWidth((name).right) === 0) return; var symbol = getSymbol(getExportsOfSymbol(namespace), (name).right.text, meaning); if (!symbol) { @@ -3536,7 +3536,7 @@ module ts { isContextSensitive((node).whenFalse); case SyntaxKind.BinaryExpression: return (node).operatorToken.kind === SyntaxKind.BarBarToken && - (isContextSensitive((node).left) || isContextSensitive((node).right)); + (isContextSensitive((node).left) || isContextSensitive((node).right)); case SyntaxKind.PropertyAssignment: return isContextSensitive((node).initializer); case SyntaxKind.MethodDeclaration: @@ -5002,7 +5002,7 @@ module ts { break; case SyntaxKind.PrefixUnaryExpression: if ((expr).operator === SyntaxKind.ExclamationToken) { - return narrowType(type,(expr).operand, !assumeTrue); + return narrowType(type, (expr).operand, !assumeTrue); } break; } @@ -5073,7 +5073,7 @@ module ts { nodeLinks.importOnRightSide = symbol; } } - + if (symbolLinks.referenced) { markLinkedImportsAsReferenced(getDeclarationOfKind(symbol, SyntaxKind.ImportEqualsDeclaration)); } @@ -5198,20 +5198,20 @@ module ts { if (container && container.parent && container.parent.kind === SyntaxKind.ClassDeclaration) { if (container.flags & NodeFlags.Static) { canUseSuperExpression = - container.kind === SyntaxKind.MethodDeclaration || - container.kind === SyntaxKind.MethodSignature || - container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor; + container.kind === SyntaxKind.MethodDeclaration || + container.kind === SyntaxKind.MethodSignature || + container.kind === SyntaxKind.GetAccessor || + container.kind === SyntaxKind.SetAccessor; } else { canUseSuperExpression = - container.kind === SyntaxKind.MethodDeclaration || - container.kind === SyntaxKind.MethodSignature || - container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor || - container.kind === SyntaxKind.PropertyDeclaration || - container.kind === SyntaxKind.PropertySignature || - container.kind === SyntaxKind.Constructor; + container.kind === SyntaxKind.MethodDeclaration || + container.kind === SyntaxKind.MethodSignature || + container.kind === SyntaxKind.GetAccessor || + container.kind === SyntaxKind.SetAccessor || + container.kind === SyntaxKind.PropertyDeclaration || + container.kind === SyntaxKind.PropertySignature || + container.kind === SyntaxKind.Constructor; } } } @@ -5441,7 +5441,7 @@ module ts { return propertyType; } } - + return isNumericName(element.name) && getIndexTypeOfContextualType(type, IndexKind.Number) || getIndexTypeOfContextualType(type, IndexKind.String); } @@ -6034,7 +6034,7 @@ module ts { if (!leftHandSideSymbol) { return false; } - + var globalESSymbol = getGlobalESSymbolConstructorSymbol(); if (!globalESSymbol) { // Already errored when we tried to look up the symbol @@ -6308,7 +6308,7 @@ module ts { // unless we're reporting errors var argType = i === 0 && node.kind === SyntaxKind.TaggedTemplateExpression ? globalTemplateStringsArrayType : arg.kind === SyntaxKind.StringLiteral && !reportErrors ? getStringLiteralType(arg) : - checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); // Use argument expression as error location when reporting errors if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined, Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) { @@ -6933,7 +6933,7 @@ module ts { if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { checkCollisionWithCapturedSuperVariable(node, (node).name); - checkCollisionWithCapturedThisVariable(node,(node).name); + checkCollisionWithCapturedThisVariable(node, (node).name); } return type; @@ -7226,7 +7226,7 @@ module ts { var propName = "" + i; var type = sourceType.flags & TypeFlags.Any ? sourceType : isTupleLikeType(sourceType) ? getTypeOfPropertyOfType(sourceType, propName) : - getIndexTypeOfType(sourceType, IndexKind.Number); + getIndexTypeOfType(sourceType, IndexKind.Number); if (type) { checkDestructuringAssignment(e, type, contextualMapper); } @@ -7380,7 +7380,7 @@ module ts { if (!checkForDisallowedESSymbolOperand(operator)) { return booleanType; } - // Fall through + // Fall through case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: @@ -7408,8 +7408,8 @@ module ts { function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { var offendingSymbolOperand = someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left : - someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? node.right : - undefined; + someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? node.right : + undefined; if (offendingSymbolOperand) { error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator)); return false; @@ -7708,8 +7708,8 @@ module ts { } // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled else if (node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.ConstructorType || - node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor || - node.kind === SyntaxKind.ConstructSignature){ + node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor || + node.kind === SyntaxKind.ConstructSignature) { checkGrammarFunctionLikeDeclaration(node); } @@ -8319,9 +8319,9 @@ module ts { function checkFunctionDeclaration(node: FunctionDeclaration): void { if (produceDiagnostics) { checkFunctionLikeDeclaration(node) || - checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || - checkGrammarFunctionName(node.name) || - checkGrammarForGenerator(node); + checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || + checkGrammarFunctionName(node.name) || + checkGrammarForGenerator(node); checkCollisionWithCapturedSuperVariable(node, node.name); checkCollisionWithCapturedThisVariable(node, node.name); @@ -8428,7 +8428,7 @@ module ts { return true; } - + function checkCollisionWithCapturedThisVariable(node: Node, name: Identifier): void { if (needCollisionCheckForIdentifier(node, name, "_this")) { potentialThisCollisions.push(node); @@ -8438,7 +8438,7 @@ module ts { // this function will run after checking the source file so 'CaptureThis' is correct for all nodes function checkIfThisIsCapturedInEnclosingScope(node: Node): void { var current = node; - while (current) { + while (current) { if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) { var isDeclaration = node.kind !== SyntaxKind.Identifier; if (isDeclaration) { @@ -8539,8 +8539,8 @@ module ts { var namesShareScope = container && (container.kind === SyntaxKind.Block && isAnyFunction(container.parent) || - (container.kind === SyntaxKind.ModuleBlock && container.kind === SyntaxKind.ModuleDeclaration) || - container.kind === SyntaxKind.SourceFile); + (container.kind === SyntaxKind.ModuleBlock && container.kind === SyntaxKind.ModuleDeclaration) || + container.kind === SyntaxKind.SourceFile); // here we know that function scoped variable is shadowed by block scoped one // if they are defined in the same scope - binder has already reported redeclaration error @@ -8746,14 +8746,28 @@ module ts { checkSourceElement(node.statement); } - function checkForOfStatement(node: ForOfStatement) { + function checkForOfStatement(node: ForOfStatement): void { if (languageVersion < ScriptTarget.ES6) { - return grammarErrorOnFirstToken(node, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher); + grammarErrorOnFirstToken(node, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher); + return; } - - checkGrammarForInOrForOfStatement(node); - // Check the expr + checkGrammarForInOrForOfStatement(node) + + // Check the LHS and RHS + // If decl: Check var decl, which will check the RHS + // If expr: Check LHS, check that it's a reference, and check that RHS is assignable to it, which will check RHS + if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { + checkForInOrForOfVariableDeclaration(node); + } + else { + var varExpr = node.initializer; + var leftType = checkExpression(varExpr); + checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); + var rightType = checkExpression(node.expression); + } + + checkSourceElement(node.statement); } function checkForInStatement(node: ForInStatement) { @@ -8766,11 +8780,7 @@ 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 variableDeclarationList = node.initializer; - if (variableDeclarationList.declarations.length >= 1) { - var decl = variableDeclarationList.declarations[0]; - checkVariableDeclaration(decl); - } + checkForInOrForOfVariableDeclaration(node); } else { // In a 'for-in' statement of the form @@ -8784,7 +8794,7 @@ module ts { } else { // run check only former check succeeded to avoid cascading errors - checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_in_statement, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant); + checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_in_statement, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant); } } @@ -8798,6 +8808,14 @@ module ts { checkSourceElement(node.statement); } + function checkForInOrForOfVariableDeclaration(iterationStatement: ForInStatement | ForOfStatement): void { + var variableDeclarationList = iterationStatement.initializer; + if (variableDeclarationList.declarations.length >= 1) { + var decl = variableDeclarationList.declarations[0]; + checkVariableDeclaration(decl); + } + } + function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node); diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 5f8be858627..35b5ca5cdc3 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -326,6 +326,9 @@ 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." }, 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 b7102337ef6..8b57778a696 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1296,6 +1296,18 @@ "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 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", From aa0662269567a84d150395bfd36c0c91cda98b31 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 20 Feb 2015 12:22:32 -0800 Subject: [PATCH 04/26] Basic tests --- tests/baselines/reference/for-of1.js | 7 +++++++ tests/baselines/reference/for-of1.types | 8 ++++++++ tests/baselines/reference/for-of2.errors.txt | 11 +++++++++++ tests/baselines/reference/for-of2.js | 7 +++++++ tests/baselines/reference/for-of3.errors.txt | 8 ++++++++ tests/baselines/reference/for-of3.js | 7 +++++++ tests/baselines/reference/for-of4.js | 9 +++++++++ tests/baselines/reference/for-of5.js | 9 +++++++++ tests/baselines/reference/for-of6.errors.txt | 9 +++++++++ tests/baselines/reference/for-of6.js | 9 +++++++++ tests/baselines/reference/for-of7.errors.txt | 8 ++++++++ tests/baselines/reference/for-of7.js | 7 +++++++ tests/baselines/reference/for-of8.js | 7 +++++++ .../cases/conformance/es6/for-ofStatements/for-of1.ts | 3 +++ .../cases/conformance/es6/for-ofStatements/for-of2.ts | 3 +++ .../cases/conformance/es6/for-ofStatements/for-of3.ts | 3 +++ .../cases/conformance/es6/for-ofStatements/for-of4.ts | 4 ++++ .../cases/conformance/es6/for-ofStatements/for-of5.ts | 4 ++++ .../cases/conformance/es6/for-ofStatements/for-of6.ts | 4 ++++ .../cases/conformance/es6/for-ofStatements/for-of7.ts | 3 +++ .../cases/conformance/es6/for-ofStatements/for-of8.ts | 3 +++ 21 files changed, 133 insertions(+) create mode 100644 tests/baselines/reference/for-of1.js create mode 100644 tests/baselines/reference/for-of1.types create mode 100644 tests/baselines/reference/for-of2.errors.txt create mode 100644 tests/baselines/reference/for-of2.js create mode 100644 tests/baselines/reference/for-of3.errors.txt create mode 100644 tests/baselines/reference/for-of3.js create mode 100644 tests/baselines/reference/for-of4.js create mode 100644 tests/baselines/reference/for-of5.js create mode 100644 tests/baselines/reference/for-of6.errors.txt create mode 100644 tests/baselines/reference/for-of6.js create mode 100644 tests/baselines/reference/for-of7.errors.txt create mode 100644 tests/baselines/reference/for-of7.js create mode 100644 tests/baselines/reference/for-of8.js create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of1.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of2.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of3.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of4.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of5.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of6.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of7.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of8.ts diff --git a/tests/baselines/reference/for-of1.js b/tests/baselines/reference/for-of1.js new file mode 100644 index 00000000000..9df6a96d78f --- /dev/null +++ b/tests/baselines/reference/for-of1.js @@ -0,0 +1,7 @@ +//// [for-of1.ts] +var v; +for (v of []) { } + +//// [for-of1.js] +var v; +for (v of []) { } diff --git a/tests/baselines/reference/for-of1.types b/tests/baselines/reference/for-of1.types new file mode 100644 index 00000000000..b21bb6046a7 --- /dev/null +++ b/tests/baselines/reference/for-of1.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of1.ts === +var v; +>v : any + +for (v of []) { } +>v : any +>[] : undefined[] + diff --git a/tests/baselines/reference/for-of2.errors.txt b/tests/baselines/reference/for-of2.errors.txt new file mode 100644 index 00000000000..0b5133cde13 --- /dev/null +++ b/tests/baselines/reference/for-of2.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/es6/for-ofStatements/for-of2.ts(1,7): error TS1155: 'const' declarations must be initialized +tests/cases/conformance/es6/for-ofStatements/for-of2.ts(2,6): error TS2485: The left-hand side of a 'for...of' statement cannot be a previously defined constant. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of2.ts (2 errors) ==== + const v; + ~ +!!! error TS1155: 'const' declarations must be initialized + for (v of []) { } + ~ +!!! error TS2485: The left-hand side of a 'for...of' statement cannot be a previously defined constant. \ No newline at end of file diff --git a/tests/baselines/reference/for-of2.js b/tests/baselines/reference/for-of2.js new file mode 100644 index 00000000000..d7eceb7c49e --- /dev/null +++ b/tests/baselines/reference/for-of2.js @@ -0,0 +1,7 @@ +//// [for-of2.ts] +const v; +for (v of []) { } + +//// [for-of2.js] +const v; +for (v of []) { } diff --git a/tests/baselines/reference/for-of3.errors.txt b/tests/baselines/reference/for-of3.errors.txt new file mode 100644 index 00000000000..973230003f9 --- /dev/null +++ b/tests/baselines/reference/for-of3.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/es6/for-ofStatements/for-of3.ts(2,6): error TS2486: Invalid left-hand side in 'for...of' statement. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of3.ts (1 errors) ==== + var v; + for (v++ of []) { } + ~~~ +!!! error TS2486: Invalid left-hand side in 'for...of' statement. \ No newline at end of file diff --git a/tests/baselines/reference/for-of3.js b/tests/baselines/reference/for-of3.js new file mode 100644 index 00000000000..7ef27187702 --- /dev/null +++ b/tests/baselines/reference/for-of3.js @@ -0,0 +1,7 @@ +//// [for-of3.ts] +var v; +for (v++ of []) { } + +//// [for-of3.js] +var v; +for (v++ of []) { } diff --git a/tests/baselines/reference/for-of4.js b/tests/baselines/reference/for-of4.js new file mode 100644 index 00000000000..147619d2fe2 --- /dev/null +++ b/tests/baselines/reference/for-of4.js @@ -0,0 +1,9 @@ +//// [for-of4.ts] +for (var v of [0]) { + v; +} + +//// [for-of4.js] +for (var v of [0]) { + v; +} diff --git a/tests/baselines/reference/for-of5.js b/tests/baselines/reference/for-of5.js new file mode 100644 index 00000000000..4d93b0bd483 --- /dev/null +++ b/tests/baselines/reference/for-of5.js @@ -0,0 +1,9 @@ +//// [for-of5.ts] +for (let v of [0]) { + v; +} + +//// [for-of5.js] +for (let v of [0]) { + v; +} diff --git a/tests/baselines/reference/for-of6.errors.txt b/tests/baselines/reference/for-of6.errors.txt new file mode 100644 index 00000000000..03f41d18b2b --- /dev/null +++ b/tests/baselines/reference/for-of6.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/es6/for-ofStatements/for-of6.ts(1,6): error TS2304: Cannot find name 'v'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of6.ts (1 errors) ==== + for (v of [0]) { + ~ +!!! error TS2304: Cannot find name 'v'. + let v; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of6.js b/tests/baselines/reference/for-of6.js new file mode 100644 index 00000000000..24e93e2a9fd --- /dev/null +++ b/tests/baselines/reference/for-of6.js @@ -0,0 +1,9 @@ +//// [for-of6.ts] +for (v of [0]) { + let v; +} + +//// [for-of6.js] +for (v of [0]) { + let v; +} diff --git a/tests/baselines/reference/for-of7.errors.txt b/tests/baselines/reference/for-of7.errors.txt new file mode 100644 index 00000000000..e67c51e2d96 --- /dev/null +++ b/tests/baselines/reference/for-of7.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/es6/for-ofStatements/for-of7.ts(1,1): error TS2304: Cannot find name 'v'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of7.ts (1 errors) ==== + v; + ~ +!!! error TS2304: Cannot find name 'v'. + for (let v of [0]) { } \ No newline at end of file diff --git a/tests/baselines/reference/for-of7.js b/tests/baselines/reference/for-of7.js new file mode 100644 index 00000000000..04aadd9736a --- /dev/null +++ b/tests/baselines/reference/for-of7.js @@ -0,0 +1,7 @@ +//// [for-of7.ts] +v; +for (let v of [0]) { } + +//// [for-of7.js] +v; +for (let v of [0]) { } diff --git a/tests/baselines/reference/for-of8.js b/tests/baselines/reference/for-of8.js new file mode 100644 index 00000000000..f33d69166dc --- /dev/null +++ b/tests/baselines/reference/for-of8.js @@ -0,0 +1,7 @@ +//// [for-of8.ts] +v; +for (var v of [0]) { } + +//// [for-of8.js] +v; +for (var v of [0]) { } diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of1.ts b/tests/cases/conformance/es6/for-ofStatements/for-of1.ts new file mode 100644 index 00000000000..b9e25f20606 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of1.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var v; +for (v of []) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of2.ts b/tests/cases/conformance/es6/for-ofStatements/for-of2.ts new file mode 100644 index 00000000000..77f72330dee --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of2.ts @@ -0,0 +1,3 @@ +//@target: ES6 +const v; +for (v of []) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of3.ts b/tests/cases/conformance/es6/for-ofStatements/for-of3.ts new file mode 100644 index 00000000000..7eb1e1fd220 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of3.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var v; +for (v++ of []) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of4.ts b/tests/cases/conformance/es6/for-ofStatements/for-of4.ts new file mode 100644 index 00000000000..d37925b67a0 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of4.ts @@ -0,0 +1,4 @@ +//@target: ES6 +for (var v of [0]) { + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of5.ts b/tests/cases/conformance/es6/for-ofStatements/for-of5.ts new file mode 100644 index 00000000000..2a581676b4b --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of5.ts @@ -0,0 +1,4 @@ +//@target: ES6 +for (let v of [0]) { + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of6.ts b/tests/cases/conformance/es6/for-ofStatements/for-of6.ts new file mode 100644 index 00000000000..1d8eccde01a --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of6.ts @@ -0,0 +1,4 @@ +//@target: ES6 +for (v of [0]) { + let v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of7.ts b/tests/cases/conformance/es6/for-ofStatements/for-of7.ts new file mode 100644 index 00000000000..5303278d910 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of7.ts @@ -0,0 +1,3 @@ +//@target: ES6 +v; +for (let v of [0]) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of8.ts b/tests/cases/conformance/es6/for-ofStatements/for-of8.ts new file mode 100644 index 00000000000..34bd4943c70 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of8.ts @@ -0,0 +1,3 @@ +//@target: ES6 +v; +for (var v of [0]) { } \ No newline at end of file From 277c931a0d87ad80102a0f4cb10ff86f45288feb Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 20 Feb 2015 17:09:03 -0800 Subject: [PATCH 05/26] Basic iterator support in for..of statement --- src/compiler/checker.ts | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cfe7134c741..1357d659e82 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8765,6 +8765,8 @@ module ts { var leftType = checkExpression(varExpr); checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); var rightType = checkExpression(node.expression); + var iteratedType = getIteratedType(rightType); + checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); } checkSourceElement(node.statement); @@ -8816,6 +8818,45 @@ module ts { } } + function getIteratedType(iterable: Type): Type { + Debug.assert(languageVersion >= ScriptTarget.ES6); + if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { + return anyType; + } + + // We want to treat type as an iterable, and get the type it is an iterable of. The iterable + // must have the following structure (annotated with the names of the variables below): + // + // { // iterable + // [Symbol.iterator]: { // iteratorFunction + // (): { // iterator + // next: { // iteratorNextFunction + // (): { // iteratorNextResult + // value: T // iteratorNextValue + // } + // } + // } + // } + // } + // + // T is the type we are after. At every level that involves analyzing return types + // of signatures, we union the return types of all the signatures. + var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); + var iteratorFunctionSignatures = getSignaturesOfType(iteratorFunction, SignatureKind.Call); + var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature)); + + var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next"); + var iteratorNextFunctionSignatures = getSignaturesOfType(iteratorNextFunction, SignatureKind.Call); + var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature)); + + var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); + + return iteratorNextValue; + // TODO + // Now even though we have extracted the iteratorNextValue, we will have to validate that the type + // passed in is actually an Iterable. + } + function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node); From ec9e5632386d35871a137cc6ad219d744dbb9704 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 20 Feb 2015 18:00:03 -0800 Subject: [PATCH 06/26] Add tests and accept correct baselines --- tests/baselines/reference/for-of10.errors.txt | 8 ++++++++ tests/baselines/reference/for-of10.js | 7 +++++++ tests/baselines/reference/for-of11.errors.txt | 10 ++++++++++ tests/baselines/reference/for-of11.js | 7 +++++++ tests/baselines/reference/for-of12.errors.txt | 10 ++++++++++ tests/baselines/reference/for-of12.js | 7 +++++++ tests/baselines/reference/for-of13.js | 7 +++++++ tests/baselines/reference/for-of13.types | 11 +++++++++++ tests/baselines/reference/for-of3.errors.txt | 4 ++-- tests/baselines/reference/for-of9.js | 9 +++++++++ tests/baselines/reference/for-of9.types | 11 +++++++++++ .../reference/parserForOfStatement18.types | 5 +++++ .../reference/parserForOfStatement8.types | 5 +++++ .../reference/parserForOfStatement9.types | 5 +++++ .../conformance/es6/for-ofStatements/for-of10.ts | 3 +++ .../conformance/es6/for-ofStatements/for-of11.ts | 3 +++ .../conformance/es6/for-ofStatements/for-of12.ts | 3 +++ .../conformance/es6/for-ofStatements/for-of13.ts | 3 +++ .../conformance/es6/for-ofStatements/for-of14.ts | 9 +++++++++ .../conformance/es6/for-ofStatements/for-of15.ts | 12 ++++++++++++ .../conformance/es6/for-ofStatements/for-of16.ts | 12 ++++++++++++ .../conformance/es6/for-ofStatements/for-of17.ts | 12 ++++++++++++ .../conformance/es6/for-ofStatements/for-of18.ts | 15 +++++++++++++++ .../conformance/es6/for-ofStatements/for-of19.ts | 15 +++++++++++++++ .../conformance/es6/for-ofStatements/for-of9.ts | 4 ++++ 25 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/for-of10.errors.txt create mode 100644 tests/baselines/reference/for-of10.js create mode 100644 tests/baselines/reference/for-of11.errors.txt create mode 100644 tests/baselines/reference/for-of11.js create mode 100644 tests/baselines/reference/for-of12.errors.txt create mode 100644 tests/baselines/reference/for-of12.js create mode 100644 tests/baselines/reference/for-of13.js create mode 100644 tests/baselines/reference/for-of13.types create mode 100644 tests/baselines/reference/for-of9.js create mode 100644 tests/baselines/reference/for-of9.types create mode 100644 tests/baselines/reference/parserForOfStatement18.types create mode 100644 tests/baselines/reference/parserForOfStatement8.types create mode 100644 tests/baselines/reference/parserForOfStatement9.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of10.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of11.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of12.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of13.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of14.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of15.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of16.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of17.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of18.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of19.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of9.ts diff --git a/tests/baselines/reference/for-of10.errors.txt b/tests/baselines/reference/for-of10.errors.txt new file mode 100644 index 00000000000..1636f1a02d0 --- /dev/null +++ b/tests/baselines/reference/for-of10.errors.txt @@ -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'. \ No newline at end of file diff --git a/tests/baselines/reference/for-of10.js b/tests/baselines/reference/for-of10.js new file mode 100644 index 00000000000..7fd05f5479b --- /dev/null +++ b/tests/baselines/reference/for-of10.js @@ -0,0 +1,7 @@ +//// [for-of10.ts] +var v: string; +for (v of [0]) { } + +//// [for-of10.js] +var v; +for (v of [0]) { } diff --git a/tests/baselines/reference/for-of11.errors.txt b/tests/baselines/reference/for-of11.errors.txt new file mode 100644 index 00000000000..dc527e73efe --- /dev/null +++ b/tests/baselines/reference/for-of11.errors.txt @@ -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'. \ No newline at end of file diff --git a/tests/baselines/reference/for-of11.js b/tests/baselines/reference/for-of11.js new file mode 100644 index 00000000000..055ed0039dc --- /dev/null +++ b/tests/baselines/reference/for-of11.js @@ -0,0 +1,7 @@ +//// [for-of11.ts] +var v: string; +for (v of [0, ""]) { } + +//// [for-of11.js] +var v; +for (v of [0, ""]) { } diff --git a/tests/baselines/reference/for-of12.errors.txt b/tests/baselines/reference/for-of12.errors.txt new file mode 100644 index 00000000000..f19fa5ed014 --- /dev/null +++ b/tests/baselines/reference/for-of12.errors.txt @@ -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'. \ No newline at end of file diff --git a/tests/baselines/reference/for-of12.js b/tests/baselines/reference/for-of12.js new file mode 100644 index 00000000000..6185ca8e331 --- /dev/null +++ b/tests/baselines/reference/for-of12.js @@ -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()) { } diff --git a/tests/baselines/reference/for-of13.js b/tests/baselines/reference/for-of13.js new file mode 100644 index 00000000000..e66668f1736 --- /dev/null +++ b/tests/baselines/reference/for-of13.js @@ -0,0 +1,7 @@ +//// [for-of13.ts] +var v: string; +for (v of [""].values()) { } + +//// [for-of13.js] +var v; +for (v of [""].values()) { } diff --git a/tests/baselines/reference/for-of13.types b/tests/baselines/reference/for-of13.types new file mode 100644 index 00000000000..4bb29c1e0ab --- /dev/null +++ b/tests/baselines/reference/for-of13.types @@ -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 +>[""].values : () => IterableIterator +>[""] : string[] +>values : () => IterableIterator + diff --git a/tests/baselines/reference/for-of3.errors.txt b/tests/baselines/reference/for-of3.errors.txt index 973230003f9..ba8e3e4a5c6 100644 --- a/tests/baselines/reference/for-of3.errors.txt +++ b/tests/baselines/reference/for-of3.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/es6/for-ofStatements/for-of3.ts(2,6): error TS2486: Invalid left-hand side in 'for...of' statement. +tests/cases/conformance/es6/for-ofStatements/for-of3.ts(2,6): error TS2487: Invalid left-hand side in 'for...of' statement. ==== tests/cases/conformance/es6/for-ofStatements/for-of3.ts (1 errors) ==== var v; for (v++ of []) { } ~~~ -!!! error TS2486: Invalid left-hand side in 'for...of' statement. \ No newline at end of file +!!! error TS2487: Invalid left-hand side in 'for...of' statement. \ No newline at end of file diff --git a/tests/baselines/reference/for-of9.js b/tests/baselines/reference/for-of9.js new file mode 100644 index 00000000000..f96d353bd7a --- /dev/null +++ b/tests/baselines/reference/for-of9.js @@ -0,0 +1,9 @@ +//// [for-of9.ts] +var v: string; +for (v of ["hello"]) { } +for (v of "hello") { } + +//// [for-of9.js] +var v; +for (v of ["hello"]) { } +for (v of "hello") { } diff --git a/tests/baselines/reference/for-of9.types b/tests/baselines/reference/for-of9.types new file mode 100644 index 00000000000..55c8167094f --- /dev/null +++ b/tests/baselines/reference/for-of9.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of9.ts === +var v: string; +>v : string + +for (v of ["hello"]) { } +>v : string +>["hello"] : string[] + +for (v of "hello") { } +>v : string + diff --git a/tests/baselines/reference/parserForOfStatement18.types b/tests/baselines/reference/parserForOfStatement18.types new file mode 100644 index 00000000000..8e3b52ac877 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement18.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement18.ts === +for (var of of of) { } +>of : any +>of : any + diff --git a/tests/baselines/reference/parserForOfStatement8.types b/tests/baselines/reference/parserForOfStatement8.types new file mode 100644 index 00000000000..a4168caf262 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement8.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts === +for (var v of X) { +>v : any +>X : unknown +} diff --git a/tests/baselines/reference/parserForOfStatement9.types b/tests/baselines/reference/parserForOfStatement9.types new file mode 100644 index 00000000000..0285a3e4b76 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement9.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts === +for (let v of X) { +>v : any +>X : unknown +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of10.ts b/tests/cases/conformance/es6/for-ofStatements/for-of10.ts new file mode 100644 index 00000000000..dec00541e93 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of10.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var v: string; +for (v of [0]) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of11.ts b/tests/cases/conformance/es6/for-ofStatements/for-of11.ts new file mode 100644 index 00000000000..e434758efa4 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of11.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var v: string; +for (v of [0, ""]) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of12.ts b/tests/cases/conformance/es6/for-ofStatements/for-of12.ts new file mode 100644 index 00000000000..78cfbaccecb --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of12.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var v: string; +for (v of [0, ""].values()) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of13.ts b/tests/cases/conformance/es6/for-ofStatements/for-of13.ts new file mode 100644 index 00000000000..2f2b922cb1d --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of13.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var v: string; +for (v of [""].values()) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of14.ts b/tests/cases/conformance/es6/for-ofStatements/for-of14.ts new file mode 100644 index 00000000000..8bb3e959501 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of14.ts @@ -0,0 +1,9 @@ +//@target: ES6 +var v: string; +for (v of new StringIterator) { } // Should fail because the iterator is not iterable + +class StringIterator implements Iterator { + next() { + return ""; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of15.ts b/tests/cases/conformance/es6/for-ofStatements/for-of15.ts new file mode 100644 index 00000000000..87ff3e9603d --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of15.ts @@ -0,0 +1,12 @@ +//@target: ES6 +var v: string; +for (v of new StringIterator) { } // Should succeed + +class StringIterator implements Iterator { + next() { + return ""; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of16.ts b/tests/cases/conformance/es6/for-ofStatements/for-of16.ts new file mode 100644 index 00000000000..92b3b4e6de5 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of16.ts @@ -0,0 +1,12 @@ +//@target: ES6 +var v: string; +for (v of (new StringIterator)[Symbol.iterator]()) { } // Should succeed + +class StringIterator implements Iterator { + next() { + return ""; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of17.ts b/tests/cases/conformance/es6/for-ofStatements/for-of17.ts new file mode 100644 index 00000000000..819e9218bd1 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of17.ts @@ -0,0 +1,12 @@ +//@target: ES6 +var v: number; +for (v of (new NumberIterator)[Symbol.iterator]().next()) { } // Should fail + +class NumberIterator { + next() { + return 0; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of18.ts b/tests/cases/conformance/es6/for-ofStatements/for-of18.ts new file mode 100644 index 00000000000..10e566cf64c --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of18.ts @@ -0,0 +1,15 @@ +//@target: ES6 +var v: string; +for (v of (new StringIterator)[Symbol.iterator]().next()) { } // Should succeed + +class StringIterator { + next() { + return { + value: "", + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of19.ts b/tests/cases/conformance/es6/for-ofStatements/for-of19.ts new file mode 100644 index 00000000000..1e45c32e8ad --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of19.ts @@ -0,0 +1,15 @@ +//@target: ES6 +var v: string; +for (v of (new StringIterator)[Symbol.iterator]().next()) { } // Should fail + +class StringIterator { + next() { + return { + value: 0, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of9.ts b/tests/cases/conformance/es6/for-ofStatements/for-of9.ts new file mode 100644 index 00000000000..45a3c7e1d94 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of9.ts @@ -0,0 +1,4 @@ +//@target: ES6 +var v: string; +for (v of ["hello"]) { } +for (v of "hello") { } \ No newline at end of file From a2c557320b5c8fe641e02f5fb1e59529bd38f7c4 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 23 Feb 2015 18:06:07 -0800 Subject: [PATCH 07/26] Get type of 'for...of' variables --- src/compiler/checker.ts | 57 ++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1357d659e82..5a9e9575bca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1862,6 +1862,9 @@ module ts { if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) { return anyType; } + if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { + return getTypeForVariableDeclarationInForOfStatement(declaration.parent.parent); + } if (isBindingPattern(declaration.parent)) { return getTypeForBindingElement(declaration); } @@ -8818,6 +8821,28 @@ module ts { } } + function getTypeForVariableDeclarationInForOfStatement(forOfStatement: ForOfStatement): Type { + // Temporarily return 'any' below ES6 + if (languageVersion < ScriptTarget.ES6) { + return anyType; + } + + var variable = forOfStatement.initializer; + var links = getNodeLinks(variable); + if (!links.resolvedType) { + links.resolvedType = resolvingType; + var type = getIteratedType(getTypeOfExpression(forOfStatement.expression)); + if (links.resolvedType === resolvingType) { + links.resolvedType = type; + } + } + else if (links.resolvedType === resolvingType) { + links.resolvedType = anyType; + } + + return links.resolvedType; + } + function getIteratedType(iterable: Type): Type { Debug.assert(languageVersion >= ScriptTarget.ES6); if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { @@ -11483,22 +11508,24 @@ module ts { } function checkGrammarVariableDeclaration(node: VariableDeclaration) { - if (isInAmbientContext(node)) { - if (isBindingPattern(node.name)) { - return grammarErrorOnNode(node, Diagnostics.Destructuring_declarations_are_not_allowed_in_ambient_contexts); - } - if (node.initializer) { - // Error on equals token which immediate precedes the initializer - return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - 1, 1, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); - } - } - else { - if (!node.initializer) { - if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { - return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer); + if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) { + if (isInAmbientContext(node)) { + if (isBindingPattern(node.name)) { + return grammarErrorOnNode(node, Diagnostics.Destructuring_declarations_are_not_allowed_in_ambient_contexts); } - if (isConst(node)) { - return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized); + if (node.initializer) { + // Error on equals token which immediate precedes the initializer + return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - 1, 1, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + } + } + else { + if (!node.initializer) { + if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { + return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer); + } + if (isConst(node)) { + return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized); + } } } } From 1043d8703faca8aa130700087439ced3767cbbd8 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 23 Feb 2015 18:06:38 -0800 Subject: [PATCH 08/26] Tests and baselines for 'for...of' variables --- .../reference/constDeclarations-errors.errors.txt | 5 +---- tests/baselines/reference/for-of4.types | 8 ++++++++ tests/baselines/reference/for-of5.types | 8 ++++++++ tests/baselines/reference/for-of8.types | 8 ++++++++ .../reference/parserForOfStatement1.d.errors.txt | 5 ++++- .../baselines/reference/parserForOfStatement10.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement11.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement12.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement13.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement14.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement15.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement16.errors.txt | 8 ++++++++ .../baselines/reference/parserForOfStatement3.errors.txt | 5 ++++- .../baselines/reference/parserForOfStatement4.errors.txt | 5 ++++- .../baselines/reference/parserForOfStatement5.errors.txt | 5 ++++- .../baselines/reference/parserForOfStatement6.errors.txt | 5 ++++- .../baselines/reference/parserForOfStatement7.errors.txt | 5 ++++- .../baselines/reference/parserForOfStatement8.errors.txt | 8 ++++++++ tests/baselines/reference/parserForOfStatement8.types | 5 ----- .../baselines/reference/parserForOfStatement9.errors.txt | 8 ++++++++ tests/baselines/reference/parserForOfStatement9.types | 5 ----- 21 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 tests/baselines/reference/for-of4.types create mode 100644 tests/baselines/reference/for-of5.types create mode 100644 tests/baselines/reference/for-of8.types create mode 100644 tests/baselines/reference/parserForOfStatement10.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement11.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement12.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement13.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement14.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement15.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement16.errors.txt create mode 100644 tests/baselines/reference/parserForOfStatement8.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement8.types create mode 100644 tests/baselines/reference/parserForOfStatement9.errors.txt delete mode 100644 tests/baselines/reference/parserForOfStatement9.types diff --git a/tests/baselines/reference/constDeclarations-errors.errors.txt b/tests/baselines/reference/constDeclarations-errors.errors.txt index c0ae6635c5e..c8d25b05e54 100644 --- a/tests/baselines/reference/constDeclarations-errors.errors.txt +++ b/tests/baselines/reference/constDeclarations-errors.errors.txt @@ -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; @@ -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++) { } diff --git a/tests/baselines/reference/for-of4.types b/tests/baselines/reference/for-of4.types new file mode 100644 index 00000000000..2076fae84fc --- /dev/null +++ b/tests/baselines/reference/for-of4.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of4.ts === +for (var v of [0]) { +>v : number +>[0] : number[] + + v; +>v : number +} diff --git a/tests/baselines/reference/for-of5.types b/tests/baselines/reference/for-of5.types new file mode 100644 index 00000000000..feac5ef9e52 --- /dev/null +++ b/tests/baselines/reference/for-of5.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of5.ts === +for (let v of [0]) { +>v : number +>[0] : number[] + + v; +>v : number +} diff --git a/tests/baselines/reference/for-of8.types b/tests/baselines/reference/for-of8.types new file mode 100644 index 00000000000..5f239d141fe --- /dev/null +++ b/tests/baselines/reference/for-of8.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of8.ts === +v; +>v : number + +for (var v of [0]) { } +>v : number +>[0] : number[] + diff --git a/tests/baselines/reference/parserForOfStatement1.d.errors.txt b/tests/baselines/reference/parserForOfStatement1.d.errors.txt index 3b1b2a65922..c492c7817e8 100644 --- a/tests/baselines/reference/parserForOfStatement1.d.errors.txt +++ b/tests/baselines/reference/parserForOfStatement1.d.errors.txt @@ -1,8 +1,11 @@ tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts(1,1): error TS1036: Statements are not allowed in ambient contexts. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts(1,15): error TS2304: Cannot find name 'e'. -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement1.d.ts (2 errors) ==== for (var i of e) { ~~~ !!! error TS1036: Statements are not allowed in ambient contexts. + ~ +!!! error TS2304: Cannot find name 'e'. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement10.errors.txt b/tests/baselines/reference/parserForOfStatement10.errors.txt new file mode 100644 index 00000000000..d2fc73e6b68 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement10.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement10.ts(1,17): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement10.ts (1 errors) ==== + for (const v of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement11.errors.txt b/tests/baselines/reference/parserForOfStatement11.errors.txt new file mode 100644 index 00000000000..2c5af586ae3 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement11.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement11.ts(1,22): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement11.ts (1 errors) ==== + for (const [a, b] of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement12.errors.txt b/tests/baselines/reference/parserForOfStatement12.errors.txt new file mode 100644 index 00000000000..951b70eac35 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement12.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement12.ts(1,22): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement12.ts (1 errors) ==== + for (const {a, b} of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement13.errors.txt b/tests/baselines/reference/parserForOfStatement13.errors.txt new file mode 100644 index 00000000000..c789ab89d9a --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement13.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement13.ts(1,20): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement13.ts (1 errors) ==== + for (let {a, b} of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement14.errors.txt b/tests/baselines/reference/parserForOfStatement14.errors.txt new file mode 100644 index 00000000000..46e71e5242f --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement14.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement14.ts(1,20): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement14.ts (1 errors) ==== + for (let [a, b] of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement15.errors.txt b/tests/baselines/reference/parserForOfStatement15.errors.txt new file mode 100644 index 00000000000..0f159c7a25a --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement15.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement15.ts(1,20): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement15.ts (1 errors) ==== + for (var [a, b] of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement16.errors.txt b/tests/baselines/reference/parserForOfStatement16.errors.txt new file mode 100644 index 00000000000..3d950fd145d --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement16.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement16.ts(1,20): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement16.ts (1 errors) ==== + for (var {a, b} of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement3.errors.txt b/tests/baselines/reference/parserForOfStatement3.errors.txt index 995ef4637c2..a565ae37d32 100644 --- a/tests/baselines/reference/parserForOfStatement3.errors.txt +++ b/tests/baselines/reference/parserForOfStatement3.errors.txt @@ -1,8 +1,11 @@ tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts(1,13): error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts(1,18): error TS2304: Cannot find name 'X'. -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement3.ts (2 errors) ==== for (var a, b of X) { ~ !!! error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. + ~ +!!! error TS2304: Cannot find name 'X'. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement4.errors.txt b/tests/baselines/reference/parserForOfStatement4.errors.txt index 65b4bf342f2..97873682082 100644 --- a/tests/baselines/reference/parserForOfStatement4.errors.txt +++ b/tests/baselines/reference/parserForOfStatement4.errors.txt @@ -1,8 +1,11 @@ tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts(1,10): error TS1190: The variable declaration of a 'for...of' statement cannot have an initializer. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts(1,19): error TS2304: Cannot find name 'X'. -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement4.ts (2 errors) ==== for (var a = 1 of X) { ~ !!! error TS1190: The variable declaration of a 'for...of' statement cannot have an initializer. + ~ +!!! error TS2304: Cannot find name 'X'. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement5.errors.txt b/tests/baselines/reference/parserForOfStatement5.errors.txt index 13fd8739866..e3ed3235910 100644 --- a/tests/baselines/reference/parserForOfStatement5.errors.txt +++ b/tests/baselines/reference/parserForOfStatement5.errors.txt @@ -1,8 +1,11 @@ tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts(1,10): error TS2483: The left-hand side of a 'for...of' statement cannot use a type annotation. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts(1,23): error TS2304: Cannot find name 'X'. -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement5.ts (2 errors) ==== for (var a: number of X) { ~ !!! error TS2483: The left-hand side of a 'for...of' statement cannot use a type annotation. + ~ +!!! error TS2304: Cannot find name 'X'. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement6.errors.txt b/tests/baselines/reference/parserForOfStatement6.errors.txt index 57d95361b65..59a18f03bcd 100644 --- a/tests/baselines/reference/parserForOfStatement6.errors.txt +++ b/tests/baselines/reference/parserForOfStatement6.errors.txt @@ -1,8 +1,11 @@ tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts(1,17): error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts(1,26): error TS2304: Cannot find name 'X'. -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement6.ts (2 errors) ==== for (var a = 1, b = 2 of X) { ~ !!! error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. + ~ +!!! error TS2304: Cannot find name 'X'. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement7.errors.txt b/tests/baselines/reference/parserForOfStatement7.errors.txt index 07f93c263ec..f5ab97b4413 100644 --- a/tests/baselines/reference/parserForOfStatement7.errors.txt +++ b/tests/baselines/reference/parserForOfStatement7.errors.txt @@ -1,8 +1,11 @@ tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts(1,25): error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts(1,43): error TS2304: Cannot find name 'X'. -==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement7.ts (2 errors) ==== for (var a: number = 1, b: string = "" of X) { ~ !!! error TS1188: Only a single variable declaration is allowed in a 'for...of' statement. + ~ +!!! error TS2304: Cannot find name 'X'. } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement8.errors.txt b/tests/baselines/reference/parserForOfStatement8.errors.txt new file mode 100644 index 00000000000..5fe9bb43415 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement8.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts(1,15): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts (1 errors) ==== + for (var v of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement8.types b/tests/baselines/reference/parserForOfStatement8.types deleted file mode 100644 index a4168caf262..00000000000 --- a/tests/baselines/reference/parserForOfStatement8.types +++ /dev/null @@ -1,5 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement8.ts === -for (var v of X) { ->v : any ->X : unknown -} diff --git a/tests/baselines/reference/parserForOfStatement9.errors.txt b/tests/baselines/reference/parserForOfStatement9.errors.txt new file mode 100644 index 00000000000..fae9beec253 --- /dev/null +++ b/tests/baselines/reference/parserForOfStatement9.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts(1,15): error TS2304: Cannot find name 'X'. + + +==== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts (1 errors) ==== + for (let v of X) { + ~ +!!! error TS2304: Cannot find name 'X'. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserForOfStatement9.types b/tests/baselines/reference/parserForOfStatement9.types deleted file mode 100644 index 0285a3e4b76..00000000000 --- a/tests/baselines/reference/parserForOfStatement9.types +++ /dev/null @@ -1,5 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/Iterators/parserForOfStatement9.ts === -for (let v of X) { ->v : any ->X : unknown -} From 2858771a54b7c426b5131fd3e47bdf93f2a3a6f2 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 23 Feb 2015 19:07:29 -0800 Subject: [PATCH 09/26] Check iterable structure of the right hand side of 'for...of' statement --- src/compiler/checker.ts | 24 +++++++++++++++---- .../diagnosticInformationMap.generated.ts | 3 +++ src/compiler/diagnosticMessages.json | 12 ++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5a9e9575bca..efd101d8c06 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8768,7 +8768,7 @@ module ts { var leftType = checkExpression(varExpr); checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); var rightType = checkExpression(node.expression); - var iteratedType = getIteratedType(rightType); + var iteratedType = getIteratedType(rightType, node.expression); checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); } @@ -8831,7 +8831,7 @@ module ts { var links = getNodeLinks(variable); if (!links.resolvedType) { links.resolvedType = resolvingType; - var type = getIteratedType(getTypeOfExpression(forOfStatement.expression)); + var type = getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression); if (links.resolvedType === resolvingType) { links.resolvedType = type; } @@ -8843,7 +8843,7 @@ module ts { return links.resolvedType; } - function getIteratedType(iterable: Type): Type { + function getIteratedType(iterable: Type, expressionForError: Expression): Type { Debug.assert(languageVersion >= ScriptTarget.ES6); if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { return anyType; @@ -8867,14 +8867,28 @@ module ts { // T is the type we are after. At every level that involves analyzing return types // of signatures, we union the return types of all the signatures. var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); - var iteratorFunctionSignatures = getSignaturesOfType(iteratorFunction, SignatureKind.Call); + var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray; + if (iteratorFunctionSignatures.length === 0) { + error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator); + return unknownType; + } + var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature)); var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next"); - var iteratorNextFunctionSignatures = getSignaturesOfType(iteratorNextFunction, SignatureKind.Call); + var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray; + if (iteratorNextFunctionSignatures.length === 0) { + error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method); + return unknownType; + } + var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature)); var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); + if (!iteratorNextValue) { + error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property); + return unknownType; + } return iteratorNextValue; // TODO diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 35b5ca5cdc3..08de6681226 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -329,6 +329,9 @@ module ts { 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." }, 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 8b57778a696..45661c570c2 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1308,6 +1308,18 @@ "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.": { + "category": "Error", + "code": 2490 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", From 3d5c113bee2d75cc0aa754b6c43cf3773b116310 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 23 Feb 2015 19:07:45 -0800 Subject: [PATCH 10/26] Iterator tests --- tests/baselines/reference/for-of14.errors.txt | 14 ++++++++ tests/baselines/reference/for-of14.js | 21 +++++++++++ tests/baselines/reference/for-of15.errors.txt | 17 +++++++++ tests/baselines/reference/for-of15.js | 27 ++++++++++++++ tests/baselines/reference/for-of16.errors.txt | 14 ++++++++ tests/baselines/reference/for-of16.js | 21 +++++++++++ tests/baselines/reference/for-of17.errors.txt | 20 +++++++++++ tests/baselines/reference/for-of17.js | 33 +++++++++++++++++ tests/baselines/reference/for-of18.js | 33 +++++++++++++++++ tests/baselines/reference/for-of18.types | 35 +++++++++++++++++++ .../es6/for-ofStatements/for-of14.ts | 2 +- .../es6/for-ofStatements/for-of15.ts | 4 +-- .../es6/for-ofStatements/for-of16.ts | 7 ++-- .../es6/for-ofStatements/for-of17.ts | 9 +++-- .../es6/for-ofStatements/for-of18.ts | 2 +- .../es6/for-ofStatements/for-of19.ts | 15 -------- 16 files changed, 247 insertions(+), 27 deletions(-) create mode 100644 tests/baselines/reference/for-of14.errors.txt create mode 100644 tests/baselines/reference/for-of14.js create mode 100644 tests/baselines/reference/for-of15.errors.txt create mode 100644 tests/baselines/reference/for-of15.js create mode 100644 tests/baselines/reference/for-of16.errors.txt create mode 100644 tests/baselines/reference/for-of16.js create mode 100644 tests/baselines/reference/for-of17.errors.txt create mode 100644 tests/baselines/reference/for-of17.js create mode 100644 tests/baselines/reference/for-of18.js create mode 100644 tests/baselines/reference/for-of18.types delete mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of19.ts diff --git a/tests/baselines/reference/for-of14.errors.txt b/tests/baselines/reference/for-of14.errors.txt new file mode 100644 index 00000000000..5e8223381c7 --- /dev/null +++ b/tests/baselines/reference/for-of14.errors.txt @@ -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 ""; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of14.js b/tests/baselines/reference/for-of14.js new file mode 100644 index 00000000000..d5f9e29b766 --- /dev/null +++ b/tests/baselines/reference/for-of14.js @@ -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; +})(); diff --git a/tests/baselines/reference/for-of15.errors.txt b/tests/baselines/reference/for-of15.errors.txt new file mode 100644 index 00000000000..ab6b6c03ea7 --- /dev/null +++ b/tests/baselines/reference/for-of15.errors.txt @@ -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; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of15.js b/tests/baselines/reference/for-of15.js new file mode 100644 index 00000000000..36955389756 --- /dev/null +++ b/tests/baselines/reference/for-of15.js @@ -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; +})(); diff --git a/tests/baselines/reference/for-of16.errors.txt b/tests/baselines/reference/for-of16.errors.txt new file mode 100644 index 00000000000..e3ecca1a256 --- /dev/null +++ b/tests/baselines/reference/for-of16.errors.txt @@ -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; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of16.js b/tests/baselines/reference/for-of16.js new file mode 100644 index 00000000000..21ba2adb75c --- /dev/null +++ b/tests/baselines/reference/for-of16.js @@ -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; +})(); diff --git a/tests/baselines/reference/for-of17.errors.txt b/tests/baselines/reference/for-of17.errors.txt new file mode 100644 index 00000000000..dfdeb8db007 --- /dev/null +++ b/tests/baselines/reference/for-of17.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/es6/for-ofStatements/for-of17.ts(2,6): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of17.ts (1 errors) ==== + var v: string; + for (v of new NumberIterator) { } // Should succeed + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + + class NumberIterator { + next() { + return { + value: 0, + done: false + }; + } + [Symbol.iterator]() { + return this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of17.js b/tests/baselines/reference/for-of17.js new file mode 100644 index 00000000000..5c56cdab445 --- /dev/null +++ b/tests/baselines/reference/for-of17.js @@ -0,0 +1,33 @@ +//// [for-of17.ts] +var v: string; +for (v of new NumberIterator) { } // Should succeed + +class NumberIterator { + next() { + return { + value: 0, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of17.js] +var v; +for (v of new NumberIterator) { } // Should succeed +var NumberIterator = (function () { + function NumberIterator() { + } + NumberIterator.prototype.next = function () { + return { + value: 0, + done: false + }; + }; + NumberIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return NumberIterator; +})(); diff --git a/tests/baselines/reference/for-of18.js b/tests/baselines/reference/for-of18.js new file mode 100644 index 00000000000..57168d9bf07 --- /dev/null +++ b/tests/baselines/reference/for-of18.js @@ -0,0 +1,33 @@ +//// [for-of18.ts] +var v: string; +for (v of new StringIterator) { } // Should succeed + +class StringIterator { + next() { + return { + value: "", + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of18.js] +var v; +for (v of new StringIterator) { } // Should succeed +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype.next = function () { + return { + value: "", + done: false + }; + }; + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of18.types b/tests/baselines/reference/for-of18.types new file mode 100644 index 00000000000..9ade9359475 --- /dev/null +++ b/tests/baselines/reference/for-of18.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of18.ts === +var v: string; +>v : string + +for (v of new StringIterator) { } // Should succeed +>v : string +>new StringIterator : StringIterator +>StringIterator : typeof StringIterator + +class StringIterator { +>StringIterator : StringIterator + + next() { +>next : () => { value: string; done: boolean; } + + return { +>{ value: "", done: false } : { value: string; done: boolean; } + + value: "", +>value : string + + done: false +>done : boolean + + }; + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : StringIterator + } +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of14.ts b/tests/cases/conformance/es6/for-ofStatements/for-of14.ts index 8bb3e959501..84fbda4825c 100644 --- a/tests/cases/conformance/es6/for-ofStatements/for-of14.ts +++ b/tests/cases/conformance/es6/for-ofStatements/for-of14.ts @@ -2,7 +2,7 @@ var v: string; for (v of new StringIterator) { } // Should fail because the iterator is not iterable -class StringIterator implements Iterator { +class StringIterator { next() { return ""; } diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of15.ts b/tests/cases/conformance/es6/for-ofStatements/for-of15.ts index 87ff3e9603d..1973e7ff95e 100644 --- a/tests/cases/conformance/es6/for-ofStatements/for-of15.ts +++ b/tests/cases/conformance/es6/for-ofStatements/for-of15.ts @@ -1,8 +1,8 @@ //@target: ES6 var v: string; -for (v of new StringIterator) { } // Should succeed +for (v of new StringIterator) { } // Should fail -class StringIterator implements Iterator { +class StringIterator { next() { return ""; } diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of16.ts b/tests/cases/conformance/es6/for-ofStatements/for-of16.ts index 92b3b4e6de5..8f7bd6d8486 100644 --- a/tests/cases/conformance/es6/for-ofStatements/for-of16.ts +++ b/tests/cases/conformance/es6/for-ofStatements/for-of16.ts @@ -1,11 +1,8 @@ //@target: ES6 var v: string; -for (v of (new StringIterator)[Symbol.iterator]()) { } // Should succeed +for (v of new StringIterator) { } // Should fail -class StringIterator implements Iterator { - next() { - return ""; - } +class StringIterator { [Symbol.iterator]() { return this; } diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of17.ts b/tests/cases/conformance/es6/for-ofStatements/for-of17.ts index 819e9218bd1..431f066d477 100644 --- a/tests/cases/conformance/es6/for-ofStatements/for-of17.ts +++ b/tests/cases/conformance/es6/for-ofStatements/for-of17.ts @@ -1,10 +1,13 @@ //@target: ES6 -var v: number; -for (v of (new NumberIterator)[Symbol.iterator]().next()) { } // Should fail +var v: string; +for (v of new NumberIterator) { } // Should succeed class NumberIterator { next() { - return 0; + return { + value: 0, + done: false + }; } [Symbol.iterator]() { return this; diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of18.ts b/tests/cases/conformance/es6/for-ofStatements/for-of18.ts index 10e566cf64c..407ad7f0ed8 100644 --- a/tests/cases/conformance/es6/for-ofStatements/for-of18.ts +++ b/tests/cases/conformance/es6/for-ofStatements/for-of18.ts @@ -1,6 +1,6 @@ //@target: ES6 var v: string; -for (v of (new StringIterator)[Symbol.iterator]().next()) { } // Should succeed +for (v of new StringIterator) { } // Should succeed class StringIterator { next() { diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of19.ts b/tests/cases/conformance/es6/for-ofStatements/for-of19.ts deleted file mode 100644 index 1e45c32e8ad..00000000000 --- a/tests/cases/conformance/es6/for-ofStatements/for-of19.ts +++ /dev/null @@ -1,15 +0,0 @@ -//@target: ES6 -var v: string; -for (v of (new StringIterator)[Symbol.iterator]().next()) { } // Should fail - -class StringIterator { - next() { - return { - value: 0, - done: false - }; - } - [Symbol.iterator]() { - return this; - } -} \ No newline at end of file From 057108646d67e75fbbfdd9d2f9651b96a2b896ee Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Tue, 24 Feb 2015 11:31:42 -0800 Subject: [PATCH 11/26] More tests --- tests/baselines/reference/for-of19.js | 41 ++++++++++++++++++ tests/baselines/reference/for-of19.types | 41 ++++++++++++++++++ tests/baselines/reference/for-of20.js | 41 ++++++++++++++++++ tests/baselines/reference/for-of20.types | 41 ++++++++++++++++++ tests/baselines/reference/for-of21.js | 41 ++++++++++++++++++ tests/baselines/reference/for-of21.types | 41 ++++++++++++++++++ tests/baselines/reference/for-of22.js | 42 +++++++++++++++++++ tests/baselines/reference/for-of22.types | 42 +++++++++++++++++++ tests/baselines/reference/for-of23.js | 41 ++++++++++++++++++ tests/baselines/reference/for-of23.types | 41 ++++++++++++++++++ .../es6/for-ofStatements/for-of19.ts | 17 ++++++++ .../es6/for-ofStatements/for-of20.ts | 17 ++++++++ .../es6/for-ofStatements/for-of21.ts | 17 ++++++++ .../es6/for-ofStatements/for-of22.ts | 18 ++++++++ .../es6/for-ofStatements/for-of23.ts | 17 ++++++++ 15 files changed, 498 insertions(+) create mode 100644 tests/baselines/reference/for-of19.js create mode 100644 tests/baselines/reference/for-of19.types create mode 100644 tests/baselines/reference/for-of20.js create mode 100644 tests/baselines/reference/for-of20.types create mode 100644 tests/baselines/reference/for-of21.js create mode 100644 tests/baselines/reference/for-of21.types create mode 100644 tests/baselines/reference/for-of22.js create mode 100644 tests/baselines/reference/for-of22.types create mode 100644 tests/baselines/reference/for-of23.js create mode 100644 tests/baselines/reference/for-of23.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of19.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of20.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of21.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of22.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of23.ts diff --git a/tests/baselines/reference/for-of19.js b/tests/baselines/reference/for-of19.js new file mode 100644 index 00000000000..eefb9339f18 --- /dev/null +++ b/tests/baselines/reference/for-of19.js @@ -0,0 +1,41 @@ +//// [for-of19.ts] +for (var v of new FooIterator) { + v; +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of19.js] +for (var v of new FooIterator) { + v; +} +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +var FooIterator = (function () { + function FooIterator() { + } + FooIterator.prototype.next = function () { + return { + value: new Foo, + done: false + }; + }; + FooIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return FooIterator; +})(); diff --git a/tests/baselines/reference/for-of19.types b/tests/baselines/reference/for-of19.types new file mode 100644 index 00000000000..49172b09d83 --- /dev/null +++ b/tests/baselines/reference/for-of19.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of19.ts === +for (var v of new FooIterator) { +>v : Foo +>new FooIterator : FooIterator +>FooIterator : typeof FooIterator + + v; +>v : Foo +} + +class Foo { } +>Foo : Foo + +class FooIterator { +>FooIterator : FooIterator + + next() { +>next : () => { value: Foo; done: boolean; } + + return { +>{ value: new Foo, done: false } : { value: Foo; done: boolean; } + + value: new Foo, +>value : Foo +>new Foo : Foo +>Foo : typeof Foo + + done: false +>done : boolean + + }; + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : FooIterator + } +} diff --git a/tests/baselines/reference/for-of20.js b/tests/baselines/reference/for-of20.js new file mode 100644 index 00000000000..39b1081954b --- /dev/null +++ b/tests/baselines/reference/for-of20.js @@ -0,0 +1,41 @@ +//// [for-of20.ts] +for (let v of new FooIterator) { + v; +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of20.js] +for (let v of new FooIterator) { + v; +} +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +var FooIterator = (function () { + function FooIterator() { + } + FooIterator.prototype.next = function () { + return { + value: new Foo, + done: false + }; + }; + FooIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return FooIterator; +})(); diff --git a/tests/baselines/reference/for-of20.types b/tests/baselines/reference/for-of20.types new file mode 100644 index 00000000000..e967869fbd0 --- /dev/null +++ b/tests/baselines/reference/for-of20.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of20.ts === +for (let v of new FooIterator) { +>v : Foo +>new FooIterator : FooIterator +>FooIterator : typeof FooIterator + + v; +>v : Foo +} + +class Foo { } +>Foo : Foo + +class FooIterator { +>FooIterator : FooIterator + + next() { +>next : () => { value: Foo; done: boolean; } + + return { +>{ value: new Foo, done: false } : { value: Foo; done: boolean; } + + value: new Foo, +>value : Foo +>new Foo : Foo +>Foo : typeof Foo + + done: false +>done : boolean + + }; + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : FooIterator + } +} diff --git a/tests/baselines/reference/for-of21.js b/tests/baselines/reference/for-of21.js new file mode 100644 index 00000000000..c11514b192c --- /dev/null +++ b/tests/baselines/reference/for-of21.js @@ -0,0 +1,41 @@ +//// [for-of21.ts] +for (const v of new FooIterator) { + v; +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of21.js] +for (var v of new FooIterator) { + v; +} +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +var FooIterator = (function () { + function FooIterator() { + } + FooIterator.prototype.next = function () { + return { + value: new Foo, + done: false + }; + }; + FooIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return FooIterator; +})(); diff --git a/tests/baselines/reference/for-of21.types b/tests/baselines/reference/for-of21.types new file mode 100644 index 00000000000..362f92577e2 --- /dev/null +++ b/tests/baselines/reference/for-of21.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of21.ts === +for (const v of new FooIterator) { +>v : Foo +>new FooIterator : FooIterator +>FooIterator : typeof FooIterator + + v; +>v : Foo +} + +class Foo { } +>Foo : Foo + +class FooIterator { +>FooIterator : FooIterator + + next() { +>next : () => { value: Foo; done: boolean; } + + return { +>{ value: new Foo, done: false } : { value: Foo; done: boolean; } + + value: new Foo, +>value : Foo +>new Foo : Foo +>Foo : typeof Foo + + done: false +>done : boolean + + }; + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : FooIterator + } +} diff --git a/tests/baselines/reference/for-of22.js b/tests/baselines/reference/for-of22.js new file mode 100644 index 00000000000..d38accb6cd8 --- /dev/null +++ b/tests/baselines/reference/for-of22.js @@ -0,0 +1,42 @@ +//// [for-of22.ts] +v; +for (var v of new FooIterator) { + +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of22.js] +v; +for (var v of new FooIterator) { +} +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +var FooIterator = (function () { + function FooIterator() { + } + FooIterator.prototype.next = function () { + return { + value: new Foo, + done: false + }; + }; + FooIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return FooIterator; +})(); diff --git a/tests/baselines/reference/for-of22.types b/tests/baselines/reference/for-of22.types new file mode 100644 index 00000000000..bb2d5569bfc --- /dev/null +++ b/tests/baselines/reference/for-of22.types @@ -0,0 +1,42 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of22.ts === +v; +>v : Foo + +for (var v of new FooIterator) { +>v : Foo +>new FooIterator : FooIterator +>FooIterator : typeof FooIterator + +} + +class Foo { } +>Foo : Foo + +class FooIterator { +>FooIterator : FooIterator + + next() { +>next : () => { value: Foo; done: boolean; } + + return { +>{ value: new Foo, done: false } : { value: Foo; done: boolean; } + + value: new Foo, +>value : Foo +>new Foo : Foo +>Foo : typeof Foo + + done: false +>done : boolean + + }; + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : FooIterator + } +} diff --git a/tests/baselines/reference/for-of23.js b/tests/baselines/reference/for-of23.js new file mode 100644 index 00000000000..943c5b6cecb --- /dev/null +++ b/tests/baselines/reference/for-of23.js @@ -0,0 +1,41 @@ +//// [for-of23.ts] +for (const v of new FooIterator) { + const v = 0; // new scope +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of23.js] +for (var v of new FooIterator) { + const v = 0; // new scope +} +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +var FooIterator = (function () { + function FooIterator() { + } + FooIterator.prototype.next = function () { + return { + value: new Foo, + done: false + }; + }; + FooIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return FooIterator; +})(); diff --git a/tests/baselines/reference/for-of23.types b/tests/baselines/reference/for-of23.types new file mode 100644 index 00000000000..b490616edc8 --- /dev/null +++ b/tests/baselines/reference/for-of23.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of23.ts === +for (const v of new FooIterator) { +>v : Foo +>new FooIterator : FooIterator +>FooIterator : typeof FooIterator + + const v = 0; // new scope +>v : number +} + +class Foo { } +>Foo : Foo + +class FooIterator { +>FooIterator : FooIterator + + next() { +>next : () => { value: Foo; done: boolean; } + + return { +>{ value: new Foo, done: false } : { value: Foo; done: boolean; } + + value: new Foo, +>value : Foo +>new Foo : Foo +>Foo : typeof Foo + + done: false +>done : boolean + + }; + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : FooIterator + } +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of19.ts b/tests/cases/conformance/es6/for-ofStatements/for-of19.ts new file mode 100644 index 00000000000..ff80b2690ef --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of19.ts @@ -0,0 +1,17 @@ +//@target: ES6 +for (var v of new FooIterator) { + v; +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of20.ts b/tests/cases/conformance/es6/for-ofStatements/for-of20.ts new file mode 100644 index 00000000000..615f5149375 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of20.ts @@ -0,0 +1,17 @@ +//@target: ES6 +for (let v of new FooIterator) { + v; +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of21.ts b/tests/cases/conformance/es6/for-ofStatements/for-of21.ts new file mode 100644 index 00000000000..4e4621034e1 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of21.ts @@ -0,0 +1,17 @@ +//@target: ES6 +for (const v of new FooIterator) { + v; +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of22.ts b/tests/cases/conformance/es6/for-ofStatements/for-of22.ts new file mode 100644 index 00000000000..10a96502cdd --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of22.ts @@ -0,0 +1,18 @@ +//@target: ES6 +v; +for (var v of new FooIterator) { + +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of23.ts b/tests/cases/conformance/es6/for-ofStatements/for-of23.ts new file mode 100644 index 00000000000..81227cd0665 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of23.ts @@ -0,0 +1,17 @@ +//@target: ES6 +for (const v of new FooIterator) { + const v = 0; // new scope +} + +class Foo { } +class FooIterator { + next() { + return { + value: new Foo, + done: false + }; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file From 732637dd5427944793e23893663862ce92844563 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Tue, 24 Feb 2015 13:35:42 -0800 Subject: [PATCH 12/26] Fix getIteratedType to work with 'any' at all levels --- src/compiler/checker.ts | 16 ++++++++++- tests/baselines/reference/for-of24.js | 8 ++++++ tests/baselines/reference/for-of24.types | 8 ++++++ tests/baselines/reference/for-of25.js | 21 +++++++++++++++ tests/baselines/reference/for-of25.types | 21 +++++++++++++++ tests/baselines/reference/for-of26.js | 27 +++++++++++++++++++ tests/baselines/reference/for-of26.types | 27 +++++++++++++++++++ tests/baselines/reference/for-of27.js | 14 ++++++++++ tests/baselines/reference/for-of27.types | 14 ++++++++++ tests/baselines/reference/for-of28.js | 20 ++++++++++++++ tests/baselines/reference/for-of28.types | 21 +++++++++++++++ .../es6/for-ofStatements/for-of24.ts | 3 +++ .../es6/for-ofStatements/for-of25.ts | 9 +++++++ .../es6/for-ofStatements/for-of26.ts | 12 +++++++++ .../es6/for-ofStatements/for-of27.ts | 6 +++++ .../es6/for-ofStatements/for-of28.ts | 9 +++++++ 16 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/for-of24.js create mode 100644 tests/baselines/reference/for-of24.types create mode 100644 tests/baselines/reference/for-of25.js create mode 100644 tests/baselines/reference/for-of25.types create mode 100644 tests/baselines/reference/for-of26.js create mode 100644 tests/baselines/reference/for-of26.types create mode 100644 tests/baselines/reference/for-of27.js create mode 100644 tests/baselines/reference/for-of27.types create mode 100644 tests/baselines/reference/for-of28.js create mode 100644 tests/baselines/reference/for-of28.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of24.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of25.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of26.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of27.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of28.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index efd101d8c06..fd0724f3335 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8846,7 +8846,7 @@ module ts { function getIteratedType(iterable: Type, expressionForError: Expression): Type { Debug.assert(languageVersion >= ScriptTarget.ES6); if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { - return anyType; + return iterable; // any or unknown } // We want to treat type as an iterable, and get the type it is an iterable of. The iterable @@ -8867,6 +8867,10 @@ module ts { // T is the type we are after. At every level that involves analyzing return types // of signatures, we union the return types of all the signatures. var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); + if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) { + return iteratorFunction; // any or unknown + } + var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray; if (iteratorFunctionSignatures.length === 0) { error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator); @@ -8874,8 +8878,15 @@ module ts { } var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature)); + if (allConstituentTypesHaveKind(iterator, TypeFlags.Any)) { + return iterator; // any or unknown + } var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next"); + if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, TypeFlags.Any)) { + return iteratorNextFunction; // any or unknown + } + var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray; if (iteratorNextFunctionSignatures.length === 0) { error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method); @@ -8883,6 +8894,9 @@ module ts { } var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature)); + if (allConstituentTypesHaveKind(iteratorNextResult, TypeFlags.Any)) { + return iteratorNextResult; // any or unknown + } var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); if (!iteratorNextValue) { diff --git a/tests/baselines/reference/for-of24.js b/tests/baselines/reference/for-of24.js new file mode 100644 index 00000000000..b4918519603 --- /dev/null +++ b/tests/baselines/reference/for-of24.js @@ -0,0 +1,8 @@ +//// [for-of24.ts] +var x: any; +for (var v of x) { } + + +//// [for-of24.js] +var x; +for (var v of x) { } diff --git a/tests/baselines/reference/for-of24.types b/tests/baselines/reference/for-of24.types new file mode 100644 index 00000000000..dc27cc32e21 --- /dev/null +++ b/tests/baselines/reference/for-of24.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of24.ts === +var x: any; +>x : any + +for (var v of x) { } +>v : any +>x : any + diff --git a/tests/baselines/reference/for-of25.js b/tests/baselines/reference/for-of25.js new file mode 100644 index 00000000000..21b5ce1408b --- /dev/null +++ b/tests/baselines/reference/for-of25.js @@ -0,0 +1,21 @@ +//// [for-of25.ts] +var x: any; +for (var v of new StringIterator) { } + +class StringIterator { + [Symbol.iterator]() { + return x; + } +} + +//// [for-of25.js] +var x; +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype[Symbol.iterator] = function () { + return x; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of25.types b/tests/baselines/reference/for-of25.types new file mode 100644 index 00000000000..c4d6b32aebc --- /dev/null +++ b/tests/baselines/reference/for-of25.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of25.ts === +var x: any; +>x : any + +for (var v of new StringIterator) { } +>v : any +>new StringIterator : StringIterator +>StringIterator : typeof StringIterator + +class StringIterator { +>StringIterator : StringIterator + + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return x; +>x : any + } +} diff --git a/tests/baselines/reference/for-of26.js b/tests/baselines/reference/for-of26.js new file mode 100644 index 00000000000..a45492a81c0 --- /dev/null +++ b/tests/baselines/reference/for-of26.js @@ -0,0 +1,27 @@ +//// [for-of26.ts] +var x: any; +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return x; + } + [Symbol.iterator]() { + return this; + } +} + +//// [for-of26.js] +var x; +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype.next = function () { + return x; + }; + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of26.types b/tests/baselines/reference/for-of26.types new file mode 100644 index 00000000000..d2608fbf154 --- /dev/null +++ b/tests/baselines/reference/for-of26.types @@ -0,0 +1,27 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of26.ts === +var x: any; +>x : any + +for (var v of new StringIterator) { } +>v : any +>new StringIterator : StringIterator +>StringIterator : typeof StringIterator + +class StringIterator { +>StringIterator : StringIterator + + next() { +>next : () => any + + return x; +>x : any + } + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : StringIterator + } +} diff --git a/tests/baselines/reference/for-of27.js b/tests/baselines/reference/for-of27.js new file mode 100644 index 00000000000..91e1e7194c1 --- /dev/null +++ b/tests/baselines/reference/for-of27.js @@ -0,0 +1,14 @@ +//// [for-of27.ts] +for (var v of new StringIterator) { } + +class StringIterator { + [Symbol.iterator]: any; +} + +//// [for-of27.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of27.types b/tests/baselines/reference/for-of27.types new file mode 100644 index 00000000000..8e9130ce272 --- /dev/null +++ b/tests/baselines/reference/for-of27.types @@ -0,0 +1,14 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of27.ts === +for (var v of new StringIterator) { } +>v : any +>new StringIterator : StringIterator +>StringIterator : typeof StringIterator + +class StringIterator { +>StringIterator : StringIterator + + [Symbol.iterator]: any; +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +} diff --git a/tests/baselines/reference/for-of28.js b/tests/baselines/reference/for-of28.js new file mode 100644 index 00000000000..06029e6bb08 --- /dev/null +++ b/tests/baselines/reference/for-of28.js @@ -0,0 +1,20 @@ +//// [for-of28.ts] +for (var v of new StringIterator) { } + +class StringIterator { + next: any; + [Symbol.iterator]() { + return this; + } +} + +//// [for-of28.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of28.types b/tests/baselines/reference/for-of28.types new file mode 100644 index 00000000000..91b77a55a4d --- /dev/null +++ b/tests/baselines/reference/for-of28.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of28.ts === +for (var v of new StringIterator) { } +>v : any +>new StringIterator : StringIterator +>StringIterator : typeof StringIterator + +class StringIterator { +>StringIterator : StringIterator + + next: any; +>next : any + + [Symbol.iterator]() { +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol + + return this; +>this : StringIterator + } +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of24.ts b/tests/cases/conformance/es6/for-ofStatements/for-of24.ts new file mode 100644 index 00000000000..6f68821a0b5 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of24.ts @@ -0,0 +1,3 @@ +//@target: ES6 +var x: any; +for (var v of x) { } diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of25.ts b/tests/cases/conformance/es6/for-ofStatements/for-of25.ts new file mode 100644 index 00000000000..a1698bd2824 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of25.ts @@ -0,0 +1,9 @@ +//@target: ES6 +var x: any; +for (var v of new StringIterator) { } + +class StringIterator { + [Symbol.iterator]() { + return x; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of26.ts b/tests/cases/conformance/es6/for-ofStatements/for-of26.ts new file mode 100644 index 00000000000..0ab564a4f52 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of26.ts @@ -0,0 +1,12 @@ +//@target: ES6 +var x: any; +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return x; + } + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of27.ts b/tests/cases/conformance/es6/for-ofStatements/for-of27.ts new file mode 100644 index 00000000000..8f2b84cbe1d --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of27.ts @@ -0,0 +1,6 @@ +//@target: ES6 +for (var v of new StringIterator) { } + +class StringIterator { + [Symbol.iterator]: any; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of28.ts b/tests/cases/conformance/es6/for-ofStatements/for-of28.ts new file mode 100644 index 00000000000..8c693193b08 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of28.ts @@ -0,0 +1,9 @@ +//@target: ES6 +for (var v of new StringIterator) { } + +class StringIterator { + next: any; + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file From 0049b21d6cc5a6b911c224738ceb2316990526b7 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Tue, 24 Feb 2015 16:09:58 -0800 Subject: [PATCH 13/26] Check for assignability to the relevant iteratable type --- src/compiler/checker.ts | 141 ++++++++++-------- tests/baselines/reference/for-of29.errors.txt | 14 ++ tests/baselines/reference/for-of29.js | 11 ++ tests/baselines/reference/for-of30.errors.txt | 32 ++++ tests/baselines/reference/for-of30.js | 35 +++++ tests/baselines/reference/for-of31.errors.txt | 34 +++++ tests/baselines/reference/for-of31.js | 32 ++++ .../es6/for-ofStatements/for-of29.ts | 6 + .../es6/for-ofStatements/for-of30.ts | 17 +++ .../es6/for-ofStatements/for-of31.ts | 15 ++ 10 files changed, 272 insertions(+), 65 deletions(-) create mode 100644 tests/baselines/reference/for-of29.errors.txt create mode 100644 tests/baselines/reference/for-of29.js create mode 100644 tests/baselines/reference/for-of30.errors.txt create mode 100644 tests/baselines/reference/for-of30.js create mode 100644 tests/baselines/reference/for-of31.errors.txt create mode 100644 tests/baselines/reference/for-of31.js create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of29.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of30.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of31.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fd0724f3335..ae20772a209 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -97,6 +97,7 @@ module ts { var globalRegExpType: ObjectType; var globalTemplateStringsArrayType: ObjectType; var globalESSymbolType: ObjectType; + var globalIterableType: ObjectType; var anyArrayType: Type; @@ -3156,8 +3157,8 @@ module ts { return resolveName(undefined, name, meaning, diagnostic, name); } - function getGlobalType(name: string): ObjectType { - return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), 0); + function getGlobalType(name: string, arity = 0): ObjectType { + return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity); } function getGlobalESSymbolConstructorSymbol() { @@ -8844,70 +8845,79 @@ module ts { } function getIteratedType(iterable: Type, expressionForError: Expression): Type { - Debug.assert(languageVersion >= ScriptTarget.ES6); - if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { - return iterable; // any or unknown - } - - // We want to treat type as an iterable, and get the type it is an iterable of. The iterable - // must have the following structure (annotated with the names of the variables below): - // - // { // iterable - // [Symbol.iterator]: { // iteratorFunction - // (): { // iterator - // next: { // iteratorNextFunction - // (): { // iteratorNextResult - // value: T // iteratorNextValue - // } - // } - // } - // } - // } - // - // T is the type we are after. At every level that involves analyzing return types - // of signatures, we union the return types of all the signatures. - var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); - if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) { - return iteratorFunction; // any or unknown - } - - var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray; - if (iteratorFunctionSignatures.length === 0) { - error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator); - return unknownType; - } - - var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature)); - if (allConstituentTypesHaveKind(iterator, TypeFlags.Any)) { - return iterator; // any or unknown - } - - var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next"); - if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, TypeFlags.Any)) { - return iteratorNextFunction; // any or unknown - } - - var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray; - if (iteratorNextFunctionSignatures.length === 0) { - error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method); - return unknownType; - } - - var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature)); - if (allConstituentTypesHaveKind(iteratorNextResult, TypeFlags.Any)) { - return iteratorNextResult; // any or unknown - } - - var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); - if (!iteratorNextValue) { - error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property); - return unknownType; - } - - return iteratorNextValue; - // TODO - // Now even though we have extracted the iteratorNextValue, we will have to validate that the type + var iteratedType = getIteratedTypeSubroutine(iterable, expressionForError); + // Now even though we have extracted the iteratedType, we will have to validate that the type // passed in is actually an Iterable. + if (iteratedType !== unknownType) { + var completeIterableType = globalIterableType !== emptyObjectType ? createTypeReference(globalIterableType, [iteratedType]) : emptyObjectType; + checkTypeAssignableTo(iterable, completeIterableType, expressionForError); + } + + return iteratedType; + + function getIteratedTypeSubroutine(iterable: Type, expressionForError: Expression) { + Debug.assert(languageVersion >= ScriptTarget.ES6); + if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { + return iterable; // any or unknown + } + + // We want to treat type as an iterable, and get the type it is an iterable of. The iterable + // must have the following structure (annotated with the names of the variables below): + // + // { // iterable + // [Symbol.iterator]: { // iteratorFunction + // (): { // iterator + // next: { // iteratorNextFunction + // (): { // iteratorNextResult + // value: T // iteratorNextValue + // } + // } + // } + // } + // } + // + // T is the type we are after. At every level that involves analyzing return types + // of signatures, we union the return types of all the signatures. + var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); + if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) { + return iteratorFunction; // any or unknown + } + + var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray; + if (iteratorFunctionSignatures.length === 0) { + error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator); + return unknownType; + } + + var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature)); + if (allConstituentTypesHaveKind(iterator, TypeFlags.Any)) { + return iterator; // any or unknown + } + + var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next"); + if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, TypeFlags.Any)) { + return iteratorNextFunction; // any or unknown + } + + var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray; + if (iteratorNextFunctionSignatures.length === 0) { + error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method); + return unknownType; + } + + var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature)); + if (allConstituentTypesHaveKind(iteratorNextResult, TypeFlags.Any)) { + return iteratorNextResult; // any or unknown + } + + var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); + if (!iteratorNextValue) { + error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property); + return unknownType; + } + + return iteratorNextValue; + } } function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { @@ -10856,6 +10866,7 @@ module ts { globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray"); globalESSymbolType = getGlobalType("Symbol"); globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"); + globalIterableType = getGlobalType("Iterable", 1); } else { globalTemplateStringsArrayType = unknownType; diff --git a/tests/baselines/reference/for-of29.errors.txt b/tests/baselines/reference/for-of29.errors.txt new file mode 100644 index 00000000000..748fcf49050 --- /dev/null +++ b/tests/baselines/reference/for-of29.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/es6/for-ofStatements/for-of29.ts(5,15): error TS2322: Type '{ [Symbol.iterator]?(): Iterator; }' is not assignable to type 'Iterable'. + Property '[Symbol.iterator]' is optional in type '{ [Symbol.iterator]?(): Iterator; }' but required in type 'Iterable'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of29.ts (1 errors) ==== + var iterableWithOptionalIterator: { + [Symbol.iterator]?(): Iterator + }; + + for (var v of iterableWithOptionalIterator) { } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ [Symbol.iterator]?(): Iterator; }' is not assignable to type 'Iterable'. +!!! error TS2322: Property '[Symbol.iterator]' is optional in type '{ [Symbol.iterator]?(): Iterator; }' but required in type 'Iterable'. + \ No newline at end of file diff --git a/tests/baselines/reference/for-of29.js b/tests/baselines/reference/for-of29.js new file mode 100644 index 00000000000..450cafbde85 --- /dev/null +++ b/tests/baselines/reference/for-of29.js @@ -0,0 +1,11 @@ +//// [for-of29.ts] +var iterableWithOptionalIterator: { + [Symbol.iterator]?(): Iterator +}; + +for (var v of iterableWithOptionalIterator) { } + + +//// [for-of29.js] +var iterableWithOptionalIterator; +for (var v of iterableWithOptionalIterator) { } diff --git a/tests/baselines/reference/for-of30.errors.txt b/tests/baselines/reference/for-of30.errors.txt new file mode 100644 index 00000000000..6434b5294d5 --- /dev/null +++ b/tests/baselines/reference/for-of30.errors.txt @@ -0,0 +1,32 @@ +tests/cases/conformance/es6/for-ofStatements/for-of30.ts(1,15): error TS2322: Type 'StringIterator' is not assignable to type 'Iterable'. + Types of property '[Symbol.iterator]' are incompatible. + Type '() => StringIterator' is not assignable to type '() => Iterator'. + Type 'StringIterator' is not assignable to type 'Iterator'. + Types of property 'return' are incompatible. + Type 'number' is not assignable to type '(value?: any) => IteratorResult'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of30.ts (1 errors) ==== + for (var v of new StringIterator) { } + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'StringIterator' is not assignable to type 'Iterable'. +!!! error TS2322: Types of property '[Symbol.iterator]' are incompatible. +!!! error TS2322: Type '() => StringIterator' is not assignable to type '() => Iterator'. +!!! error TS2322: Type 'StringIterator' is not assignable to type 'Iterator'. +!!! error TS2322: Types of property 'return' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type '(value?: any) => IteratorResult'. + + class StringIterator { + next() { + return { + done: false, + value: "" + } + } + + return = 0; + + [Symbol.iterator]() { + return this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of30.js b/tests/baselines/reference/for-of30.js new file mode 100644 index 00000000000..4618dae5ff6 --- /dev/null +++ b/tests/baselines/reference/for-of30.js @@ -0,0 +1,35 @@ +//// [for-of30.ts] +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return { + done: false, + value: "" + } + } + + return = 0; + + [Symbol.iterator]() { + return this; + } +} + +//// [for-of30.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + this.return = 0; + } + StringIterator.prototype.next = function () { + return { + done: false, + value: "" + }; + }; + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of31.errors.txt b/tests/baselines/reference/for-of31.errors.txt new file mode 100644 index 00000000000..74afff00e99 --- /dev/null +++ b/tests/baselines/reference/for-of31.errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/es6/for-ofStatements/for-of31.ts(1,15): error TS2322: Type 'StringIterator' is not assignable to type 'Iterable'. + Types of property '[Symbol.iterator]' are incompatible. + Type '() => StringIterator' is not assignable to type '() => Iterator'. + Type 'StringIterator' is not assignable to type 'Iterator'. + Types of property 'next' are incompatible. + Type '() => { value: string; }' is not assignable to type '() => IteratorResult'. + Type '{ value: string; }' is not assignable to type 'IteratorResult'. + Property 'done' is missing in type '{ value: string; }'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of31.ts (1 errors) ==== + for (var v of new StringIterator) { } + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'StringIterator' is not assignable to type 'Iterable'. +!!! error TS2322: Types of property '[Symbol.iterator]' are incompatible. +!!! error TS2322: Type '() => StringIterator' is not assignable to type '() => Iterator'. +!!! error TS2322: Type 'StringIterator' is not assignable to type 'Iterator'. +!!! error TS2322: Types of property 'next' are incompatible. +!!! error TS2322: Type '() => { value: string; }' is not assignable to type '() => IteratorResult'. +!!! error TS2322: Type '{ value: string; }' is not assignable to type 'IteratorResult'. +!!! error TS2322: Property 'done' is missing in type '{ value: string; }'. + + class StringIterator { + next() { + return { + // no done property + value: "" + } + } + + [Symbol.iterator]() { + return this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of31.js b/tests/baselines/reference/for-of31.js new file mode 100644 index 00000000000..588c75a1145 --- /dev/null +++ b/tests/baselines/reference/for-of31.js @@ -0,0 +1,32 @@ +//// [for-of31.ts] +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return { + // no done property + value: "" + } + } + + [Symbol.iterator]() { + return this; + } +} + +//// [for-of31.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype.next = function () { + return { + // no done property + value: "" + }; + }; + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of29.ts b/tests/cases/conformance/es6/for-ofStatements/for-of29.ts new file mode 100644 index 00000000000..8df83db1588 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of29.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var iterableWithOptionalIterator: { + [Symbol.iterator]?(): Iterator +}; + +for (var v of iterableWithOptionalIterator) { } diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of30.ts b/tests/cases/conformance/es6/for-ofStatements/for-of30.ts new file mode 100644 index 00000000000..03b97c23136 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of30.ts @@ -0,0 +1,17 @@ +//@target: ES6 +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return { + done: false, + value: "" + } + } + + return = 0; + + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of31.ts b/tests/cases/conformance/es6/for-ofStatements/for-of31.ts new file mode 100644 index 00000000000..307f9b7cd43 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of31.ts @@ -0,0 +1,15 @@ +//@target: ES6 +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return { + // no done property + value: "" + } + } + + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file From 034bd0952615b629d0f9a76053b7c8ef30cd0a19 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Tue, 24 Feb 2015 17:26:16 -0800 Subject: [PATCH 14/26] Add tests for circular references in for...of loops --- src/compiler/checker.ts | 15 +-------- tests/baselines/reference/for-of32.errors.txt | 7 ++++ tests/baselines/reference/for-of32.js | 5 +++ tests/baselines/reference/for-of33.errors.txt | 13 ++++++++ tests/baselines/reference/for-of33.js | 19 +++++++++++ tests/baselines/reference/for-of34.errors.txt | 17 ++++++++++ tests/baselines/reference/for-of34.js | 26 +++++++++++++++ tests/baselines/reference/for-of35.errors.txt | 20 ++++++++++++ tests/baselines/reference/for-of35.js | 32 +++++++++++++++++++ .../es6/for-ofStatements/for-of32.ts | 3 ++ .../es6/for-ofStatements/for-of33.ts | 9 ++++++ .../es6/for-ofStatements/for-of34.ts | 13 ++++++++ .../es6/for-ofStatements/for-of35.ts | 16 ++++++++++ 13 files changed, 181 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/for-of32.errors.txt create mode 100644 tests/baselines/reference/for-of32.js create mode 100644 tests/baselines/reference/for-of33.errors.txt create mode 100644 tests/baselines/reference/for-of33.js create mode 100644 tests/baselines/reference/for-of34.errors.txt create mode 100644 tests/baselines/reference/for-of34.js create mode 100644 tests/baselines/reference/for-of35.errors.txt create mode 100644 tests/baselines/reference/for-of35.js create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of32.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of33.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of34.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of35.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ae20772a209..7c4b9fe8dca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8828,20 +8828,7 @@ module ts { return anyType; } - var variable = forOfStatement.initializer; - var links = getNodeLinks(variable); - if (!links.resolvedType) { - links.resolvedType = resolvingType; - var type = getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression); - if (links.resolvedType === resolvingType) { - links.resolvedType = type; - } - } - else if (links.resolvedType === resolvingType) { - links.resolvedType = anyType; - } - - return links.resolvedType; + return getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression); } function getIteratedType(iterable: Type, expressionForError: Expression): Type { diff --git a/tests/baselines/reference/for-of32.errors.txt b/tests/baselines/reference/for-of32.errors.txt new file mode 100644 index 00000000000..4b139d386c0 --- /dev/null +++ b/tests/baselines/reference/for-of32.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/es6/for-ofStatements/for-of32.ts(1,10): error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of32.ts (1 errors) ==== + for (var v of v) { } + ~ +!!! error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. \ No newline at end of file diff --git a/tests/baselines/reference/for-of32.js b/tests/baselines/reference/for-of32.js new file mode 100644 index 00000000000..d25d16fbebe --- /dev/null +++ b/tests/baselines/reference/for-of32.js @@ -0,0 +1,5 @@ +//// [for-of32.ts] +for (var v of v) { } + +//// [for-of32.js] +for (var v of v) { } diff --git a/tests/baselines/reference/for-of33.errors.txt b/tests/baselines/reference/for-of33.errors.txt new file mode 100644 index 00000000000..1c631042d7d --- /dev/null +++ b/tests/baselines/reference/for-of33.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/es6/for-ofStatements/for-of33.ts(1,10): error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of33.ts (1 errors) ==== + for (var v of new StringIterator) { } + ~ +!!! error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + class StringIterator { + [Symbol.iterator]() { + return v; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of33.js b/tests/baselines/reference/for-of33.js new file mode 100644 index 00000000000..91d8de41c6a --- /dev/null +++ b/tests/baselines/reference/for-of33.js @@ -0,0 +1,19 @@ +//// [for-of33.ts] +for (var v of new StringIterator) { } + +class StringIterator { + [Symbol.iterator]() { + return v; + } +} + +//// [for-of33.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype[Symbol.iterator] = function () { + return v; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of34.errors.txt b/tests/baselines/reference/for-of34.errors.txt new file mode 100644 index 00000000000..994302db88b --- /dev/null +++ b/tests/baselines/reference/for-of34.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/es6/for-ofStatements/for-of34.ts(1,10): error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of34.ts (1 errors) ==== + for (var v of new StringIterator) { } + ~ +!!! error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + class StringIterator { + next() { + return v; + } + + [Symbol.iterator]() { + return this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of34.js b/tests/baselines/reference/for-of34.js new file mode 100644 index 00000000000..ccb6006c63d --- /dev/null +++ b/tests/baselines/reference/for-of34.js @@ -0,0 +1,26 @@ +//// [for-of34.ts] +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return v; + } + + [Symbol.iterator]() { + return this; + } +} + +//// [for-of34.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype.next = function () { + return v; + }; + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/baselines/reference/for-of35.errors.txt b/tests/baselines/reference/for-of35.errors.txt new file mode 100644 index 00000000000..f83b6d2ec3c --- /dev/null +++ b/tests/baselines/reference/for-of35.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/es6/for-ofStatements/for-of35.ts(1,10): error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of35.ts (1 errors) ==== + for (var v of new StringIterator) { } + ~ +!!! error TS7022: 'v' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer. + + class StringIterator { + next() { + return { + done: true, + value: v + } + } + + [Symbol.iterator]() { + return this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of35.js b/tests/baselines/reference/for-of35.js new file mode 100644 index 00000000000..a4f1a37e3bf --- /dev/null +++ b/tests/baselines/reference/for-of35.js @@ -0,0 +1,32 @@ +//// [for-of35.ts] +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return { + done: true, + value: v + } + } + + [Symbol.iterator]() { + return this; + } +} + +//// [for-of35.js] +for (var v of new StringIterator) { } +var StringIterator = (function () { + function StringIterator() { + } + StringIterator.prototype.next = function () { + return { + done: true, + value: v + }; + }; + StringIterator.prototype[Symbol.iterator] = function () { + return this; + }; + return StringIterator; +})(); diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of32.ts b/tests/cases/conformance/es6/for-ofStatements/for-of32.ts new file mode 100644 index 00000000000..de95350b724 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of32.ts @@ -0,0 +1,3 @@ +//@target: ES6 +//@noImplicitAny: true +for (var v of v) { } \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of33.ts b/tests/cases/conformance/es6/for-ofStatements/for-of33.ts new file mode 100644 index 00000000000..b73d2daee8a --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of33.ts @@ -0,0 +1,9 @@ +//@target: ES6 +//@noImplicitAny: true +for (var v of new StringIterator) { } + +class StringIterator { + [Symbol.iterator]() { + return v; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of34.ts b/tests/cases/conformance/es6/for-ofStatements/for-of34.ts new file mode 100644 index 00000000000..d00f5ccde2e --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of34.ts @@ -0,0 +1,13 @@ +//@target: ES6 +//@noImplicitAny: true +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return v; + } + + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of35.ts b/tests/cases/conformance/es6/for-ofStatements/for-of35.ts new file mode 100644 index 00000000000..0d66ce39edf --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of35.ts @@ -0,0 +1,16 @@ +//@target: ES6 +//@noImplicitAny: true +for (var v of new StringIterator) { } + +class StringIterator { + next() { + return { + done: true, + value: v + } + } + + [Symbol.iterator]() { + return this; + } +} \ No newline at end of file From c00a264bb7b3e2870261e657d9489c4834325fcd Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 25 Feb 2015 14:28:37 -0800 Subject: [PATCH 15/26] Move assert --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7c4b9fe8dca..6df535bd322 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8832,6 +8832,7 @@ module ts { } function getIteratedType(iterable: Type, expressionForError: Expression): Type { + Debug.assert(languageVersion >= ScriptTarget.ES6); var iteratedType = getIteratedTypeSubroutine(iterable, expressionForError); // Now even though we have extracted the iteratedType, we will have to validate that the type // passed in is actually an Iterable. @@ -8843,7 +8844,6 @@ module ts { return iteratedType; function getIteratedTypeSubroutine(iterable: Type, expressionForError: Expression) { - Debug.assert(languageVersion >= ScriptTarget.ES6); if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { return iterable; // any or unknown } From f3543b718f389cb6678bfc7b192b40c99ee0966e Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 25 Feb 2015 18:15:48 -0800 Subject: [PATCH 16/26] In ES6, an Iterable should contextually type an array literal --- src/compiler/checker.ts | 52 +++++++++++++------ tests/baselines/reference/for-of36.js | 11 ++++ tests/baselines/reference/for-of36.types | 12 +++++ tests/baselines/reference/for-of37.js | 11 ++++ tests/baselines/reference/for-of37.types | 15 ++++++ .../reference/iterableContextualTyping1.js | 5 ++ .../reference/iterableContextualTyping1.types | 12 +++++ .../es6/for-ofStatements/for-of36.ts | 5 ++ .../es6/for-ofStatements/for-of37.ts | 5 ++ .../iterableContextualTyping1.ts | 2 + 10 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 tests/baselines/reference/for-of36.js create mode 100644 tests/baselines/reference/for-of36.types create mode 100644 tests/baselines/reference/for-of37.js create mode 100644 tests/baselines/reference/for-of37.types create mode 100644 tests/baselines/reference/iterableContextualTyping1.js create mode 100644 tests/baselines/reference/iterableContextualTyping1.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of36.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of37.ts create mode 100644 tests/cases/conformance/expressions/contextualTyping/iterableContextualTyping1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6df535bd322..2e5d61f860a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5461,7 +5461,9 @@ module ts { var type = getContextualType(arrayLiteral); if (type) { var index = indexOf(arrayLiteral.elements, node); - return getTypeOfPropertyOfContextualType(type, "" + index) || getIndexTypeOfContextualType(type, IndexKind.Number); + return getTypeOfPropertyOfContextualType(type, "" + index) + || getIndexTypeOfContextualType(type, IndexKind.Number) + || (languageVersion >= ScriptTarget.ES6 ? getIteratedType(type, /*expressionForError*/ undefined) : undefined); } return undefined; } @@ -8770,7 +8772,14 @@ module ts { checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); var rightType = checkExpression(node.expression); var iteratedType = getIteratedType(rightType, node.expression); - checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); + + // iteratedType will be undefined if the rightType was missing properties/signatures + // required to get it's iteratedType (like [Symbol.iterator] or next). This may be + // because we accessed properties from anyType, or it may have led to an error inside + // getIteratedType. + if (iteratedType) { + checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); + } } checkSourceElement(node.statement); @@ -8828,15 +8837,22 @@ module ts { return anyType; } - return getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression); + // iteratedType will be undefined if the for-of expression type was missing properties/signatures + // required to get it's iteratedType (like [Symbol.iterator] or next). This may be + // because we accessed properties from anyType, or it may have led to an error inside + // getIteratedType. + return getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression) || anyType; } + /** + * When expressionForError is undefined, it means we should not report any errors. + */ function getIteratedType(iterable: Type, expressionForError: Expression): Type { Debug.assert(languageVersion >= ScriptTarget.ES6); var iteratedType = getIteratedTypeSubroutine(iterable, expressionForError); // Now even though we have extracted the iteratedType, we will have to validate that the type // passed in is actually an Iterable. - if (iteratedType !== unknownType) { + if (expressionForError && iteratedType) { var completeIterableType = globalIterableType !== emptyObjectType ? createTypeReference(globalIterableType, [iteratedType]) : emptyObjectType; checkTypeAssignableTo(iterable, completeIterableType, expressionForError); } @@ -8845,7 +8861,7 @@ module ts { function getIteratedTypeSubroutine(iterable: Type, expressionForError: Expression) { if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { - return iterable; // any or unknown + return undefined; } // We want to treat type as an iterable, and get the type it is an iterable of. The iterable @@ -8867,40 +8883,46 @@ module ts { // of signatures, we union the return types of all the signatures. var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) { - return iteratorFunction; // any or unknown + return undefined; } var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray; if (iteratorFunctionSignatures.length === 0) { - error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator); - return unknownType; + if (expressionForError) { + error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator); + } + return undefined; } var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature)); if (allConstituentTypesHaveKind(iterator, TypeFlags.Any)) { - return iterator; // any or unknown + return undefined; } var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next"); if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, TypeFlags.Any)) { - return iteratorNextFunction; // any or unknown + return undefined; } var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray; if (iteratorNextFunctionSignatures.length === 0) { - error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method); - return unknownType; + if (expressionForError) { + error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method); + } + return undefined; } var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature)); if (allConstituentTypesHaveKind(iteratorNextResult, TypeFlags.Any)) { - return iteratorNextResult; // any or unknown + return undefined; } var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); if (!iteratorNextValue) { - error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property); - return unknownType; + if (expressionForError) { + error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property); + } + return undefined; } return iteratorNextValue; diff --git a/tests/baselines/reference/for-of36.js b/tests/baselines/reference/for-of36.js new file mode 100644 index 00000000000..14523695151 --- /dev/null +++ b/tests/baselines/reference/for-of36.js @@ -0,0 +1,11 @@ +//// [for-of36.ts] +var tuple: [string, boolean] = ["", true]; +for (var v of tuple) { + v; +} + +//// [for-of36.js] +var tuple = ["", true]; +for (var v of tuple) { + v; +} diff --git a/tests/baselines/reference/for-of36.types b/tests/baselines/reference/for-of36.types new file mode 100644 index 00000000000..da03367ba5d --- /dev/null +++ b/tests/baselines/reference/for-of36.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of36.ts === +var tuple: [string, boolean] = ["", true]; +>tuple : [string, boolean] +>["", true] : [string, boolean] + +for (var v of tuple) { +>v : string | boolean +>tuple : [string, boolean] + + v; +>v : string | boolean +} diff --git a/tests/baselines/reference/for-of37.js b/tests/baselines/reference/for-of37.js new file mode 100644 index 00000000000..472193e6cb5 --- /dev/null +++ b/tests/baselines/reference/for-of37.js @@ -0,0 +1,11 @@ +//// [for-of37.ts] +var map = new Map([["", true]]); +for (var v of map) { + v; +} + +//// [for-of37.js] +var map = new Map([["", true]]); +for (var v of map) { + v; +} diff --git a/tests/baselines/reference/for-of37.types b/tests/baselines/reference/for-of37.types new file mode 100644 index 00000000000..f137db79af0 --- /dev/null +++ b/tests/baselines/reference/for-of37.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of37.ts === +var map = new Map([["", true]]); +>map : Map +>new Map([["", true]]) : Map +>Map : MapConstructor +>[["", true]] : [string, boolean][] +>["", true] : [string, boolean] + +for (var v of map) { +>v : [string, boolean] +>map : Map + + v; +>v : [string, boolean] +} diff --git a/tests/baselines/reference/iterableContextualTyping1.js b/tests/baselines/reference/iterableContextualTyping1.js new file mode 100644 index 00000000000..8621bbd8417 --- /dev/null +++ b/tests/baselines/reference/iterableContextualTyping1.js @@ -0,0 +1,5 @@ +//// [iterableContextualTyping1.ts] +var iter: Iterable<(x: string) => number> = [s => s.length]; + +//// [iterableContextualTyping1.js] +var iter = [s => s.length]; diff --git a/tests/baselines/reference/iterableContextualTyping1.types b/tests/baselines/reference/iterableContextualTyping1.types new file mode 100644 index 00000000000..386d64312fc --- /dev/null +++ b/tests/baselines/reference/iterableContextualTyping1.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/expressions/contextualTyping/iterableContextualTyping1.ts === +var iter: Iterable<(x: string) => number> = [s => s.length]; +>iter : Iterable<(x: string) => number> +>Iterable : Iterable +>x : string +>[s => s.length] : ((s: string) => number)[] +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of36.ts b/tests/cases/conformance/es6/for-ofStatements/for-of36.ts new file mode 100644 index 00000000000..e67806fef64 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of36.ts @@ -0,0 +1,5 @@ +//@target: ES6 +var tuple: [string, boolean] = ["", true]; +for (var v of tuple) { + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of37.ts b/tests/cases/conformance/es6/for-ofStatements/for-of37.ts new file mode 100644 index 00000000000..561e3bf2e52 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of37.ts @@ -0,0 +1,5 @@ +//@target: ES6 +var map = new Map([["", true]]); +for (var v of map) { + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/contextualTyping/iterableContextualTyping1.ts b/tests/cases/conformance/expressions/contextualTyping/iterableContextualTyping1.ts new file mode 100644 index 00000000000..542d1928011 --- /dev/null +++ b/tests/cases/conformance/expressions/contextualTyping/iterableContextualTyping1.ts @@ -0,0 +1,2 @@ +//@target: ES6 +var iter: Iterable<(x: string) => number> = [s => s.length]; \ No newline at end of file From 00408a68d3f5f6635af28eae5312d7148d44652a Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 25 Feb 2015 18:56:12 -0800 Subject: [PATCH 17/26] Add tests for for-of destructuring --- tests/baselines/reference/for-of38.js | 13 ++++++++++ tests/baselines/reference/for-of38.types | 19 +++++++++++++++ tests/baselines/reference/for-of39.errors.txt | 13 ++++++++++ tests/baselines/reference/for-of39.js | 13 ++++++++++ tests/baselines/reference/for-of40.js | 13 ++++++++++ tests/baselines/reference/for-of40.types | 19 +++++++++++++++ tests/baselines/reference/for-of41.js | 13 ++++++++++ tests/baselines/reference/for-of41.types | 24 +++++++++++++++++++ tests/baselines/reference/for-of42.js | 13 ++++++++++ tests/baselines/reference/for-of42.types | 21 ++++++++++++++++ tests/baselines/reference/for-of43.errors.txt | 11 +++++++++ tests/baselines/reference/for-of43.js | 13 ++++++++++ tests/baselines/reference/for-of44.js | 13 ++++++++++ tests/baselines/reference/for-of44.types | 21 ++++++++++++++++ tests/baselines/reference/for-of45.types | 24 +++++++++++++++++++ .../es6/for-ofStatements/for-of38.ts | 6 +++++ .../es6/for-ofStatements/for-of39.ts | 6 +++++ .../es6/for-ofStatements/for-of40.ts | 6 +++++ .../es6/for-ofStatements/for-of41.ts | 6 +++++ .../es6/for-ofStatements/for-of42.ts | 6 +++++ .../es6/for-ofStatements/for-of43.ts | 6 +++++ .../es6/for-ofStatements/for-of44.ts | 6 +++++ 22 files changed, 285 insertions(+) create mode 100644 tests/baselines/reference/for-of38.js create mode 100644 tests/baselines/reference/for-of38.types create mode 100644 tests/baselines/reference/for-of39.errors.txt create mode 100644 tests/baselines/reference/for-of39.js create mode 100644 tests/baselines/reference/for-of40.js create mode 100644 tests/baselines/reference/for-of40.types create mode 100644 tests/baselines/reference/for-of41.js create mode 100644 tests/baselines/reference/for-of41.types create mode 100644 tests/baselines/reference/for-of42.js create mode 100644 tests/baselines/reference/for-of42.types create mode 100644 tests/baselines/reference/for-of43.errors.txt create mode 100644 tests/baselines/reference/for-of43.js create mode 100644 tests/baselines/reference/for-of44.js create mode 100644 tests/baselines/reference/for-of44.types create mode 100644 tests/baselines/reference/for-of45.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of38.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of39.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of40.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of41.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of42.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of43.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of44.ts diff --git a/tests/baselines/reference/for-of38.js b/tests/baselines/reference/for-of38.js new file mode 100644 index 00000000000..1f0ac09682e --- /dev/null +++ b/tests/baselines/reference/for-of38.js @@ -0,0 +1,13 @@ +//// [for-of38.ts] +var map = new Map([["", true]]); +for (var [k, v] of map) { + k; + v; +} + +//// [for-of38.js] +var map = new Map([["", true]]); +for (var [k, v] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of38.types b/tests/baselines/reference/for-of38.types new file mode 100644 index 00000000000..cdd1e05dd7e --- /dev/null +++ b/tests/baselines/reference/for-of38.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of38.ts === +var map = new Map([["", true]]); +>map : Map +>new Map([["", true]]) : Map +>Map : MapConstructor +>[["", true]] : [string, boolean][] +>["", true] : [string, boolean] + +for (var [k, v] of map) { +>k : string +>v : boolean +>map : Map + + k; +>k : string + + v; +>v : boolean +} diff --git a/tests/baselines/reference/for-of39.errors.txt b/tests/baselines/reference/for-of39.errors.txt new file mode 100644 index 00000000000..48db183a58c --- /dev/null +++ b/tests/baselines/reference/for-of39.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,15): error TS2453: The type argument for type parameter 'V' cannot be inferred from the usage. Consider specifying the type arguments explicitly. + Type argument candidate 'boolean' is not a valid type argument because it is not a supertype of candidate 'number'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of39.ts (1 errors) ==== + var map = new Map([["", true], ["", 0]]); + ~~~ +!!! error TS2453: The type argument for type parameter 'V' cannot be inferred from the usage. Consider specifying the type arguments explicitly. +!!! error TS2453: Type argument candidate 'boolean' is not a valid type argument because it is not a supertype of candidate 'number'. + for (var [k, v] of map) { + k; + v; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of39.js b/tests/baselines/reference/for-of39.js new file mode 100644 index 00000000000..91dbc56c0ab --- /dev/null +++ b/tests/baselines/reference/for-of39.js @@ -0,0 +1,13 @@ +//// [for-of39.ts] +var map = new Map([["", true], ["", 0]]); +for (var [k, v] of map) { + k; + v; +} + +//// [for-of39.js] +var map = new Map([["", true], ["", 0]]); +for (var [k, v] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of40.js b/tests/baselines/reference/for-of40.js new file mode 100644 index 00000000000..243f81097db --- /dev/null +++ b/tests/baselines/reference/for-of40.js @@ -0,0 +1,13 @@ +//// [for-of40.ts] +var map = new Map([["", true]]); +for (var [k = "", v = false] of map) { + k; + v; +} + +//// [for-of40.js] +var map = new Map([["", true]]); +for (var [k = "", v = false] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of40.types b/tests/baselines/reference/for-of40.types new file mode 100644 index 00000000000..c0fe7cbbc02 --- /dev/null +++ b/tests/baselines/reference/for-of40.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of40.ts === +var map = new Map([["", true]]); +>map : Map +>new Map([["", true]]) : Map +>Map : MapConstructor +>[["", true]] : [string, boolean][] +>["", true] : [string, boolean] + +for (var [k = "", v = false] of map) { +>k : string +>v : boolean +>map : Map + + k; +>k : string + + v; +>v : boolean +} diff --git a/tests/baselines/reference/for-of41.js b/tests/baselines/reference/for-of41.js new file mode 100644 index 00000000000..0fa380c53c4 --- /dev/null +++ b/tests/baselines/reference/for-of41.js @@ -0,0 +1,13 @@ +//// [for-of41.ts] +var array = [{x: [0], y: {p: ""}}] +for (var {x: [a], y: {p}} of array) { + a; + p; +} + +//// [for-of41.js] +var array = [{ x: [0], y: { p: "" } }]; +for (var { x: [a], y: { p } } of array) { + a; + p; +} diff --git a/tests/baselines/reference/for-of41.types b/tests/baselines/reference/for-of41.types new file mode 100644 index 00000000000..54e58aa1ec7 --- /dev/null +++ b/tests/baselines/reference/for-of41.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of41.ts === +var array = [{x: [0], y: {p: ""}}] +>array : { x: number[]; y: { p: string; }; }[] +>[{x: [0], y: {p: ""}}] : { x: number[]; y: { p: string; }; }[] +>{x: [0], y: {p: ""}} : { x: number[]; y: { p: string; }; } +>x : number[] +>[0] : number[] +>y : { p: string; } +>{p: ""} : { p: string; } +>p : string + +for (var {x: [a], y: {p}} of array) { +>x : unknown +>a : number +>y : unknown +>p : string +>array : { x: number[]; y: { p: string; }; }[] + + a; +>a : number + + p; +>p : string +} diff --git a/tests/baselines/reference/for-of42.js b/tests/baselines/reference/for-of42.js new file mode 100644 index 00000000000..1fa9219df47 --- /dev/null +++ b/tests/baselines/reference/for-of42.js @@ -0,0 +1,13 @@ +//// [for-of42.ts] +var array = [{ x: "", y: 0 }] +for (var {x: a, y: b} of array) { + a; + b; +} + +//// [for-of42.js] +var array = [{ x: "", y: 0 }]; +for (var { x: a, y: b } of array) { + a; + b; +} diff --git a/tests/baselines/reference/for-of42.types b/tests/baselines/reference/for-of42.types new file mode 100644 index 00000000000..1a819452770 --- /dev/null +++ b/tests/baselines/reference/for-of42.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of42.ts === +var array = [{ x: "", y: 0 }] +>array : { x: string; y: number; }[] +>[{ x: "", y: 0 }] : { x: string; y: number; }[] +>{ x: "", y: 0 } : { x: string; y: number; } +>x : string +>y : number + +for (var {x: a, y: b} of array) { +>x : unknown +>a : string +>y : unknown +>b : number +>array : { x: string; y: number; }[] + + a; +>a : string + + b; +>b : number +} diff --git a/tests/baselines/reference/for-of43.errors.txt b/tests/baselines/reference/for-of43.errors.txt new file mode 100644 index 00000000000..c5790278e53 --- /dev/null +++ b/tests/baselines/reference/for-of43.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/es6/for-ofStatements/for-of43.ts(2,25): error TS2322: Type 'boolean' is not assignable to type 'number'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of43.ts (1 errors) ==== + var array = [{ x: "", y: 0 }] + for (var {x: a = "", y: b = true} of array) { + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. + a; + b; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of43.js b/tests/baselines/reference/for-of43.js new file mode 100644 index 00000000000..de3b4fcd9b0 --- /dev/null +++ b/tests/baselines/reference/for-of43.js @@ -0,0 +1,13 @@ +//// [for-of43.ts] +var array = [{ x: "", y: 0 }] +for (var {x: a = "", y: b = true} of array) { + a; + b; +} + +//// [for-of43.js] +var array = [{ x: "", y: 0 }]; +for (var { x: a = "", y: b = true } of array) { + a; + b; +} diff --git a/tests/baselines/reference/for-of44.js b/tests/baselines/reference/for-of44.js new file mode 100644 index 00000000000..087485ed73f --- /dev/null +++ b/tests/baselines/reference/for-of44.js @@ -0,0 +1,13 @@ +//// [for-of44.ts] +var array: [number, string | boolean | symbol][] = [[0, ""], [0, true], [1, Symbol()]] +for (var [num, strBoolSym] of array) { + num; + strBoolSym; +} + +//// [for-of44.js] +var array = [[0, ""], [0, true], [1, Symbol()]]; +for (var [num, strBoolSym] of array) { + num; + strBoolSym; +} diff --git a/tests/baselines/reference/for-of44.types b/tests/baselines/reference/for-of44.types new file mode 100644 index 00000000000..078b49bd309 --- /dev/null +++ b/tests/baselines/reference/for-of44.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of44.ts === +var array: [number, string | boolean | symbol][] = [[0, ""], [0, true], [1, Symbol()]] +>array : [number, string | boolean | symbol][] +>[[0, ""], [0, true], [1, Symbol()]] : ([number, string] | [number, boolean] | [number, symbol])[] +>[0, ""] : [number, string] +>[0, true] : [number, boolean] +>[1, Symbol()] : [number, symbol] +>Symbol() : symbol +>Symbol : SymbolConstructor + +for (var [num, strBoolSym] of array) { +>num : number +>strBoolSym : string | boolean | symbol +>array : [number, string | boolean | symbol][] + + num; +>num : number + + strBoolSym; +>strBoolSym : string | boolean | symbol +} diff --git a/tests/baselines/reference/for-of45.types b/tests/baselines/reference/for-of45.types new file mode 100644 index 00000000000..53b82a90111 --- /dev/null +++ b/tests/baselines/reference/for-of45.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of45.ts === +var array = [{x: [0], y: {p: ""}}] +>array : { x: number[]; y: { p: string; }; }[] +>[{x: [0], y: {p: ""}}] : { x: number[]; y: { p: string; }; }[] +>{x: [0], y: {p: ""}} : { x: number[]; y: { p: string; }; } +>x : number[] +>[0] : number[] +>y : { p: string; } +>{p: ""} : { p: string; } +>p : string + +for (var {x: [a], y: {p}} of array) { +>x : unknown +>a : number +>y : unknown +>p : string +>array : { x: number[]; y: { p: string; }; }[] + + a; +>a : number + + p; +>p : string +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of38.ts b/tests/cases/conformance/es6/for-ofStatements/for-of38.ts new file mode 100644 index 00000000000..0511ff140bd --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of38.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var map = new Map([["", true]]); +for (var [k, v] of map) { + k; + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of39.ts b/tests/cases/conformance/es6/for-ofStatements/for-of39.ts new file mode 100644 index 00000000000..1d3ae5fc76c --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of39.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var map = new Map([["", true], ["", 0]]); +for (var [k, v] of map) { + k; + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of40.ts b/tests/cases/conformance/es6/for-ofStatements/for-of40.ts new file mode 100644 index 00000000000..128e6b4f186 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of40.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var map = new Map([["", true]]); +for (var [k = "", v = false] of map) { + k; + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of41.ts b/tests/cases/conformance/es6/for-ofStatements/for-of41.ts new file mode 100644 index 00000000000..207ab8ab2b9 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of41.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var array = [{x: [0], y: {p: ""}}] +for (var {x: [a], y: {p}} of array) { + a; + p; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of42.ts b/tests/cases/conformance/es6/for-ofStatements/for-of42.ts new file mode 100644 index 00000000000..2eb25ab52f2 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of42.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var array = [{ x: "", y: 0 }] +for (var {x: a, y: b} of array) { + a; + b; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of43.ts b/tests/cases/conformance/es6/for-ofStatements/for-of43.ts new file mode 100644 index 00000000000..fec349e1073 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of43.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var array = [{ x: "", y: 0 }] +for (var {x: a = "", y: b = true} of array) { + a; + b; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of44.ts b/tests/cases/conformance/es6/for-ofStatements/for-of44.ts new file mode 100644 index 00000000000..7d7d21d8691 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of44.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var array: [number, string | boolean | symbol][] = [[0, ""], [0, true], [1, Symbol()]] +for (var [num, strBoolSym] of array) { + num; + strBoolSym; +} \ No newline at end of file From 79b609b6323755426ff07dd2d90f31d26fb700aa Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 26 Feb 2015 10:27:16 -0800 Subject: [PATCH 18/26] Update comment --- src/compiler/checker.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2e5d61f860a..be59b41fbee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5454,8 +5454,9 @@ module ts { } // In an array literal contextually typed by a type T, the contextual type of an element expression at index N is - // the type of the property with the numeric name N in T, if one exists. Otherwise, it is the type of the numeric - // index signature in T, if one exists. + // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature, + // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated + // type of T. function getContextualTypeForElementExpression(node: Expression): Type { var arrayLiteral = node.parent; var type = getContextualType(arrayLiteral); From 9faa09b5d7e058f7d9a33d419f513de4965df97a Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 26 Feb 2015 15:11:48 -0800 Subject: [PATCH 19/26] Delete bad baseline --- tests/baselines/reference/for-of45.types | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 tests/baselines/reference/for-of45.types diff --git a/tests/baselines/reference/for-of45.types b/tests/baselines/reference/for-of45.types deleted file mode 100644 index 53b82a90111..00000000000 --- a/tests/baselines/reference/for-of45.types +++ /dev/null @@ -1,24 +0,0 @@ -=== tests/cases/conformance/es6/for-ofStatements/for-of45.ts === -var array = [{x: [0], y: {p: ""}}] ->array : { x: number[]; y: { p: string; }; }[] ->[{x: [0], y: {p: ""}}] : { x: number[]; y: { p: string; }; }[] ->{x: [0], y: {p: ""}} : { x: number[]; y: { p: string; }; } ->x : number[] ->[0] : number[] ->y : { p: string; } ->{p: ""} : { p: string; } ->p : string - -for (var {x: [a], y: {p}} of array) { ->x : unknown ->a : number ->y : unknown ->p : string ->array : { x: number[]; y: { p: string; }; }[] - - a; ->a : number - - p; ->p : string -} From f8150d3734759a0befc54a97074305efca6d86f9 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 26 Feb 2015 15:32:37 -0800 Subject: [PATCH 20/26] Support assignment patterns in 'for...of' statements --- src/compiler/checker.ts | 30 ++++++++++++------- tests/baselines/reference/for-of45.js | 15 ++++++++++ tests/baselines/reference/for-of45.types | 26 ++++++++++++++++ tests/baselines/reference/for-of46.errors.txt | 15 ++++++++++ tests/baselines/reference/for-of46.js | 15 ++++++++++ tests/baselines/reference/for-of47.errors.txt | 13 ++++++++ tests/baselines/reference/for-of47.js | 20 +++++++++++++ .../es6/for-ofStatements/for-of45.ts | 7 +++++ .../es6/for-ofStatements/for-of46.ts | 7 +++++ .../es6/for-ofStatements/for-of47.ts | 8 +++++ 10 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/for-of45.js create mode 100644 tests/baselines/reference/for-of45.types create mode 100644 tests/baselines/reference/for-of46.errors.txt create mode 100644 tests/baselines/reference/for-of46.js create mode 100644 tests/baselines/reference/for-of47.errors.txt create mode 100644 tests/baselines/reference/for-of47.js create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of45.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of46.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of47.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index be59b41fbee..ae1e9a398a2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7411,7 +7411,7 @@ module ts { return rightType; } - // Return type is true if there was no error, false if there was an error. + // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { var offendingSymbolOperand = someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left : @@ -8758,7 +8758,7 @@ module ts { grammarErrorOnFirstToken(node, Diagnostics.for_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher); return; } - + checkGrammarForInOrForOfStatement(node) // Check the LHS and RHS @@ -8769,17 +8769,27 @@ module ts { } else { var varExpr = node.initializer; - var leftType = checkExpression(varExpr); - checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); var rightType = checkExpression(node.expression); var iteratedType = getIteratedType(rightType, node.expression); - // iteratedType will be undefined if the rightType was missing properties/signatures - // required to get it's iteratedType (like [Symbol.iterator] or next). This may be - // because we accessed properties from anyType, or it may have led to an error inside - // getIteratedType. - if (iteratedType) { - checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); + // There may be a destructuring assignment on the left side + if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { + // iteratedType may be undefined. In this case, we still want to check the structure of + // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like + // to short circuit the type relation checking as much as possible, so we pass the unknownType. + checkDestructuringAssignment(varExpr, iteratedType || unknownType); + } + else { + var leftType = checkExpression(varExpr); + checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); + + // iteratedType will be undefined if the rightType was missing properties/signatures + // required to get it's iteratedType (like [Symbol.iterator] or next). This may be + // because we accessed properties from anyType, or it may have led to an error inside + // getIteratedType. + if (iteratedType) { + checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); + } } } diff --git a/tests/baselines/reference/for-of45.js b/tests/baselines/reference/for-of45.js new file mode 100644 index 00000000000..1222b2dcdd5 --- /dev/null +++ b/tests/baselines/reference/for-of45.js @@ -0,0 +1,15 @@ +//// [for-of45.ts] +var k: string, v: boolean; +var map = new Map([["", true]]); +for ([k = "", v = false] of map) { + k; + v; +} + +//// [for-of45.js] +var k, v; +var map = new Map([["", true]]); +for ([k = "", v = false] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of45.types b/tests/baselines/reference/for-of45.types new file mode 100644 index 00000000000..8ac4b9fa7e9 --- /dev/null +++ b/tests/baselines/reference/for-of45.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of45.ts === +var k: string, v: boolean; +>k : string +>v : boolean + +var map = new Map([["", true]]); +>map : Map +>new Map([["", true]]) : Map +>Map : MapConstructor +>[["", true]] : [string, boolean][] +>["", true] : [string, boolean] + +for ([k = "", v = false] of map) { +>[k = "", v = false] : (string | boolean)[] +>k = "" : string +>k : string +>v = false : boolean +>v : boolean +>map : Map + + k; +>k : string + + v; +>v : boolean +} diff --git a/tests/baselines/reference/for-of46.errors.txt b/tests/baselines/reference/for-of46.errors.txt new file mode 100644 index 00000000000..13685b122ca --- /dev/null +++ b/tests/baselines/reference/for-of46.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/es6/for-ofStatements/for-of46.ts(3,7): error TS2322: Type 'boolean' is not assignable to type 'string'. +tests/cases/conformance/es6/for-ofStatements/for-of46.ts(3,18): error TS2322: Type 'string' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of46.ts (2 errors) ==== + var k: string, v: boolean; + var map = new Map([["", true]]); + for ([k = false, v = ""] of map) { + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'string'. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. + k; + v; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of46.js b/tests/baselines/reference/for-of46.js new file mode 100644 index 00000000000..2ea15936c54 --- /dev/null +++ b/tests/baselines/reference/for-of46.js @@ -0,0 +1,15 @@ +//// [for-of46.ts] +var k: string, v: boolean; +var map = new Map([["", true]]); +for ([k = false, v = ""] of map) { + k; + v; +} + +//// [for-of46.js] +var k, v; +var map = new Map([["", true]]); +for ([k = false, v = ""] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of47.errors.txt b/tests/baselines/reference/for-of47.errors.txt new file mode 100644 index 00000000000..241dc107caa --- /dev/null +++ b/tests/baselines/reference/for-of47.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/es6/for-ofStatements/for-of47.ts(4,13): error TS2322: Type 'boolean' is not assignable to type 'number'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of47.ts (1 errors) ==== + var x: string, y: number; + var array = [{ x: "", y: true }] + enum E { x } + for ({x, y: y = E.x} of array) { + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. + x; + y; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of47.js b/tests/baselines/reference/for-of47.js new file mode 100644 index 00000000000..b2de46d677f --- /dev/null +++ b/tests/baselines/reference/for-of47.js @@ -0,0 +1,20 @@ +//// [for-of47.ts] +var x: string, y: number; +var array = [{ x: "", y: true }] +enum E { x } +for ({x, y: y = E.x} of array) { + x; + y; +} + +//// [for-of47.js] +var x, y; +var array = [{ x: "", y: true }]; +var E; +(function (E) { + E[E["x"] = 0] = "x"; +})(E || (E = {})); +for ({ x, y: y = 0 /* x */ } of array) { + x; + y; +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of45.ts b/tests/cases/conformance/es6/for-ofStatements/for-of45.ts new file mode 100644 index 00000000000..f347069ab10 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of45.ts @@ -0,0 +1,7 @@ +//@target: ES6 +var k: string, v: boolean; +var map = new Map([["", true]]); +for ([k = "", v = false] of map) { + k; + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of46.ts b/tests/cases/conformance/es6/for-ofStatements/for-of46.ts new file mode 100644 index 00000000000..a08791068b7 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of46.ts @@ -0,0 +1,7 @@ +//@target: ES6 +var k: string, v: boolean; +var map = new Map([["", true]]); +for ([k = false, v = ""] of map) { + k; + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of47.ts b/tests/cases/conformance/es6/for-ofStatements/for-of47.ts new file mode 100644 index 00000000000..bd21a0db382 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of47.ts @@ -0,0 +1,8 @@ +//@target: ES6 +var x: string, y: number; +var array = [{ x: "", y: true }] +enum E { x } +for ({x, y: y = E.x} of array) { + x; + y; +} \ No newline at end of file From 84a22be433f8d0e44e2d98af38d685d214499f45 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 26 Feb 2015 15:58:46 -0800 Subject: [PATCH 21/26] Add a few more tests --- tests/baselines/reference/for-of48.errors.txt | 13 ++++++++++++ tests/baselines/reference/for-of48.js | 20 +++++++++++++++++++ tests/baselines/reference/for-of49.errors.txt | 12 +++++++++++ tests/baselines/reference/for-of49.js | 15 ++++++++++++++ tests/baselines/reference/for-of50.js | 13 ++++++++++++ tests/baselines/reference/for-of50.types | 19 ++++++++++++++++++ .../es6/for-ofStatements/for-of48.ts | 8 ++++++++ .../es6/for-ofStatements/for-of49.ts | 7 +++++++ .../es6/for-ofStatements/for-of50.ts | 6 ++++++ 9 files changed, 113 insertions(+) create mode 100644 tests/baselines/reference/for-of48.errors.txt create mode 100644 tests/baselines/reference/for-of48.js create mode 100644 tests/baselines/reference/for-of49.errors.txt create mode 100644 tests/baselines/reference/for-of49.js create mode 100644 tests/baselines/reference/for-of50.js create mode 100644 tests/baselines/reference/for-of50.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of48.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of49.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of50.ts diff --git a/tests/baselines/reference/for-of48.errors.txt b/tests/baselines/reference/for-of48.errors.txt new file mode 100644 index 00000000000..f6826e14c61 --- /dev/null +++ b/tests/baselines/reference/for-of48.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/es6/for-ofStatements/for-of48.ts(4,12): error TS1005: ':' expected. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of48.ts (1 errors) ==== + var x: string, y: number; + var array = [{ x: "", y: true }] + enum E { x } + for ({x, y = E.x} of array) { + ~ +!!! error TS1005: ':' expected. + x; + y; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of48.js b/tests/baselines/reference/for-of48.js new file mode 100644 index 00000000000..15b9f5f12f6 --- /dev/null +++ b/tests/baselines/reference/for-of48.js @@ -0,0 +1,20 @@ +//// [for-of48.ts] +var x: string, y: number; +var array = [{ x: "", y: true }] +enum E { x } +for ({x, y = E.x} of array) { + x; + y; +} + +//// [for-of48.js] +var x, y; +var array = [{ x: "", y: true }]; +var E; +(function (E) { + E[E["x"] = 0] = "x"; +})(E || (E = {})); +for ({ x, y: = 0 /* x */ } of array) { + x; + y; +} diff --git a/tests/baselines/reference/for-of49.errors.txt b/tests/baselines/reference/for-of49.errors.txt new file mode 100644 index 00000000000..d5bc314e678 --- /dev/null +++ b/tests/baselines/reference/for-of49.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/es6/for-ofStatements/for-of49.ts(3,13): error TS2364: Invalid left-hand side of assignment expression. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of49.ts (1 errors) ==== + var k: string, v: boolean; + var map = new Map([["", true]]); + for ([k, ...[v]] of map) { + ~~~ +!!! error TS2364: Invalid left-hand side of assignment expression. + k; + v; + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of49.js b/tests/baselines/reference/for-of49.js new file mode 100644 index 00000000000..ac7f99f3607 --- /dev/null +++ b/tests/baselines/reference/for-of49.js @@ -0,0 +1,15 @@ +//// [for-of49.ts] +var k: string, v: boolean; +var map = new Map([["", true]]); +for ([k, ...[v]] of map) { + k; + v; +} + +//// [for-of49.js] +var k, v; +var map = new Map([["", true]]); +for ([k, ...[v]] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of50.js b/tests/baselines/reference/for-of50.js new file mode 100644 index 00000000000..bf1192c59dd --- /dev/null +++ b/tests/baselines/reference/for-of50.js @@ -0,0 +1,13 @@ +//// [for-of50.ts] +var map = new Map([["", true]]); +for (const [k, v] of map) { + k; + v; +} + +//// [for-of50.js] +var map = new Map([["", true]]); +for (var [k, v] of map) { + k; + v; +} diff --git a/tests/baselines/reference/for-of50.types b/tests/baselines/reference/for-of50.types new file mode 100644 index 00000000000..a38f3855174 --- /dev/null +++ b/tests/baselines/reference/for-of50.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of50.ts === +var map = new Map([["", true]]); +>map : Map +>new Map([["", true]]) : Map +>Map : MapConstructor +>[["", true]] : [string, boolean][] +>["", true] : [string, boolean] + +for (const [k, v] of map) { +>k : string +>v : boolean +>map : Map + + k; +>k : string + + v; +>v : boolean +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of48.ts b/tests/cases/conformance/es6/for-ofStatements/for-of48.ts new file mode 100644 index 00000000000..c2e228d0fb9 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of48.ts @@ -0,0 +1,8 @@ +//@target: ES6 +var x: string, y: number; +var array = [{ x: "", y: true }] +enum E { x } +for ({x, y = E.x} of array) { + x; + y; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of49.ts b/tests/cases/conformance/es6/for-ofStatements/for-of49.ts new file mode 100644 index 00000000000..62fa4acd425 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of49.ts @@ -0,0 +1,7 @@ +//@target: ES6 +var k: string, v: boolean; +var map = new Map([["", true]]); +for ([k, ...[v]] of map) { + k; + v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of50.ts b/tests/cases/conformance/es6/for-ofStatements/for-of50.ts new file mode 100644 index 00000000000..d4e1bba5ae4 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of50.ts @@ -0,0 +1,6 @@ +//@target: ES6 +var map = new Map([["", true]]); +for (const [k, v] of map) { + k; + v; +} \ No newline at end of file From fd0fd365977f344f153d426fdfea31d3865cd6fe Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 26 Feb 2015 18:16:21 -0800 Subject: [PATCH 22/26] Disallow destructuring in 'for...in' --- src/compiler/checker.ts | 10 +++++++++- src/compiler/diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 6 +++++- src/compiler/utilities.ts | 2 +- .../reference/for-inStatementsDestructuring.errors.txt | 7 +++++++ .../reference/for-inStatementsDestructuring.js | 5 +++++ .../for-inStatementsDestructuring2.errors.txt | 7 +++++++ .../reference/for-inStatementsDestructuring2.js | 5 +++++ .../for-inStatementsDestructuring3.errors.txt | 8 ++++++++ .../reference/for-inStatementsDestructuring3.js | 7 +++++++ .../for-inStatementsDestructuring4.errors.txt | 8 ++++++++ .../reference/for-inStatementsDestructuring4.js | 7 +++++++ .../baselines/reference/parserForStatement5.errors.txt | 4 ++-- .../for-inStatements/for-inStatementsDestructuring.ts | 1 + .../for-inStatements/for-inStatementsDestructuring2.ts | 1 + .../for-inStatements/for-inStatementsDestructuring3.ts | 2 ++ .../for-inStatements/for-inStatementsDestructuring4.ts | 2 ++ 17 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/for-inStatementsDestructuring.errors.txt create mode 100644 tests/baselines/reference/for-inStatementsDestructuring.js create mode 100644 tests/baselines/reference/for-inStatementsDestructuring2.errors.txt create mode 100644 tests/baselines/reference/for-inStatementsDestructuring2.js create mode 100644 tests/baselines/reference/for-inStatementsDestructuring3.errors.txt create mode 100644 tests/baselines/reference/for-inStatementsDestructuring3.js create mode 100644 tests/baselines/reference/for-inStatementsDestructuring4.errors.txt create mode 100644 tests/baselines/reference/for-inStatementsDestructuring4.js create mode 100644 tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring.ts create mode 100644 tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring2.ts create mode 100644 tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring3.ts create mode 100644 tests/cases/conformance/statements/for-inStatements/for-inStatementsDestructuring4.ts 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 From 996b9d27b4efd9a83613137ceb3f1f1e1cebddc2 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 27 Feb 2015 11:59:06 -0800 Subject: [PATCH 23/26] Respond to PR feedback --- src/compiler/checker.ts | 43 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 23aa8dc92c9..0f06a9d4b54 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5202,20 +5202,20 @@ module ts { if (container && container.parent && container.parent.kind === SyntaxKind.ClassDeclaration) { if (container.flags & NodeFlags.Static) { canUseSuperExpression = - container.kind === SyntaxKind.MethodDeclaration || - container.kind === SyntaxKind.MethodSignature || - container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor; + container.kind === SyntaxKind.MethodDeclaration || + container.kind === SyntaxKind.MethodSignature || + container.kind === SyntaxKind.GetAccessor || + container.kind === SyntaxKind.SetAccessor; } else { canUseSuperExpression = - container.kind === SyntaxKind.MethodDeclaration || - container.kind === SyntaxKind.MethodSignature || - container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor || - container.kind === SyntaxKind.PropertyDeclaration || - container.kind === SyntaxKind.PropertySignature || - container.kind === SyntaxKind.Constructor; + container.kind === SyntaxKind.MethodDeclaration || + container.kind === SyntaxKind.MethodSignature || + container.kind === SyntaxKind.GetAccessor || + container.kind === SyntaxKind.SetAccessor || + container.kind === SyntaxKind.PropertyDeclaration || + container.kind === SyntaxKind.PropertySignature || + container.kind === SyntaxKind.Constructor; } } } @@ -8879,10 +8879,6 @@ module ts { return iteratedType; function getIteratedTypeSubroutine(iterable: Type, expressionForError: Expression) { - if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { - return undefined; - } - // We want to treat type as an iterable, and get the type it is an iterable of. The iterable // must have the following structure (annotated with the names of the variables below): // @@ -8900,6 +8896,19 @@ module ts { // // T is the type we are after. At every level that involves analyzing return types // of signatures, we union the return types of all the signatures. + // + // Another thing to note is that at any step of this process, we could run into a dead end, + // meaning either the property is missing, or we run into the anyType. If either of these things + // happens, we return undefined to signal that we could not find the iterated type. If a property + // is missing, and the previous step did not result in 'any', then we also give an error if the + // caller requested it. Then the caller can decide what to do in the case where there is no iterated + // type. This is different from returning anyType, because that would signify that we have matched the + // whole pattern and that T (above) is 'any'. + + if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) { + return undefined; + } + var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator")); if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) { return undefined; @@ -10880,7 +10889,7 @@ module ts { globals[undefinedSymbol.name] = undefinedSymbol; // Initialize special types globalArraySymbol = getGlobalTypeSymbol("Array"); - globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, 1); + globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, /*arity*/ 1); globalObjectType = getGlobalType("Object"); globalFunctionType = getGlobalType("Function"); globalStringType = getGlobalType("String"); @@ -10894,7 +10903,7 @@ module ts { globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray"); globalESSymbolType = getGlobalType("Symbol"); globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"); - globalIterableType = getGlobalType("Iterable", 1); + globalIterableType = getGlobalType("Iterable", /*arity*/ 1); } else { globalTemplateStringsArrayType = unknownType; From 8da49aaf443e453b40c967fe429b3b47b0f39c1a Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Sun, 1 Mar 2015 16:45:14 -0800 Subject: [PATCH 24/26] Address feedback --- src/compiler/checker.ts | 59 +++++++++++-------- .../diagnosticInformationMap.generated.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- tests/baselines/reference/for-of15.errors.txt | 4 +- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0d4b243c71f..9daa87daed4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5514,7 +5514,7 @@ module ts { var index = indexOf(arrayLiteral.elements, node); return getTypeOfPropertyOfContextualType(type, "" + index) || getIndexTypeOfContextualType(type, IndexKind.Number) - || (languageVersion >= ScriptTarget.ES6 ? getIteratedType(type, /*expressionForError*/ undefined) : undefined); + || (languageVersion >= ScriptTarget.ES6 ? checkIteratedType(type, /*expressionForError*/ undefined) : undefined); } return undefined; } @@ -7024,7 +7024,7 @@ module ts { return true; } - function checkReferenceExpression(n: Node, invalidReferenceMessage: DiagnosticMessage, constantVarianleMessage: DiagnosticMessage): boolean { + function checkReferenceExpression(n: Node, invalidReferenceMessage: DiagnosticMessage, constantVariableMessage: DiagnosticMessage): boolean { function findSymbol(n: Node): Symbol { var symbol = getNodeLinks(n).resolvedSymbol; // Because we got the symbol from the resolvedSymbol property, it might be of kind @@ -7091,7 +7091,7 @@ module ts { return false; } if (isConstVariableReference(n)) { - error(n, constantVarianleMessage); + error(n, constantVariableMessage); return false; } return true; @@ -7465,8 +7465,8 @@ module ts { function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { var offendingSymbolOperand = someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left : - someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? node.right : - undefined; + someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? node.right : + undefined; if (offendingSymbolOperand) { error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator)); return false; @@ -8812,15 +8812,17 @@ module ts { checkGrammarForInOrForOfStatement(node) // Check the LHS and RHS - // If decl: Check var decl, which will check the RHS - // If expr: Check LHS, check that it's a reference, and check that RHS is assignable to it, which will check RHS + // If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS + // via getTypeForVariableDeclarationInForOfStatement. + // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference. + // Then check that the RHS is assignable to it. if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { checkForInOrForOfVariableDeclaration(node); } else { var varExpr = node.initializer; var rightType = checkExpression(node.expression); - var iteratedType = getIteratedType(rightType, node.expression); + var iteratedType = checkIteratedType(rightType, node.expression); // There may be a destructuring assignment on the left side if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { @@ -8831,10 +8833,11 @@ module ts { } else { var leftType = checkExpression(varExpr); - checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); + checkReferenceExpression(varExpr, /*invalidReferenceMessage*/ Diagnostics.Invalid_left_hand_side_in_for_of_statement, + /*constantVariableMessage*/ Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant); // iteratedType will be undefined if the rightType was missing properties/signatures - // required to get it's iteratedType (like [Symbol.iterator] or next). This may be + // required to get its iteratedType (like [Symbol.iterator] or next). This may be // because we accessed properties from anyType, or it may have led to an error inside // getIteratedType. if (iteratedType) { @@ -8894,6 +8897,7 @@ module ts { function checkForInOrForOfVariableDeclaration(iterationStatement: ForInStatement | ForOfStatement): void { var variableDeclarationList = iterationStatement.initializer; + // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. if (variableDeclarationList.declarations.length >= 1) { var decl = variableDeclarationList.declarations[0]; checkVariableDeclaration(decl); @@ -8907,28 +8911,31 @@ module ts { } // iteratedType will be undefined if the for-of expression type was missing properties/signatures - // required to get it's iteratedType (like [Symbol.iterator] or next). This may be + // required to get its iteratedType (like [Symbol.iterator] or next). This may be // because we accessed properties from anyType, or it may have led to an error inside // getIteratedType. - return getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression) || anyType; + var expressionType = getTypeOfExpression(forOfStatement.expression); + return checkIteratedType(expressionType, forOfStatement.expression) || anyType; } /** * When expressionForError is undefined, it means we should not report any errors. */ - function getIteratedType(iterable: Type, expressionForError: Expression): Type { + function checkIteratedType(iterable: Type, expressionForError: Expression): Type { Debug.assert(languageVersion >= ScriptTarget.ES6); - var iteratedType = getIteratedTypeSubroutine(iterable, expressionForError); + var iteratedType = getIteratedType(iterable, expressionForError); // Now even though we have extracted the iteratedType, we will have to validate that the type // passed in is actually an Iterable. if (expressionForError && iteratedType) { - var completeIterableType = globalIterableType !== emptyObjectType ? createTypeReference(globalIterableType, [iteratedType]) : emptyObjectType; + var completeIterableType = globalIterableType !== emptyObjectType + ? createTypeReference(globalIterableType, [iteratedType]) + : emptyObjectType; checkTypeAssignableTo(iterable, completeIterableType, expressionForError); } return iteratedType; - function getIteratedTypeSubroutine(iterable: Type, expressionForError: Expression) { + function getIteratedType(iterable: Type, expressionForError: Expression) { // We want to treat type as an iterable, and get the type it is an iterable of. The iterable // must have the following structure (annotated with the names of the variables below): // @@ -8998,7 +9005,7 @@ module ts { var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value"); if (!iteratorNextValue) { if (expressionForError) { - error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property); + error(expressionForError, Diagnostics.The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property); } return undefined; } @@ -11671,17 +11678,17 @@ module ts { } if (node.initializer) { // Error on equals token which immediate precedes the initializer - return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - 1, 1, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + var equalsTokenLength = "=".length; + return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, + equalsTokenLength, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } } - else { - if (!node.initializer) { - if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { - return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer); - } - if (isConst(node)) { - return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized); - } + else if (!node.initializer) { + if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { + return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer); + } + if (isConst(node)) { + return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized); } } } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index ca826b01a19..758c3ee6ba7 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -333,7 +333,7 @@ module ts { 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_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an 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}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index efc7bb6a202..b4786bb93d7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1324,7 +1324,7 @@ "category": "Error", "code": 2489 }, - "The object returned by the next method of the iterator must have a 'value' property.": { + "The type returned by the 'next()' method of an iterator must have a 'value' property.": { "category": "Error", "code": 2490 }, diff --git a/tests/baselines/reference/for-of15.errors.txt b/tests/baselines/reference/for-of15.errors.txt index ab6b6c03ea7..20a4abe4bd0 100644 --- a/tests/baselines/reference/for-of15.errors.txt +++ b/tests/baselines/reference/for-of15.errors.txt @@ -1,11 +1,11 @@ -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(2,11): error TS2490: The type returned by the 'next()' method of an 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. +!!! error TS2490: The type returned by the 'next()' method of an iterator must have a 'value' property. class StringIterator { next() { From cb9768649655288c33a8ee1171eb392b23b93707 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Sun, 1 Mar 2015 18:16:20 -0800 Subject: [PATCH 25/26] Add tests for scoping --- tests/baselines/reference/for-of51.errors.txt | 7 +++++++ tests/baselines/reference/for-of51.js | 5 +++++ tests/baselines/reference/for-of52.errors.txt | 10 ++++++++++ tests/baselines/reference/for-of52.js | 5 +++++ tests/baselines/reference/for-of53.js | 9 +++++++++ tests/baselines/reference/for-of53.types | 8 ++++++++ tests/baselines/reference/for-of54.errors.txt | 9 +++++++++ tests/baselines/reference/for-of54.js | 9 +++++++++ tests/baselines/reference/for-of55.js | 11 +++++++++++ tests/baselines/reference/for-of55.types | 12 ++++++++++++ .../conformance/es6/for-ofStatements/for-of51.ts | 2 ++ .../conformance/es6/for-ofStatements/for-of52.ts | 2 ++ .../conformance/es6/for-ofStatements/for-of53.ts | 4 ++++ .../conformance/es6/for-ofStatements/for-of54.ts | 4 ++++ .../conformance/es6/for-ofStatements/for-of55.ts | 5 +++++ 15 files changed, 102 insertions(+) create mode 100644 tests/baselines/reference/for-of51.errors.txt create mode 100644 tests/baselines/reference/for-of51.js create mode 100644 tests/baselines/reference/for-of52.errors.txt create mode 100644 tests/baselines/reference/for-of52.js create mode 100644 tests/baselines/reference/for-of53.js create mode 100644 tests/baselines/reference/for-of53.types create mode 100644 tests/baselines/reference/for-of54.errors.txt create mode 100644 tests/baselines/reference/for-of54.js create mode 100644 tests/baselines/reference/for-of55.js create mode 100644 tests/baselines/reference/for-of55.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of51.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of52.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of53.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of54.ts create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of55.ts diff --git a/tests/baselines/reference/for-of51.errors.txt b/tests/baselines/reference/for-of51.errors.txt new file mode 100644 index 00000000000..54a6eb9d89c --- /dev/null +++ b/tests/baselines/reference/for-of51.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/es6/for-ofStatements/for-of51.ts(1,10): error TS2480: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of51.ts (1 errors) ==== + for (let let of []) {} + ~~~ +!!! error TS2480: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. \ No newline at end of file diff --git a/tests/baselines/reference/for-of51.js b/tests/baselines/reference/for-of51.js new file mode 100644 index 00000000000..cae8c8b38fe --- /dev/null +++ b/tests/baselines/reference/for-of51.js @@ -0,0 +1,5 @@ +//// [for-of51.ts] +for (let let of []) {} + +//// [for-of51.js] +for (let let of []) { } diff --git a/tests/baselines/reference/for-of52.errors.txt b/tests/baselines/reference/for-of52.errors.txt new file mode 100644 index 00000000000..5110768e104 --- /dev/null +++ b/tests/baselines/reference/for-of52.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/es6/for-ofStatements/for-of52.ts(1,11): error TS2451: Cannot redeclare block-scoped variable 'v'. +tests/cases/conformance/es6/for-ofStatements/for-of52.ts(1,14): error TS2451: Cannot redeclare block-scoped variable 'v'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of52.ts (2 errors) ==== + for (let [v, v] of [[]]) {} + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'v'. + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'v'. \ No newline at end of file diff --git a/tests/baselines/reference/for-of52.js b/tests/baselines/reference/for-of52.js new file mode 100644 index 00000000000..48e1dca936c --- /dev/null +++ b/tests/baselines/reference/for-of52.js @@ -0,0 +1,5 @@ +//// [for-of52.ts] +for (let [v, v] of [[]]) {} + +//// [for-of52.js] +for (let [v, v] of [[]]) { } diff --git a/tests/baselines/reference/for-of53.js b/tests/baselines/reference/for-of53.js new file mode 100644 index 00000000000..810d23644a6 --- /dev/null +++ b/tests/baselines/reference/for-of53.js @@ -0,0 +1,9 @@ +//// [for-of53.ts] +for (let v of []) { + var v; +} + +//// [for-of53.js] +for (let v of []) { + var v; +} diff --git a/tests/baselines/reference/for-of53.types b/tests/baselines/reference/for-of53.types new file mode 100644 index 00000000000..475d63e9b5a --- /dev/null +++ b/tests/baselines/reference/for-of53.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of53.ts === +for (let v of []) { +>v : any +>[] : undefined[] + + var v; +>v : any +} diff --git a/tests/baselines/reference/for-of54.errors.txt b/tests/baselines/reference/for-of54.errors.txt new file mode 100644 index 00000000000..cb040c44382 --- /dev/null +++ b/tests/baselines/reference/for-of54.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/es6/for-ofStatements/for-of54.ts(2,9): error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + + +==== tests/cases/conformance/es6/for-ofStatements/for-of54.ts (1 errors) ==== + for (let v of []) { + var v = 0; + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + } \ No newline at end of file diff --git a/tests/baselines/reference/for-of54.js b/tests/baselines/reference/for-of54.js new file mode 100644 index 00000000000..442e6e86146 --- /dev/null +++ b/tests/baselines/reference/for-of54.js @@ -0,0 +1,9 @@ +//// [for-of54.ts] +for (let v of []) { + var v = 0; +} + +//// [for-of54.js] +for (let v of []) { + var v = 0; +} diff --git a/tests/baselines/reference/for-of55.js b/tests/baselines/reference/for-of55.js new file mode 100644 index 00000000000..a0f949c6ce5 --- /dev/null +++ b/tests/baselines/reference/for-of55.js @@ -0,0 +1,11 @@ +//// [for-of55.ts] +let v = [1]; +for (let v of v) { + v; +} + +//// [for-of55.js] +let v = [1]; +for (let v of v) { + v; +} diff --git a/tests/baselines/reference/for-of55.types b/tests/baselines/reference/for-of55.types new file mode 100644 index 00000000000..b0f5aab3fee --- /dev/null +++ b/tests/baselines/reference/for-of55.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of55.ts === +let v = [1]; +>v : number[] +>[1] : number[] + +for (let v of v) { +>v : any +>v : any + + v; +>v : any +} diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of51.ts b/tests/cases/conformance/es6/for-ofStatements/for-of51.ts new file mode 100644 index 00000000000..a97b05d7fe9 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of51.ts @@ -0,0 +1,2 @@ +//@target: ES6 +for (let let of []) {} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of52.ts b/tests/cases/conformance/es6/for-ofStatements/for-of52.ts new file mode 100644 index 00000000000..80cc680060d --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of52.ts @@ -0,0 +1,2 @@ +//@target: ES6 +for (let [v, v] of [[]]) {} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of53.ts b/tests/cases/conformance/es6/for-ofStatements/for-of53.ts new file mode 100644 index 00000000000..34db2bab704 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of53.ts @@ -0,0 +1,4 @@ +//@target: ES6 +for (let v of []) { + var v; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of54.ts b/tests/cases/conformance/es6/for-ofStatements/for-of54.ts new file mode 100644 index 00000000000..6cf79ae0945 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of54.ts @@ -0,0 +1,4 @@ +//@target: ES6 +for (let v of []) { + var v = 0; +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of55.ts b/tests/cases/conformance/es6/for-ofStatements/for-of55.ts new file mode 100644 index 00000000000..e1d16a3e068 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of55.ts @@ -0,0 +1,5 @@ +//@target: ES6 +let v = [1]; +for (let v of v) { + v; +} \ No newline at end of file From 7dd7b4344813003f86b99b1bdc89e2e8fd770f1a Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 2 Mar 2015 13:53:59 -0800 Subject: [PATCH 26/26] Add one more test --- tests/baselines/reference/for-of56.js | 5 +++++ tests/baselines/reference/for-of56.types | 5 +++++ tests/cases/conformance/es6/for-ofStatements/for-of56.ts | 2 ++ 3 files changed, 12 insertions(+) create mode 100644 tests/baselines/reference/for-of56.js create mode 100644 tests/baselines/reference/for-of56.types create mode 100644 tests/cases/conformance/es6/for-ofStatements/for-of56.ts diff --git a/tests/baselines/reference/for-of56.js b/tests/baselines/reference/for-of56.js new file mode 100644 index 00000000000..0992b9c0bb9 --- /dev/null +++ b/tests/baselines/reference/for-of56.js @@ -0,0 +1,5 @@ +//// [for-of56.ts] +for (var let of []) {} + +//// [for-of56.js] +for (var let of []) { } diff --git a/tests/baselines/reference/for-of56.types b/tests/baselines/reference/for-of56.types new file mode 100644 index 00000000000..d853ff9f62c --- /dev/null +++ b/tests/baselines/reference/for-of56.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/es6/for-ofStatements/for-of56.ts === +for (var let of []) {} +>let : any +>[] : undefined[] + diff --git a/tests/cases/conformance/es6/for-ofStatements/for-of56.ts b/tests/cases/conformance/es6/for-ofStatements/for-of56.ts new file mode 100644 index 00000000000..3b73a529425 --- /dev/null +++ b/tests/cases/conformance/es6/for-ofStatements/for-of56.ts @@ -0,0 +1,2 @@ +//@target: ES6 +for (var let of []) {} \ No newline at end of file